private function encode(EventAdapterInterface $ea, $object, $config)
 {
     $om = $ea->getObjectManager();
     $meta = $om->getClassMetadata(get_class($object));
     $uow = $om->getUnitOfWork();
     foreach ($config['encode'] as $field => $options) {
         $value = $meta->getReflectionProperty($field)->getValue($object);
         $method = $options['type'];
         $encoded = $method($options['secret'] . $value);
         $meta->getReflectionProperty($field)->setValue($object, $encoded);
     }
     // recalculate changeset
     $ea->recomputeSingleObjectChangeSet($uow, $meta, $object);
 }
 /**
  * {@inheritdoc}
  */
 protected function releaseTreeLocks(ObjectManager $om, AdapterInterface $ea)
 {
     $uow = $om->getUnitOfWork();
     foreach ($this->rootsOfTreesWhichNeedsLocking as $oid => $root) {
         $meta = $om->getClassMetadata(get_class($root));
         $config = $this->listener->getConfiguration($om, $meta->name);
         $lockTimeProp = $meta->getReflectionProperty($config['lock_time']);
         $lockTimeProp->setAccessible(true);
         $lockTimeValue = null;
         $lockTimeProp->setValue($root, $lockTimeValue);
         $changes = array($config['lock_time'] => array(null, null));
         $ea->recomputeSingleObjectChangeSet($uow, $meta, $root);
         unset($this->rootsOfTreesWhichNeedsLocking[$oid]);
     }
 }
 /**
  * Update the $node
  *
  * @param ObjectManager    $om
  * @param object           $node - target node
  * @param AdapterInterface $ea   - event adapter
  *
  * @return void
  */
 public function updateNode(ObjectManager $om, $node, AdapterInterface $ea)
 {
     $oid = spl_object_hash($node);
     $meta = $om->getClassMetadata(get_class($node));
     $config = $this->listener->getConfiguration($om, $meta->name);
     $uow = $om->getUnitOfWork();
     $parentProp = $meta->getReflectionProperty($config['parent']);
     $parentProp->setAccessible(true);
     $parent = $parentProp->getValue($node);
     $pathProp = $meta->getReflectionProperty($config['path']);
     $pathProp->setAccessible(true);
     $pathSourceProp = $meta->getReflectionProperty($config['path_source']);
     $pathSourceProp->setAccessible(true);
     $path = $pathSourceProp->getValue($node);
     // We need to avoid the presence of the path separator in the path source
     if (strpos($path, $config['path_separator']) !== false) {
         $msg = 'You can\'t use the Path separator ("%s") as a character for your PathSource field value.';
         throw new RuntimeException(sprintf($msg, $config['path_separator']));
     }
     $fieldMapping = $meta->getFieldMapping($config['path_source']);
     // default behavior: if PathSource field is a string, we append the ID to the path
     // path_append_id is true: always append id
     // path_append_id is false: never append id
     if ($config['path_append_id'] === true || $fieldMapping['type'] === 'string' && $config['path_append_id'] !== false) {
         if (method_exists($meta, 'getIdentifierValue')) {
             $identifier = $meta->getIdentifierValue($node);
         } else {
             $identifierProp = $meta->getReflectionProperty($meta->getSingleIdentifierFieldName());
             $identifierProp->setAccessible(true);
             $identifier = $identifierProp->getValue($node);
         }
         $path .= '-' . $identifier;
     }
     if ($parent) {
         // Ensure parent has been initialized in the case where it's a proxy
         $om->initializeObject($parent);
         $changeSet = $uow->isScheduledForUpdate($parent) ? $ea->getObjectChangeSet($uow, $parent) : false;
         $pathOrPathSourceHasChanged = $changeSet && (isset($changeSet[$config['path_source']]) || isset($changeSet[$config['path']]));
         if ($pathOrPathSourceHasChanged || !$pathProp->getValue($parent)) {
             $this->updateNode($om, $parent, $ea);
         }
         $parentPath = $pathProp->getValue($parent);
         // if parent path not ends with separator
         if ($parentPath[strlen($parentPath) - 1] !== $config['path_separator']) {
             // add separator
             $path = $pathProp->getValue($parent) . $config['path_separator'] . $path;
         } else {
             // don't add separator
             $path = $pathProp->getValue($parent) . $path;
         }
     }
     if ($config['path_starts_with_separator'] && (strlen($path) > 0 && $path[0] !== $config['path_separator'])) {
         $path = $config['path_separator'] . $path;
     }
     if ($config['path_ends_with_separator'] && $path[strlen($path) - 1] !== $config['path_separator']) {
         $path .= $config['path_separator'];
     }
     $pathProp->setValue($node, $path);
     $changes = array($config['path'] => array(null, $path));
     if (isset($config['path_hash'])) {
         $pathHash = md5($path);
         $pathHashProp = $meta->getReflectionProperty($config['path_hash']);
         $pathHashProp->setAccessible(true);
         $pathHashProp->setValue($node, $pathHash);
         $changes[$config['path_hash']] = array(null, $pathHash);
     }
     if (isset($config['level'])) {
         $level = substr_count($path, $config['path_separator']);
         $levelProp = $meta->getReflectionProperty($config['level']);
         $levelProp->setAccessible(true);
         $levelProp->setValue($node, $level);
         $changes[$config['level']] = array(null, $level);
     }
     if (!$uow instanceof MongoDBUnitOfWork) {
         $ea->setOriginalObjectProperty($uow, $oid, $config['path'], $path);
         $uow->scheduleExtraUpdate($node, $changes);
     } else {
         $ea->recomputeSingleObjectChangeSet($uow, $meta, $node);
     }
     if (isset($config['path_hash'])) {
         $ea->setOriginalObjectProperty($uow, $oid, $config['path_hash'], $pathHash);
     }
 }
