def scale(self, fieldname=None, scale=None, height=None, width=None, direction='thumbnail', **parameters): # import pdb # pdb.set_trace() if fieldname is None: fieldname = IPrimaryFieldInfo(self.context).fieldname if scale is not None: available = self.getAvailableSizes(fieldname) if not scale in available: return None width, height = available[scale] if self.request is not None: alsoProvides(self.request, IDisableCSRFProtection) storage = AnnotationStorage(self.context, self.modified) info = storage.scale(factory=self.create, fieldname=fieldname, height=height, width=width, direction=direction, **parameters) if info is not None: info['fieldname'] = fieldname scale_view = ImageScale(self.context, self.request, **info) return scale_view.__of__(self.context)
def save_cropped( self, fieldname, field, scale, image_file, interface=None): """ see interface """ handler = IImageScaleHandler(field) sizes = field.getAvailableSizes(self.context) w, h = sizes[scale] data = handler.createScale( self.context, scale, w, h, data=image_file.read()) # store scale for classic <fieldname>_<scale> traversing handler.storeScale(self.context, scale, **data) # call plone.scale.storage.scale method in order to # provide saved scale for plone.app.imaging @@images view def crop_factory(fieldname, direction='keep', **parameters): blob = Blob() result = blob.open('w') _, image_format, dimensions = scaleImage( data['data'], result=result, **parameters) result.close() return blob, image_format, dimensions # call storage with actual time in milliseconds # this always invalidates old scales storage = AnnotationStorage(self.context, self.now_millis) storage.scale( factory=crop_factory, fieldname=field.__name__, width=w, height=h)
def publishTraverse(self, request, name): """ used for traversal via publisher, i.e. when using as a url """ stack = request.get('TraversalRequestNameStack') image = None if stack and stack[-1] not in self._ignored_stacks: # field and scale name were given... scale = stack.pop() image = self.scale(name, scale) # this is aq-wrapped elif '-' in name: # we got a uid... if '.' in name: name, ext = name.rsplit('.', 1) storage = AnnotationStorage(self.context) info = storage.get(name) if info is not None: scale_view = ImageScale(self.context, self.request, **info) alsoProvides(scale_view, IStableImageScale) return scale_view.__of__(self.context) else: # otherwise `name` must refer to a field... if '.' in name: name, ext = name.rsplit('.', 1) value = getattr(self.context, name) scale_view = ImageScale(self.context, self.request, data=value, fieldname=name) return scale_view.__of__(self.context) if image is not None: return image raise NotFound(self, name, self.request)
def storage(self): from plone.scale.storage import AnnotationStorage storage = AnnotationStorage(None) storage.modified = lambda: 42 storage.storage = {} return storage
def publishTraverse(self, request, name): """ used for traversal via publisher, i.e. when using as a url """ stack = request.get('TraversalRequestNameStack') image = None if stack and stack[-1] not in self._ignored_stacks: # field and scale name were given... scale = stack.pop() image = self.scale(name, scale) # this is aq-wrapped elif '-' in name: # we got a uid... if '.' in name: name, ext = name.rsplit('.', 1) storage = AnnotationStorage(self.context) info = storage.get(name) if info is not None: scale_view = ImageScale(self.context, self.request, **info) alsoProvides(scale_view, IStableImageScale) return scale_view.__of__(self.context) else: # otherwise `name` must refer to a field... if '.' in name: name, ext = name.rsplit('.', 1) value = getattr(self.context, name) scale_view = ImageScale( self.context, self.request, data=value, fieldname=name) return scale_view.__of__(self.context) if image is not None: return image raise NotFound(self, name, self.request)
def publishTraverse(self, request, name): """ used for traversal via publisher, i.e. when using as a url """ stack = request.get('TraversalRequestNameStack') if stack and stack[-1] not in self._ignored_stacks: # field and scale name were given... scale = stack.pop() image = self.scale(name, scale) # this is aq-wrapped elif '.' in name: # we got a uid... uid, ext = name.rsplit('.', 1) storage = AnnotationStorage(self.context) info = storage.get(uid) image = None if info is not None: image = self.make(info).__of__(self.context) alsoProvides(image, IStableImageScale) else: # otherwise `name` must refer to a field... scale_view = self.get_image_scale_view() if not scale_view: raise NotFound(self, name, self.request) return scale_view.scale() if image is not None: return image raise NotFound(self, name, self.request)
def scale(self, fieldname=None, scale=None, height=None, width=None, direction='thumbnail', **parameters): if fieldname is None: fieldname = IPrimaryFieldInfo(self.context).fieldname if scale is not None: available = self.getAvailableSizes(fieldname) if scale not in available: return None width, height = available[scale] if IDisableCSRFProtection and self.request is not None: alsoProvides(self.request, IDisableCSRFProtection) storage = AnnotationStorage(self.context, self.modified) info = storage.scale(factory=self.create, fieldname=fieldname, height=height, width=width, direction=direction, **parameters) if info is not None: info['fieldname'] = fieldname scale_view = ImageScale(self.context, self.request, **info) return scale_view.__of__(self.context)
def save_cropped(self, fieldname, scale, image_file): """ see interface """ field = self.get_image_field(fieldname) handler = IImageScaleHandler(field) sizes = field.getAvailableSizes(self.context) w, h = sizes[scale] data = handler.createScale(self.context, scale, w, h, data=image_file.read()) # store scale for classic <fieldname>_<scale> traversing handler.storeScale(self.context, scale, **data) # call plone.scale.storage.scale method in order to # provide saved scale for plone.app.imaging @@images view def crop_factory(fieldname, direction="keep", **parameters): blob = Blob() result = blob.open("w") _, image_format, dimensions = scaleImage(data["data"], result=result, **parameters) result.close() return blob, image_format, dimensions # Avoid browser cache # calling reindexObject updates the modified metadate too self.context.reindexObject() # call storage with actual time in milliseconds # this always invalidates old scales storage = AnnotationStorage(self.context, _millis) storage.scale(factory=crop_factory, fieldname=field.__name__, width=w, height=h)
def _crop(self, fieldname, scale, box, interface=None): """interface just useful to locate field on dexterity types """ # https://github.com/plone/plone.app.imaging/blob/ggozad-cropping/src/ # plone/app/imaging/cropping.py field = self.context.getField(fieldname) if hasattr(field,'getHandler'): handler = field.getHandler() else: handler = IImageScaleHandler(field) # TODO this is archetype only value = field.get(self.context) data = getattr(aq_base(value), 'data', value) if isinstance(data, Pdata): data = str(data) original_file = StringIO(data) image = PIL.Image.open(original_file) image_format = image.format or self.DEFAULT_FORMAT cropped_image = image.crop(box) cropped_image_file = StringIO() cropped_image.save(cropped_image_file, image_format, quality=100) cropped_image_file.seek(0) sizes = field.getAvailableSizes(self.context) #regular scale if len(sizes[scale]) ==3: w, h, s = sizes[scale] data = handler.createScale(self.context, scale, w, h, data=cropped_image_file.read()) else: w, h = sizes[scale] data = handler.createScale(self.context, scale, w, h, data=cropped_image_file.read()) # store scale for classic <fieldname>_<scale> traversing handler.storeScale(self.context, scale, **data) # call plone.scale.storage.scale method in order to # provide saved scale for plone.app.imaging @@images view def crop_factory(fieldname, direction='keep', **parameters): blob = Blob() result = blob.open('w') _, image_format, dimensions = scaleImage(data['data'], result=result, **parameters) result.close() return blob, image_format, dimensions # call storage with actual time in milliseconds # this always invalidates old scales storage = AnnotationStorage(self.context, self.now_millis) storage.scale(factory=crop_factory, fieldname=fieldname, width=w, height=h) # store crop information in annotations self._store(fieldname, scale, box)
def _invalidate_scale(self, fieldname, scale): # Call storage with actual time in milliseconds. # This always invalidates old scales scale_storage = AnnotationStorage(self.context, int(time.time())) # holzhammermethode uids = scale_storage.keys() for uid in uids: del scale_storage[uid]
def getInfo(self, fieldname=None, scale=None, height=None, width=None, **parameters): storage = AnnotationStorage(self.context, self.modified) return storage.scale( factory=self.create, fieldname=fieldname, height=height, width=width, **parameters)
def _invalidate_scale(self, fieldname, scale): # Call storage with actual time in milliseconds. # This always invalidates old scales scale_storage = AnnotationStorage( self.context, int(time.time()) ) # holzhammermethode uids = list(scale_storage.keys()) for uid in uids: del scale_storage[uid]
def scale( self, fieldname=None, scale=None, height=None, width=None, direction="thumbnail", **parameters ): if fieldname is None: primary_field = IPrimaryFieldInfo(self.context, None) if primary_field is None: return # 404 fieldname = primary_field.fieldname if scale is not None: if width is not None or height is not None: logger.warn( "A scale name and width/heigth are given. Those are" "mutually exclusive: solved by ignoring width/heigth and " "taking name", ) available = self.available_sizes if scale not in available: return None # 404 width, height = available[scale] if IDisableCSRFProtection and self.request is not None: alsoProvides(self.request, IDisableCSRFProtection) storage = AnnotationStorage( self.context, functools.partial(self.modified, fieldname) ) info = storage.scale( fieldname=fieldname, height=height, width=width, direction=direction, scale=scale, **parameters ) if info is None: return # 404 info["srcset"] = self.calculate_srcset( fieldname=fieldname, height=height, width=width, direction=direction, scale=scale, storage=storage, **parameters ) info["fieldname"] = fieldname scale_view = self._scale_view_class(self.context, self.request, **info) return scale_view
def scale(self, fieldname=None, scale=None, height=None, width=None, **parameters): if scale is not None: available = self.getAvailableSizes(fieldname) if not scale in available: return None width, height = available[scale] if width is None and height is None: field = self.field(fieldname) return field.get(self.context) storage = AnnotationStorage(self.context, self.modified) info = storage.scale(factory=self.create, fieldname=fieldname, height=height, width=width, **parameters) if info is not None: return self.make(info).__of__(self.context)
def scale(self, fieldname=None, scale=None, height=None, width=None, **parameters): if fieldname is None: fieldname = IPrimaryFieldInfo(self.context).fieldname if scale is not None: available = self.getAvailableSizes(fieldname) if not scale in available: return None width, height = available[scale] storage = AnnotationStorage(self.context, self.modified) info = storage.scale(factory=self.create, fieldname=fieldname, height=height, width=width, **parameters) if info is not None: info['fieldname'] = fieldname scale_view = ImageScale(self.context, self.request, **info) return scale_view.__of__(self.context)
def save_cropped(self, fieldname, scale, image_file): """ see interface """ sizes = getAllowedSizes() w, h = sizes[scale] def crop_factory(fieldname, **parameters): # LMU patch: remove the scale parameter _parameters = { key: value for key, value in parameters.iteritems() if key != 'scale' } result = scaleImage(image_file.read(), **_parameters) if result is not None: data, format, dimensions = result mimetype = 'image/{0:s}'.format(format.lower()) field = self.get_image_field(fieldname) value = field.__class__(data, contentType=mimetype, filename=field.filename) value.fieldname = fieldname return value, format, dimensions # call storage with actual time in milliseconds # this always invalidates old scales storage = AnnotationStorage(self.context, _millis) # We need to pass direction='thumbnail' since this is the default # used by plone.namedfile.scaling, also for retrieval of scales. # Otherwise the key under which the scaled and cropped image is # saved in plone.scale.storage.AnnotationStorage will not match the # key used for retrieval (= the cropped scaled image will not be # found) # LMU patch: add the scale parameter storage.scale( factory=crop_factory, direction='thumbnail', fieldname=fieldname, scale=scale, width=w, height=h, )
def populate_with_object(self, obj): # check permissions super(ImageTile, self).populate_with_object(obj) data = {} obj = aq_inner(obj) try: scales = queryMultiAdapter((obj, self.request), name="images") data['image'] = NamedImageFile(str(scales.scale('image').data)) except AttributeError: pass data_mgr = ITileDataManager(self) data_mgr.set(data) tile_storage = AnnotationStorage(self) obj_storage = BaseAnnotationStorage(obj) for k, v in obj_storage.items(): tile_storage.storage[k] = v tile_storage.storage[k]['modified'] = '%f' % time.time() scale_data = obj_storage.storage[k]['data'].open().read() tile_storage.storage[k]['data'] = NamedImageFile(str(scale_data))
def _remove(self, fieldname, scale): # remove info from annotation key = "%s_%s" % (fieldname, scale) if key in self._storage.keys(): del self._storage[key] # remove saved scale scale_storage = AnnotationStorage(self.context) image_scales = self.context.restrictedTraverse("@@images") image_scale = image_scales.scale(fieldname, scale=scale) del scale_storage[image_scale.uid]
def scale( self, fieldname=None, scale=None, height=None, width=None, direction='thumbnail', **parameters ): if fieldname is None: primary_field = IPrimaryFieldInfo(self.context, None) if primary_field is None: return # 404 fieldname = primary_field.fieldname if scale is not None: if width is not None or height is not None: logger.warn( 'A scale name and width/heigth are given. Those are' 'mutually exclusive: solved by ignoring width/heigth and ' 'taking name' ) available = self.available_sizes if scale not in available: return None # 404 width, height = available[scale] if IDisableCSRFProtection and self.request is not None: alsoProvides(self.request, IDisableCSRFProtection) storage = AnnotationStorage(self.context, self.modified) info = storage.scale( fieldname=fieldname, height=height, width=width, direction=direction, scale=scale, **parameters ) if info is None: return # 404 info['fieldname'] = fieldname scale_view = ImageScale(self.context, self.request, **info) return scale_view.__of__(self.context)
def publishTraverse(self, request, name): """ used for traversal via publisher, i.e. when using as a url """ stack = request.get('TraversalRequestNameStack') if stack: # field and scale name were given... scale = stack.pop() image = self.scale(name, scale) # this is aq-wrapped elif '.' in name: # we got a uid... uid, ext = name.rsplit('.', 1) storage = AnnotationStorage(self.context) info = storage.get(uid) image = None if info is not None: image = self.make(info).__of__(self.context) else: # otherwise `name` must refer to a field... field = self.field(name) image = field.get(self.context) # this is aq-wrapped if image is not None: return image raise NotFound(self, name, self.request)
def save_cropped(self, fieldname, scale, image_file): """ see interface """ field = self.get_image_field(fieldname) handler = IImageScaleHandler(field) sizes = field.getAvailableSizes(self.context) w, h = sizes[scale] data = handler.createScale(self.context, scale, w, h, data=image_file.read()) # store scale for classic <fieldname>_<scale> traversing handler.storeScale(self.context, scale, **data) # call plone.scale.storage.scale method in order to # provide saved scale for plone.app.imaging @@images view def crop_factory(fieldname, direction='keep', **parameters): blob = Blob() result = blob.open('w') _, image_format, dimensions = scaleImage(data['data'], result=result, **parameters) result.close() return blob, image_format, dimensions # Avoid browser cache # calling reindexObject updates the modified metadate too self.context.reindexObject() # call storage with actual time in milliseconds # this always invalidates old scales storage = AnnotationStorage(self.context, _millis) storage.scale(factory=crop_factory, fieldname=field.__name__, width=w, height=h)
def __call__(self): form = self.request.form size = form.get('size', form.get('s', None)) if size is None: # return original - no scaling required return self.context.index_html(self.request, self.request.RESPONSE) else: size = int(size) if not IAttributeAnnotatable.providedBy(self.context): alsoProvides(self.context, IAttributeAnnotatable) storage = AnnotationStorage(self.context) scale = storage.scale(self.scale_factory, width=size, height=size) response = self.request.RESPONSE response.setHeader('Last-Modified', rfc1123_date(scale['modified'])) response.setHeader('Content-Type', scale['mimetype']) response.setHeader('Content-Length', len(scale['data'])) response.setHeader('Accept-Ranges', 'bytes') return scale['data']
def save_cropped( self, fieldname, field, scale, image_file, interface=None): """ see interface """ sizes = getAllowedSizes() w, h = sizes[scale] def crop_factory(fieldname, **parameters): result = scaleImage(image_file.read(), **parameters) if result is not None: data, format, dimensions = result mimetype = 'image/%s' % format.lower() value = field.__class__( data, contentType=mimetype, filename=field.filename ) value.fieldname = fieldname return value, format, dimensions # call storage with actual time in milliseconds # this always invalidates old scales storage = AnnotationStorage(self.context, self.now_millis) # We need to pass direction='thumbnail' since this is the default # used by plone.namedfile.scaling, also for retrieval of scales. # Otherwise the key under which the scaled and cropped image is # saved in plone.scale.storage.AnnotationStorage will not match the # key used for retrieval (= the cropped scaled image will not be # found) storage.scale( factory=crop_factory, direction='thumbnail', fieldname=fieldname, width=w, height=h, )
def CopyToClient(survey, preview=False): """Copy the survey to the online client part of the site. :param survey: the survey to copy :param bool preview: indicates if this is a preview or a normal publication :rtype: :py:class:`euphorie.content.survey.Survey` The public area is hardcoded to be a container with id ``client`` within the site root. The ''id'' and ''title'' of the survey group will be used for the published survey. If another object with the same ''id'' already exists it will be removed first. Any missing country and sector folders are created if needed. If this is a preview (as indicated by the ``preview`` parameter) the id of the survey will be set to ``preview``, guaranteeing that an existing published survey will not be replaced. This also means only a sector can only have one preview online. This method assumes the current user has permissions to create content in the online client. This is normally done by using the :py:func:`PublishToClient` function which switches the current user for the copy operation. Returns the new public survey instance. """ # This is based on OFS.CopyContainer.manage_clone, modified to # use the sector id and title, skip security checks and remove # an existing object with the same id. client = getPortal(survey).client source = aq_inner(survey) surveygroup = aq_parent(source) sector = aq_parent(surveygroup) country = aq_parent(sector) from euphorie.content.sector import ISector assert ISector.providedBy(sector) if country.id not in client: client.invokeFactory("euphorie.clientcountry", country.id, title=country.title, country_type=country.country_type) cl_country = client[country.id] if sector.id not in cl_country: cl_country.invokeFactory("euphorie.clientsector", sector.id) target = cl_country[sector.id] target.title = sector.title target.logo = sector.logo # Clear any scaled logos AnnotationStorage(target).storage.clear() target.main_background_colour = getattr(sector, "main_colour", None) if target.main_background_colour: target.main_foreground_colour = utils.MatchColour( target.main_background_colour, 0.0, 0.6, 0.3) target.main_background_bright = \ utils.IsBright(target.main_background_colour) target.support_background_colour = getattr(sector, "support_colour", None) if target.support_background_colour: target.support_foreground_colour = \ utils.MatchColour(target.support_background_colour) target.support_background_bright = \ utils.IsBright(target.support_background_colour) copy = source._getCopy(target) if preview: copy.id = "preview" else: copy.id = surveygroup.id copy.title = surveygroup.title copy.obsolete = surveygroup.obsolete copy.evaluation_algorithm = surveygroup.evaluation_algorithm copy.version = source.id copy.published = datetime.datetime.now() copy.preview = preview if copy.id in target: # We must suppress events to prevent the can-not-delete-published- # content check from blocking us. # XXX: We need however the ObjectWillBeRemovedEvent event to be called # otherwise the removed objects are not uncatalogged. to_delete = target._getOb(copy.id) notify(ObjectWillBeRemovedEvent(to_delete, target, copy.id)) target._delObject(copy.id, suppress_events=True) target._setObject(copy.id, copy, suppress_events=True) copy = target[copy.id] copy._postCopy(target, op=0) notify(ObjectPublishedEvent(source)) return copy
def _deploy_resources(self, urls, base_path): """ Deploy resources linked in HTML or CSS. """ portal_url = getToolByName(self.context, "portal_url")() for url in urls: url = url.strip() scheme, netloc, path, query, fragment = urlsplit(url) if not path: ## internal anchor continue if netloc and netloc != portal_url: ## external link continue elif path.startswith("image/svg+xml;base64") or path.startswith("image/png;base64"): ## images defined in css continue if path.startswith("/"): objpath = path[1:] else: objpath = os.path.join(base_path, path) if isinstance(objpath, unicode): objpath = objpath.encode("utf-8") # PloneSite with id 'plone' case problems during # restrictedTraverse() so we cut it objpath_spl = objpath.split("/", 1) if objpath_spl[0] == "plone" and len(objpath_spl) > 1: objpath = objpath_spl[1] # fix "../" in paths objpath = os.path.normpath(objpath).replace("%20", " ") if objpath in self.deployed_resources: continue obj = self.context.unrestrictedTraverse(objpath, None) if objpath.rsplit("/", 1)[-1].split(".")[0] == "image": obj = self.context.restrictedTraverse(objpath.rsplit(".", 1)[0], None) if not obj: obj = self.context.restrictedTraverse(unquote(objpath), None) if not obj: parent_obj = self.context.restrictedTraverse(unquote(objpath.rsplit("/", 1)[0]), None) if parent_obj: image_name = objpath.rsplit("/", 1)[-1] if hasattr(parent_obj, "schema"): for field in parent_obj.schema.fields(): fieldname = field.getName() if image_name.startswith(fieldname): scalename = image_name[len(fieldname) + 1 :] obj = field.getScale(parent_obj, scalename) objpath = os.path.join(objpath, "image.jpg") break else: # didn't find it, just go for field name now... # could be added with archetypes.schemaextender parts = image_name.split("_") fieldname = parts[0] field = parent_obj.getField(fieldname) if field and len(parts) == 2: scalename = parts[1] obj = field.getScale(parent_obj, scalename) objpath = os.path.join(objpath, "image.jpg") add_path = True if not obj: if "/@@images/" in objpath: parent_path, image_name = objpath.split("/@@images/") parent_obj = self.context.unrestrictedTraverse(unquote(parent_path), None) if parent_obj: spl_img_name = image_name.split("/") if len(spl_img_name) == 1: # no scalename in path fieldname = spl_img_name[0] scalename = None objpath = "/".join((parent_path, "image.jpg")) else: fieldname, scalename = spl_img_name objpath = os.path.join(parent_path, "_".join((fieldname, scalename)), "image.jpg") try: images_view = getMultiAdapter((parent_obj, self.request), name="images") field = images_view.field(fieldname) if field: obj = field.getScale(parent_obj, scalename) else: # need to try and get it from the uid uid, ext = fieldname.rsplit(".", 1) from plone.scale.storage import AnnotationStorage storage = AnnotationStorage(parent_obj) info = storage.get(uid) if info is not None: obj = images_view.make(info).__of__(parent_obj) # using the exported scale now instead objpath = "/".join((parent_path, fieldname)) add_path = False except ComponentLookupError: pass if not obj: log.warning("Unable to deploy resource '%s'!" % objpath) continue if ( isinstance(obj, ATImage) or hasattr(obj, "getBlobWrapper") and "image" in obj.getBlobWrapper().getContentType() and add_path ): # create path to dump ATImage in original size if objpath.rsplit(".", 1)[-1] in ("png", "jpg", "gif", "jpeg"): objpath = os.path.join(objpath, "image.%s" % (objpath.rsplit(".", 1)[-1])) else: objpath = os.path.join(objpath, "image.jpg") try: content = self._render_obj(obj) except AttributeError: # XXX this can happen with CachedResource? # can't figure out how but let's not error if so... log.warning("Unable to deploy resource '%s'!" % objpath) continue if content is None: continue if ( isinstance(obj, (FSImage, OFSImage, ATImage)) or hasattr(obj, "getBlobWrapper") and "image" in obj.getBlobWrapper().getContentType() ): objpath, content = self._apply_image_transforms(objpath, content) self._write(objpath, content) self.deployed_resources.append(objpath)
def storage(self): from plone.scale.storage import AnnotationStorage storage = AnnotationStorage(_DummyContext()) storage.modified = lambda: 42 storage.storage = {} return storage
def save_images(self, context): """Save images from ZODB to temp directory """ portal = getSite() portal_url = portal.absolute_url() if not portal_url.endswith('/'): portal_url += '/' portal_path = '/'.join(portal.getPhysicalPath()) reference_tool = getToolByName(portal, 'reference_catalog') mtool = getToolByName(portal, 'portal_membership') for filename, image in self.images: size = None # Traverse methods mess with unicode if type(image) is unicode: image = str(image) path = image.replace(portal_url, '') item = None # using uid if 'resolveuid' in image: # uid is the traversed value coming after "resolveuid/" resolveuidpath = image.split('/') resolveuid_idx = resolveuidpath.index('resolveuid') try: uuid = resolveuidpath[resolveuid_idx + 1] except IndexError: logger.error("Failed to get image uid from %s", image) continue item = reference_tool.lookupObject(uuid) if len(resolveuidpath) >= resolveuid_idx + 2: size = resolveuidpath[resolveuid_idx + 2] logger.debug("Get image from uid %s", uuid) if not item: # relative url try: item = context.restrictedTraverse(image) logger.debug("Get image from context") except Unauthorized: logger.warning( "Unauthorized to get image from context path %s", item) except: logger.debug("Failed to get image from context path %s", image) if not item: # plone.app.imaging if '@@images' in path and AnnotationStorage: context_path, images_str, uid_filename = path.rsplit( '/', 2) image_context = portal.restrictedTraverse(context_path) uid, ext = uid_filename.rsplit('.', 1) storage = AnnotationStorage(image_context) info = storage.get(uid) if info is not None: request = TestRequest() scale_view = ImageScale(image_context, request, **info) item = scale_view.__of__(image_context) if not item: # absolute url image_path = '/'.join((portal_path, path)) try: item = portal.restrictedTraverse(image_path) logger.debug("Get image from portal") except Unauthorized: logger.warning("Unauthorized to get from context path %s", image_path) except: logger.error("Failed to get image from portal path %s", image_path) continue if not mtool.checkPermission('View', item): logger.warning("Unauthorized to get image %s", item) continue if item and size: try: item = item.restrictedTraverse(size) except Unauthorized: logger.warning("Unauthorized to get size %s from image %s", size, image) except: logger.error("Failed to get size %s from image %s", size, image) pass # Eek, we should put an adapter for various image providers (overkill ?). data = get_image_data(item) if data: _write_file(data, self.fsinfo, filename) return
for site in plones: print('') print('Handling Plone Site %s.' % site.id) setSite(site) catalog = getToolByName(site, 'portal_catalog') count = 0 purged = 0 for brain in catalog(): try: obj = brain.getObject() except: continue savepoint = transaction.savepoint() ann = AnnotationStorage(obj) try: ann.storage except TypeError: # This happens when the context cannot be annotated, for # example for a plone.app.discussion comment. continue # We want to remove all scales that are X days older than the # last modification date of the object. final_date = obj.modified() - DAYS changed = False for key, value in ann.items(): if value['modified'] < final_date.millis(): # This may easily give an error, as it tries to remove # two keys: del ann[key] del ann.storage[key]
def object_modified_or_deleted(obj, event): storage = AnnotationStorage(obj) storage.clear()
def save_images(self, context): """Save images from ZODB to temp directory """ portal = getSite() portal_url = portal.absolute_url() if not portal_url.endswith('/'): portal_url += '/' portal_path = '/'.join(portal.getPhysicalPath()) reference_tool = getToolByName(portal, 'reference_catalog') mtool = getToolByName(portal, 'portal_membership') for filename, image in self.images: size = None # Traverse methods mess with unicode if type(image) is unicode: image = str(image) path = image.replace(portal_url, '') item = None # using uid if 'resolveuid' in image: # uid is the traversed value coming after "resolveuid/" resolveuidpath = image.split('/') resolveuid_idx = resolveuidpath.index('resolveuid') try: uuid = resolveuidpath[resolveuid_idx + 1] except IndexError: logger.error("Failed to get image uid from %s", image) continue item = reference_tool.lookupObject(uuid) if len(resolveuidpath) >= resolveuid_idx + 2: size = resolveuidpath[resolveuid_idx + 2] logger.debug("Get image from uid %s", uuid) if not item: # relative url try: item = context.restrictedTraverse(image) logger.debug("Get image from context") except Unauthorized: logger.warning("Unauthorized to get image from context path %s", item) except: logger.debug("Failed to get image from context path %s", image) if not item: # plone.app.imaging if '@@images' in path and AnnotationStorage: context_path, images_str, uid_filename = path.rsplit('/', 2) image_context = portal.restrictedTraverse(context_path) uid, ext = uid_filename.rsplit('.', 1) storage = AnnotationStorage(image_context) info = storage.get(uid) if info is not None: request = TestRequest() scale_view = ImageScale(image_context, request, **info) item = scale_view.__of__(image_context) if not item: # absolute url image_path = '/'.join((portal_path, path)) try: item = portal.restrictedTraverse(image_path) logger.debug("Get image from portal") except Unauthorized: logger.warning("Unauthorized to get from context path %s", image_path) except: logger.error("Failed to get image from portal path %s", image_path) continue if not mtool.checkPermission('View', item): logger.warning("Unauthorized to get image %s", item) continue if item and size: try: item = item.restrictedTraverse(size) except Unauthorized: logger.warning("Unauthorized to get size %s from image %s", size, image) except: logger.error("Failed to get size %s from image %s", size, image) pass # Eek, we should put an adapter for various image providers (overkill ?). data = get_image_data(item) if data: _write_file(data, self.fsinfo, filename) return
def storage(self): from plone.scale.storage import AnnotationStorage provideAdapter(zope.annotation.attribute.AttributeAnnotations) storage = AnnotationStorage(_DummyContext()) storage.modified = lambda: 42 return storage
def reset_scales(app, args): parser = argparse.ArgumentParser( description='Reset all scales in the application') parser.add_argument('--site', help='Add the site id', required=True) parser.add_argument( '--regenerate', help='Scale(s) you want to regnerate, multiple allowed', action='append') parser.add_argument('-c', help='stupid bug') args = parser.parse_args(args) site_name = args.site root = makerequest.makerequest(app) site = root.get(site_name, None) logger = getLogger(__name__) log = mklog(root.REQUEST) if site is None: msg = "No site called `%s` found in the database." % site_name log(msg) logger.info(msg) sys.exit(1) # Set up local site manager setHooks() setSite(site) # Set up security uf = app.acl_users user = uf.getUserById("admin") newSecurityManager(None, user) catalog = site.portal_catalog log('resetting all scales from %r:' % site) real = timer() # real time lap = timer() # real lap time (for intermediate commits) cpu = timer(clock) # cpu time processed = 0 def checkPoint(): msg = 'intermediate commit '\ '(%d objects processed, last batch in %s)...' log(msg % (processed, lap.next())) trx = get() trx.note(u'migrated %d btree-folders' % processed) trx.savepoint() cpi = checkpointIterator(checkPoint, 1000) for item in catalog(object_provides=IDexterityItem.__identifier__): o = item.getObject() storage = AnnotationStorage(o) storage.clear() msg = "Cleared storage for %s" % (item.getURL()) log(msg) try: if args.regenerate is not None: for scale in args.regenerate: if hasattr(o, 'image'): scaler = o.unrestrictedTraverse('@@images') if scaler.scale(fieldname='image', scale=scale) is not None: log("regenerated scale %s" % (scale)) else: log("error regenerating scale %s" % (scale)) except AttributeError: continue except IOError: continue processed += 1 cpi.next() checkPoint() msg = 'processed %d object(s) in %s (%s cpu time).' msg = msg % (processed, real.next(), cpu.next()) log(msg) logger.info(msg) transaction.commit()
for site in plones: print('') print('Handling Plone Site %s.' % site.id) setSite(site) catalog = getToolByName(site, 'portal_catalog') count = 0 purged = 0 for brain in catalog.unrestrictedSearchResults(): try: obj = brain.getObject() except: continue savepoint = transaction.savepoint() ann = AnnotationStorage(obj) try: ann.storage except TypeError: # This happens when the context cannot be annotated, for # example for a plone.app.discussion comment. continue # We want to remove all scales that are X days older than the # last modification date of the object. final_date = obj.modified() - DAYS changed = False for key, value in ann.items(): if value['modified'] < final_date.millis(): # This may easily give an error, as it tries to remove # two keys: del ann[key] del ann.storage[key]