public function process($fromCollection, $toCollection) { // der genericCollectionSynchronizer braucht ArrayCollections $fromCollection = Code::castCollection($fromCollection); $toCollection = Code::castCollection($toCollection); // die defaults sind: compare nach object, hashe nach identifier, und die sind prima für uns $this->innerSynchronizer->process($fromCollection, $toCollection); }
/** * * @controller-api * @TODO orderby? */ public function getEntities(array $query = array(), $subResource = NULL) { if ($subResource === 'search') { return $this->getEntitySearchPanel($this->getEntityMeta(), $query); } elseif ($subResource !== NULL && array_key_exists($subResource, $this->customActions)) { return $this->callCustomAction($this->customActions[$subResource], array($query)); } if (array_key_exists('autocomplete', $query) && $query['autocomplete'] === 'true') { $entityMeta = $this->getEntityMeta(); $fields = array_keys($entityMeta->getAutoCompleteFields()); $maxResults = isset($query['maxResults']) ? max(1, (int) $query['maxResults']) : NULL; $entities = $this->doAutoCompleteEntities($fields, $query['search'], array_key_exists('filters', $query) ? (array) $query['filters'] : array(), $maxResults); $exporter = new \Psc\CMS\Item\Exporter(); $export = array(); foreach ($entities as $entity) { // @TODO es wäre schön hier spezifizieren zu können welche interfaces exportiert werden müssen // dies muss vom request her passieren $export[] = $exporter->ComboDropBoxable($entityMeta->getAdapter($entity)->getComboDropBoxable()); //$export[] = $exporter->AutoCompletable($entityMeta->getAdapter($entity)->getAutoCompletable()); //$export[] = $exporter->merge($entityMeta->getAdapter($entity), // array('AutoCompletable','Identifyable','TabOpenable') // ); } if (isset($maxResults) && count($export) === $maxResults) { // exceeds $this->metadata = new MetadataGenerator(); $this->metadata->autoCompleteMaxResultsHit($maxResults); } return $export; } else { $entities = $this->findEntitiesFor($query, $this->getDefaultSort(), $subResource); } if ($subResource === NULL) { return Code::castCollection($entities); } elseif ($subResource === 'grid') { return $this->getEntityGrid($this->dc->getEntityMeta($this->getEntityName()), $entities); } else { throw $this->err->invalidArgument(__FUNCTION__, 'subResource', $subResource); } }
/** * Synchronisiert eine Collection eines Entities mit Entities in der Datenbank (deprecated) * * Diese Art der Synchroniserung ist deprecated, weil es mittlerweile ausgelagerte Funktionen dafür gibt * (siehe Psc\Doctrine\*Synchro*) * * also es werden für die bestehenden Objekte in $entity->$collectionProperty die objekte gelöscht * die nicht in newCollection drin sind und die, die in $newCollection drin sind aber nicht in * $entity->$collectionProperty gelöscht * * - Achtung(!): dies führt persist() auf den Entitys der Collection (also quasi andere Seite der Association) aus, wenn $this->entity nicht die Owning-Side der CollectionAssociation ist * - Dies führt persist für items in newCollection, die neu sind * * Die Basis für eine erfolgreiche Synchronization ist eine $newCollection die wirklich die gleichen Objekte enthält, für die Updates gemacht werden sollen. Also vorsicht mit serialisierten Einträgen und clones * * @param string $associationName der Name des Properties der Collection in $entity */ public function synchronizeCollection($associationName, $newCollection) { if (!is_string($associationName)) { throw new \Psc\Exception('string erwartet: ' . Code::varInfo($associationName)); } /* $mapping = $coll->getMapping(); $targetClass = $this->_em->getClassMetadata($mapping['targetEntity']); $sourceClass = $this->_em->getClassMetadata($mapping['sourceEntity']); $id = $this->_em->getUnitOfWork()->getEntityIdentifier($coll->getOwner()); */ if ($this->entity instanceof \Psc\Doctrine\Object) { $entityClass = $this->entity->getDoctrineMetadata(); // Sound } elseif ($this->entity instanceof \Psc\Doctrine\Entity) { $entityClass = $this->em->getClassMetadata($this->entity->getEntityName()); } else { throw new \InvalidArgumentException('$this->entity ist von der Klasse: ' . Code::getClass($this->entity) . ' und diese ist unbekannt'); } $entityAssoc = $entityClass->getAssociationMapping($associationName); // speakers $owning = $entityAssoc['isOwningSide']; // true $targetClass = $this->em->getClassMetadata($entityAssoc['targetEntity']); // Metadata:Speaker if ($owning) { $entityProperty = $entityAssoc['inversedBy']; $collectionProperty = $entityAssoc['fieldName']; } else { $entityProperty = $entityAssoc['mappedBy']; $collectionProperty = $entityAssoc['fieldName']; } // entityProperty = sounds // collectionProperty = speakers $getter = Code::castGetter($collectionProperty); //getSpeakers $collection = $getter($this->entity); // $this->entity->getSpeakers() $collection = Code::castCollection($collection); $newCollection = Code::castCollection($newCollection); $this->log(sprintf("synchronizeCollection '%s'", $associationName)); $this->log('in DBCollection:'); $this->log(DoctrineHelper::debugCollection($collection)); $this->log(NULL); $this->log('in FormCollection:'); $this->log(DoctrineHelper::debugCollection($newCollection)); $this->log(NULL); $this->log('Processing:'); /* Wir synchronisieren hier auf der Owning Side oder Reverse Side jenachdem müssen wir auf der owning oder reverse side die add + remove funktionen aufrufen */ if ($owning) { $remove = 'remove' . ucfirst(Inflector::singular($collectionProperty)); // removeSpeaker $add = 'add' . ucfirst(Inflector::singular($collectionProperty)); // addSpeaker } else { $remove = 'remove' . ucfirst(Inflector::singular($entityProperty)); // removeSound $add = 'add' . ucfirst(Inflector::singular($entityProperty)); // addSound } $logThis = Code::getClassName($entityClass->getName()); // @TODO hier mit reflection prüfen //if (!->hasMethod($remove)) { // throw new \Psc\Exception('Es gibt keine '.$remove.' Methode im Entity: '.$owningEntity); //} //if (!$this->entity->hasMethod($add)) { // throw new \Psc\Exception('Es gibt keine '.$add.' Methode im Entity: '.$owningEntity); //} // foreach ($collection->deleteDiff($newCollection, ArrayCollection::COMPARE_OBJECTS) as $entity) { if ($owning) { $this->entity->{$remove}($entity); // $sound->removeSpeaker($speaker) } else { $this->em->persist($entity); // $speaker persist $entity->{$remove}($this->entity); // $speaker->removeSound($sound) } } foreach ($collection->insertDiff($newCollection, ArrayCollection::COMPARE_OBJECTS) as $entity) { if ($owning) { $this->entity->{$add}($entity); $this->em->persist($entity); } else { $entity->{$add}($this->entity); $this->em->persist($entity); } } }
/** * Erstellt einen ComponentsValidator anhand des EntityFormPanels * * Der FormPanel muss die Componenten schon erstellt haben sie werden mit getComponents() aus dem Formular genommen */ public function createComponentsValidator(FormData $requestData, EntityFormPanel $panel, DCPackage $dc, array $components = NULL) { $this->validationEntity = $entity = $panel->getEntityForm()->getEntity(); $components = isset($components) ? Code::castCollection($components) : $panel->getEntityForm()->getComponents(); return $this->componentsValidator = new ComponentsValidator($this->createFormDataSet($requestData, $panel, $entity), $components, $this->componentRuleMapper); }