Beispiel #4
0
 /**
  * {@inheritdoc}
  */
 public function processPostPersist($em, $entity, AdapterInterface $ea)
 {
     $uow = $em->getUnitOfWork();
     while ($node = array_shift($this->pendingChildNodeInserts)) {
         $meta = $em->getClassMetadata(get_class($node));
         $config = $this->listener->getConfiguration($em, $meta->name);
         $identifier = $meta->getSingleIdentifierFieldName();
         $nodeId = $meta->getReflectionProperty($identifier)->getValue($node);
         $parent = $meta->getReflectionProperty($config['parent'])->getValue($node);
         $closureClass = $config['closure'];
         $closureMeta = $em->getClassMetadata($closureClass);
         $closureTable = $closureMeta->getTableName();
         $ancestorColumnName = $this->getJoinColumnFieldName($em->getClassMetadata($config['closure'])->getAssociationMapping('ancestor'));
         $descendantColumnName = $this->getJoinColumnFieldName($em->getClassMetadata($config['closure'])->getAssociationMapping('descendant'));
         $depthColumnName = $em->getClassMetadata($config['closure'])->getColumnName('depth');
         $entries = array(array($ancestorColumnName => $nodeId, $descendantColumnName => $nodeId, $depthColumnName => 0));
         if ($parent) {
             $dql = "SELECT c, a FROM {$closureMeta->name} c";
             $dql .= " JOIN c.ancestor a";
             $dql .= " WHERE c.descendant = :parent";
             $q = $em->createQuery($dql);
             $q->setParameters(compact('parent'));
             $ancestors = $q->getArrayResult();
             foreach ($ancestors as $ancestor) {
                 $entries[] = array($ancestorColumnName => $ancestor['ancestor']['id'], $descendantColumnName => $nodeId, $depthColumnName => $ancestor['depth'] + 1);
             }
             if (isset($config['level'])) {
                 $this->pendingNodesLevelProcess[$nodeId] = $node;
             }
         } else {
             if (isset($config['level'])) {
                 $uow->scheduleExtraUpdate($node, array($config['level'] => array(null, 1)));
                 $ea->setOriginalObjectProperty($uow, spl_object_hash($node), $config['level'], 1);
             }
         }
         foreach ($entries as $closure) {
             if (!$em->getConnection()->insert($closureTable, $closure)) {
                 throw new RuntimeException('Failed to insert new Closure record');
             }
         }
     }
     // Process pending node updates
     if (!empty($this->pendingNodeUpdates)) {
         foreach ($this->pendingNodeUpdates as $info) {
             $this->updateNode($em, $info['node'], $info['oldParent']);
         }
         $this->pendingNodeUpdates = array();
     }
     // Process TreeLevel field value
     $this->setLevelFieldOnPendingNodes($em);
 }
 /**
  * Update the $node
  *
  * @param ObjectManager $om
  * @param object $node - target node
  * @param object $ea - event adapter
  * @return void
  */
 public function updateNode(ObjectManager $om, $node, AdapterInterface $ea)
 {
     $oid = spl_object_hash($node);
     $meta = $om->getClassMetadata(get_class($node));
     $config = $this->listener->getConfiguration($om, $meta->name);
     $uow = $om->getUnitOfWork();
     $parentProp = $meta->getReflectionProperty($config['parent']);
     $parentProp->setAccessible(true);
     $parent = $parentProp->getValue($node);
     $pathProp = $meta->getReflectionProperty($config['path']);
     $pathProp->setAccessible(true);
     $pathSourceProp = $meta->getReflectionProperty($config['path_source']);
     $pathSourceProp->setAccessible(true);
     $path = $pathSourceProp->getValue($node);
     // We need to avoid the presence of the path separator in the path source
     if (strpos($path, $config['path_separator']) !== false) {
         $msg = 'You can\'t use the Path separator ("%s") as a character for your PathSource field value.';
         throw new RuntimeException(sprintf($msg, $config['path_separator']));
     }
     $fieldMapping = $meta->getFieldMapping($config['path_source']);
     // If PathSource field is a string, we append the ID to the path
     if ($fieldMapping['type'] === 'string') {
         if (method_exists($meta, 'getIdentifierValue')) {
             $identifier = $meta->getIdentifierValue($node);
         } else {
             $identifierProp = $meta->getReflectionProperty($meta->getSingleIdentifierFieldName());
             $identifierProp->setAccessible(true);
             $identifier = $identifierProp->getValue($node);
         }
         $path .= '-' . $identifier;
     }
     $path .= $config['path_separator'];
     if ($parent) {
         $changeSet = $uow->isScheduledForUpdate($parent) ? $ea->getObjectChangeSet($uow, $parent) : false;
         $pathOrPathSourceHasChanged = $changeSet && (isset($changeSet[$config['path_source']]) || isset($changeSet[$config['path']]));
         if ($pathOrPathSourceHasChanged || !$pathProp->getValue($parent)) {
             $this->updateNode($om, $parent, $ea);
         }
         $path = $pathProp->getValue($parent) . $path;
     }
     $pathProp->setValue($node, $path);
     $changes = array($config['path'] => array(null, $path));
     if (isset($config['level'])) {
         $level = substr_count($path, $config['path_separator']);
         $levelProp = $meta->getReflectionProperty($config['level']);
         $levelProp->setAccessible(true);
         $levelProp->setValue($node, $level);
         $changes[$config['level']] = array(null, $level);
     }
     $uow->scheduleExtraUpdate($node, $changes);
     $ea->setOriginalObjectProperty($uow, $oid, $config['path'], $path);
 }
 protected function updateField($object, $uow, AdapterInterface $ea, $meta, $field, $value, $notifyPropertyChanged = true)
 {
     $property = $meta->getReflectionProperty($field);
     $oldValue = $property->getValue($object);
     $property->setValue($object, $value);
     if ($notifyPropertyChanged && $object instanceof NotifyPropertyChanged) {
         $uow = $ea->getObjectManager()->getUnitOfWork();
         $uow->propertyChanged($object, $field, $oldValue, $value);
     }
 }
 /**
  * If it's a Uploadable object, verify if the file was uploaded.
  * If that's the case, process it.
  *
  * @param UnitOfWork
  * @param AdapterInterface
  * @param ClassMetadata
  * @param array - Configuration
  * @param object - The entity
  * @param string - String representing the action (insert or update)
  *
  * @return void
  */
 public function processFile(UnitOfWork $uow, AdapterInterface $ea, ClassMetadata $meta, array $config, $object, $action)
 {
     $refl = $meta->getReflectionClass();
     $oid = spl_object_hash($object);
     if (!isset($this->fileInfoObjects[$oid])) {
         // Nothing to do
         return;
     }
     $fileInfo = $this->fileInfoObjects[$oid];
     // Validations
     if ($config['maxSize'] > 0 && $fileInfo->getSize() > $config['maxSize']) {
         $msg = 'File "%s" exceeds the maximum allowed size of %d bytes. File size: %d bytes';
         throw new UploadableMaxSizeException(sprintf($msg, $fileInfo->getName(), $config['maxSize'], $fileInfo->getSize()));
     }
     $mime = $this->mimeTypeGuesser->guess($fileInfo->getTmpName());
     if (!$mime) {
         throw new UploadableCouldntGuessMimeTypeException(sprintf('Couldn\'t guess mime type for file "%s".', $fileInfo->getName()));
     }
     if ($config['allowedTypes'] || $config['disallowedTypes']) {
         $ok = $config['allowedTypes'] ? false : true;
         $mimes = $config['allowedTypes'] ? $config['allowedTypes'] : $config['disallowedTypes'];
         foreach ($mimes as $m) {
             if ($mime === $m) {
                 $ok = $config['allowedTypes'] ? true : false;
                 break;
             }
         }
         if (!$ok) {
             throw new UploadableInvalidMimeTypeException(sprintf('Invalid mime type "%s" for file "%s".', $mime, $fileInfo->getName()));
         }
     }
     $filePathField = $refl->getProperty($config['filePathField']);
     $filePathField->setAccessible(true);
     $path = $config['path'];
     if ($path === '') {
         if ($config['pathMethod'] !== '') {
             $pathMethod = $refl->getMethod($config['pathMethod']);
             $pathMethod->setAccessible(true);
             $path = $pathMethod->invoke($object);
         } else {
             if ($this->getDefaultPath() !== null) {
                 $path = $this->getDefaultPath();
             } else {
                 $msg = 'You have to define the path to save files either in the listener, or in the class "%s"';
                 throw new UploadableNoPathDefinedException(sprintf($msg, $meta->name));
             }
         }
     }
     Validator::validatePath($path);
     $path = substr($path, strlen($path) - 1) === '/' ? substr($path, 0, strlen($path) - 2) : $path;
     if ($config['fileMimeTypeField']) {
         $fileMimeTypeField = $refl->getProperty($config['fileMimeTypeField']);
         $fileMimeTypeField->setAccessible(true);
     }
     if ($config['fileSizeField']) {
         $fileSizeField = $refl->getProperty($config['fileSizeField']);
         $fileSizeField->setAccessible(true);
     }
     if ($action === self::ACTION_UPDATE) {
         // First we add the original file to the pendingFileRemovals array
         $this->pendingFileRemovals[] = $this->getFilePath($meta, $config, $object);
     }
     // We generate the filename based on configuration
     $generatorNamespace = 'Gedmo\\Uploadable\\FilenameGenerator';
     switch ($config['filenameGenerator']) {
         case Validator::FILENAME_GENERATOR_ALPHANUMERIC:
             $generatorClass = $generatorNamespace . '\\FilenameGeneratorAlphanumeric';
             break;
         case Validator::FILENAME_GENERATOR_SHA1:
             $generatorClass = $generatorNamespace . '\\FilenameGeneratorSha1';
             break;
         case Validator::FILENAME_GENERATOR_NONE:
             $generatorClass = false;
             break;
         default:
             $generatorClass = $config['filenameGenerator'];
     }
     $info = $this->moveFile($fileInfo, $path, $generatorClass, $config['allowOverwrite'], $config['appendNumber']);
     // We override the mime type with the guessed one
     $info['fileMimeType'] = $mime;
     $filePathField->setValue($object, $info['filePath']);
     if ($config['callback'] !== '') {
         $callbackMethod = $refl->getMethod($config['callback']);
         $callbackMethod->setAccessible(true);
         $callbackMethod->invokeArgs($object, array($info));
     }
     $changes = array($config['filePathField'] => array($filePathField->getValue($object), $info['filePath']));
     if ($config['fileMimeTypeField']) {
         $changes[$config['fileMimeTypeField']] = array($fileMimeTypeField->getValue($object), $info['fileMimeType']);
         $ea->setOriginalObjectProperty($uow, $oid, $config['fileMimeTypeField'], $info['fileMimeType']);
     }
     if ($config['fileSizeField']) {
         $changes[$config['fileSizeField']] = array($fileSizeField->getValue($object), $info['fileSize']);
         $ea->setOriginalObjectProperty($uow, $oid, $config['fileSizeField'], $info['fileSize']);
     }
     $uow->scheduleExtraUpdate($object, $changes);
     $ea->setOriginalObjectProperty($uow, $oid, $config['filePathField'], $info['filePath']);
     unset($this->fileInfoObjects[$oid]);
 }
Beispiel #8
0
 /**
  * @param AdapterInterface $ea
  * @throws \RuntimeException
  */
 protected function initUploadableSubscriber(AdapterInterface $ea)
 {
     $em = $ea->getObjectManager()->getEventManager();
     if (null === $this->uploadableSubscriber) {
         foreach ($em->getListeners('loadClassMetadata') as $listener) {
             if ($listener instanceof UploadableSubscriber) {
                 $this->setUploadableSubscriber($listener);
                 break;
             }
         }
         if (!$this->uploadableSubscriber) {
             throw new RuntimeException("UploadableSubscriber can't be found");
         }
     }
     foreach ($this->uploadableSubscriberEvents as $event) {
         if (!$em->hasListeners($event) || !in_array($this, $em->getListeners($event), true)) {
             $em->addEventListener($event, $this);
         }
     }
 }
 /**
  * @param AdapterInterface $ea
  * @param ObjectManager $om
  * @param UnitOfWork $uow
  * @param object $entity
  * @param string $method
  */
 protected function handle(AdapterInterface $ea, ObjectManager $om, UnitOfWork $uow, $entity, $method)
 {
     /**
      * @var \Doctrine\ORM\EntityManager $om
      */
     $meta = $om->getClassMetadata(get_class($entity));
     $config = $this->getConfiguration($om, $meta->name);
     if (isset($config[self::TRANSFORMABLE]) && $config[self::TRANSFORMABLE]) {
         foreach ($config[self::TRANSFORMABLE] as $column) {
             $this->handleField($entity, $method, $column, $meta);
         }
         $ea->recomputeSingleObjectChangeSet($uow, $meta, $entity);
     }
 }