public function bootRunTime(Object $object, Configs $configs) { if (!$object->hasRelation($this->getFieldDefinition()->getId())) { $relation = new RelationDefinition(); $relation->setName($this->getFieldDefinition()->getId()); $relation->setType(AbstractStorage::ONE_TO_MANY); $relation->setForeignObjectKey('jarves/content'); $relation->setRefName($object->getId()); $object->addRelation($relation); $configs->addReboot('Added auto relation because of PageContents type.'); } if (!$object->hasField('layout')) { $field = new Field(); $field->setId('layout'); $field->setType('text'); $object->addField($field); $configs->addReboot('PageContents needs `layout` field.'); } if (!$object->hasField('theme')) { $field = new Field(); $field->setId('theme'); $field->setType('text'); $object->addField($field); $configs->addReboot('PageContents needs `theme field.'); } }
/** * @param Configuration\Configs $configs */ public function registerBundleEvents(Configuration\Configs $configs) { $this->detachEvents(); foreach ($configs->getConfigs() as $bundleConfig) { //register custom listener through config, like cache clearing, service calls etc if ($events = $bundleConfig->getListeners()) { foreach ($events as $event) { $this->attachEvent($event); } } //clear storage caches when object changes if ($objects = $bundleConfig->getObjects()) { foreach ($objects as $object) { $fn = function () use($object) { $storage = $this->container->get($object->getStorageService()); $storage->configure($object->getKey(), $object); $storage->clearCache(); }; $event = new Event(); $event->setSubject($object->getKey()); $event->setKey('core/object/modify'); $event->setCalls([$fn]); $this->attachEvent($event); } } } }
public function testAttributes() { $xml = <<<EOF <bundle> <objects> <object id="Test2"> <label>Test</label> <class>tests.store.core.test2</class> <fields> <field id="id" type="number" primaryKey="true"> <label>ID</label> </field> <field id="name" type="text"> <label>Name</label> </field> </fields> </object> </objects> <objectAttributes> <attribute target="asdasd" id="bar" type="text"/> <attribute target="nonExistingBundle/ASD" id="bar" type="text"/> <attribute target="test/test2" id="foo" type="text"/> <attribute target="TestBundle/Test2" id="hans" type="text"/> </objectAttributes> </bundle> EOF; $configs = new Configs($this->getJarves()); $bundle = new Bundle('TestBundle'); $bundle->initialize($xml); $configs->addConfig($bundle); $this->assertCount(2, $bundle->getObject('Test2')->getFieldsArray()); $bundle->boot($configs); $this->assertCount(4, $bundle->getObject('Test2')->getFieldsArray()); $foo = $bundle->getObject('Test2')->getField('foo'); $this->assertTrue($foo->getAttribute()); }
public function bootRunTime(Object $object, Configs $configs) { $contentsObjectName = $object->getId() . ucfirst($this->getFieldDefinition()->getId()); $contentsObject = $object->getBundle()->getObject($contentsObjectName); if (!$contentsObject) { $contentsObject = new Object(); $contentsObject->setId($contentsObjectName); if ($object->getWorkspace()) { $contentsObject->setWorkspace(true); } $contentsObject->setAutoCrud(false); $contentsObject->setSearchable(false); $contentsObject->setExcludeFromREST(true); $contentsObject->setNested(true); $contentsObject->setNestedRootAsObject(true); $contentsObject->setNestedRootObject($object->getKey()); $contentsObject->setNestedRootObjectField('foreignId'); $contentsObject->setTable($object->getTable() . '_' . Tools::camelcase2Underscore($this->getFieldDefinition()->getId())); $contentsObject->setStorageService($object->getStorageService()); } $fields = ['id' => ['type' => 'number', 'autoIncrement' => true, 'primaryKey' => true], 'foreignId' => ['type' => 'number'], 'slotId' => ['type' => 'number'], 'sort' => ['type' => 'number'], 'content' => ['type' => 'textarea'], 'template' => ['type' => 'view'], 'type' => ['type' => 'text'], 'hide' => ['type' => 'checkbox'], 'unsearchable' => ['type' => 'checkbox'], 'access_from' => ['type' => 'datetime'], 'access_to' => ['type' => 'datetime'], 'access_from_groups' => ['type' => 'text']]; foreach ($fields as $k => $def) { if (!$contentsObject->getField($k)) { $def['id'] = $k; $field = new Field($def, $object->getJarves()); $contentsObject->addField($field); $configs->addReboot(sprintf('[ContentElements] Added field %s to %s', $k, $contentsObject->getKey())); } } if (!$contentsObject->hasRelation('ForeignObject')) { $relation = new RelationDefinition(); $relation->setName('ForeignObject'); $relation->setType(AbstractStorage::MANY_TO_ONE); $relation->setForeignObjectKey($object->getKey()); $relation->setRefName(ucfirst($this->getFieldDefinition()->getId())); $reference = new RelationReferenceDefinition(); $primaryFields = $object->getPrimaryKeys(); if (1 < count($primaryFields)) { throw new ModelBuildException(sprintf('FieldType `ContentElements` can not be used on the object `%s` with composite PrimaryKey', $object->getId())); } if (0 === count($primaryFields)) { throw new ModelBuildException(sprintf('FieldType `ContentElements` can not be used on the object `%s` with no PrimaryKey', $object->getId())); } $columns = $primaryFields[0]->getFieldType()->getColumns(); if (1 < count($columns)) { throw new ModelBuildException(sprintf('FieldType `ContentElements` can not be used on the object `%s` with composite PrimaryKey', $object->getId())); } $reference->setForeignColumn($columns[0]); $field = $contentsObject->getField('foreignId'); $columns = $field->getFieldType()->getColumns(); $reference->setLocalColumn($columns[0]); $relation->setReferences([$reference]); $contentsObject->addRelation($relation); $configs->addReboot(sprintf('[ContentElements] Added relation ForeignObject to %s', $contentsObject->getKey())); } if (!$contentsObject->getBundle()) { $object->getBundle()->addObject($contentsObject); } if (!$object->hasRelation($this->getFieldDefinition()->getId())) { $relation = new RelationDefinition(); $relation->setName(ucfirst($this->getFieldDefinition()->getId())); $relation->setType(AbstractStorage::ONE_TO_MANY); $relation->setForeignObjectKey($contentsObject->getKey()); $relation->setRefName('ForeignObject'); $reference = new RelationReferenceDefinition(); $primaryFields = $object->getPrimaryKeys(); $columns = $primaryFields[0]->getFieldType()->getColumns(); $reference->setLocalColumn($columns[0]); $field = $contentsObject->getField('foreignId'); $columns = $field->getFieldType()->getColumns(); $reference->setForeignColumn($columns[0]); $relation->setReferences([$reference]); $object->addRelation($relation); $configs->addReboot(sprintf('[ContentElements] Added relation %s to %s', ucfirst($this->getFieldDefinition()->getId()), $object->getKey())); } }
/** * @param Configs $configs * @return RelationDefinition|null * @throws \Jarves\Exceptions\ModelBuildException */ protected function getRelation(Configs $configs) { $field = $this->getFieldDefinition(); $columns = []; $foreignObjectDefinition = $configs->getObject($field->getObject()); if (!$foreignObjectDefinition) { throw new ModelBuildException(sprintf('ObjectKey `%s` not found for field `%s` in object `%s`', $field->getObject(), $field->getId(), $field->getObjectDefinition()->getId())); } $relation = new RelationDefinition(); $relation->setName($field->getId()); $relation->setType($field->getObjectRelation()); $relation->setForeignObjectKey($field->getObject()); $relation->setWithConstraint($field->getObjectRelationWithConstraint()); if ($refName = $field->getObjectRefRelationName()) { $relation->setRefName($refName); } foreach ($foreignObjectDefinition->getPrimaryKeys() as $pk) { $fieldColumns = $pk->getFieldType()->getColumns(); $columns = array_merge($columns, $fieldColumns); } if (!$columns) { return null; } $references = []; foreach ($columns as $column) { $reference = new RelationReferenceDefinition(); $localColumn = clone $column; $localColumn->setName($field->getId() . ucfirst($column->getName())); $reference->setLocalColumn($localColumn); $reference->setForeignColumn($column); $references[] = $reference; } $relation->setReferences($references); return $relation; }
/** * Loads all configurations from all registered bundles (BundleName/Resources/config/jarves*.xml) * @param Cacher $cacher * * @return null|callable returns a callable that should be called when config stuff have been registered */ public function loadBundleConfigs(Cacher $cacher) { $cached = $cacher->getFastCache('core/configs'); $bundles = array_keys($this->kernel->getBundles()); $configs = new Configuration\Configs($this); $hashes = []; foreach ($bundles as $bundleName) { $hashes[] = $configs->getConfigHash($bundleName); } $hash = md5(implode('.', $hashes)); if ($cached) { $cached = unserialize($cached); if (is_array($cached) && $cached['md5'] == $hash) { $this->configs = $cached['data']; $this->configs->setCore($this); } } if (!$this->configs) { $this->configs = new Configuration\Configs($this, $bundles); return function () use($hash, $cacher) { $cached = serialize(['md5' => $hash, 'data' => $this->configs]); $cacher->setFastCache('core/configs', $cached); }; } }
/** * Returns a real Bundle config object, which is being read from the configurations * files without bootstrap. So this configuration does not contain any changes from * autoCrud, object-attributes, field modifications and other configuration manipulations from the bootstrap. * * When no configurations are found, it returns a completely new Jarves\Configuration\Bundle object. * * @param string $bundleName * @return Bundle */ public function getRealConfig($bundleName) { $configs = new Configs($this); $configs->loadBundles([$bundleName]); $config = $configs->getConfig($bundleName); if (!$config) { $bundle = $this->getBundle($bundleName); return new Bundle($bundle, $this, null); } return $config; }
public function testFileImportSaveMixed() { $configs = new Configs($this->getJarves()); $this->setupFiles(); $bundle = new TestsFileImportBundle(); $configStrings = $configs->getXmlConfigsForBundle($bundle); $configObjects = $configs->parseConfig($configStrings); $testBundleConfig = $configObjects['testsfileimport']; $this->assertNotNull($testBundleConfig); $export = $testBundleConfig->exportFileBased('objects'); $exportCaches = $testBundleConfig->exportFileBased('caches'); $this->assertStringEqualsFile($this->getJarvesObjectsXmlFile(), $export, 'no changes'); $this->assertStringEqualsFile($this->getJarvesXmlFile(), $exportCaches, 'no changes'); $objects = $testBundleConfig->getObjects(); current($objects)->setId('TestChanged'); $testBundleConfig->setObjects($objects); $caches = $testBundleConfig->getCaches(); $caches[1]->setMethod('testMethod2'); $testBundleConfig->setCaches($caches); $events = $testBundleConfig->getEvents(); $events[1]->setKey('core/object/updateModified'); $testBundleConfig->setEvents($events); $this->getConfigurationOperator()->saveFileBased($testBundleConfig, 'objects'); $xml = '<config> <bundle> <objects> <object id="TestChanged"> <label>Test</label> <storageService>tests.store.core.test</storageService> <fields> <field id="id" type="number" primaryKey="true"> <label>ID</label> </field> <field id="name" type="text"> <label>Name</label> </field> </fields> </object> </objects> </bundle> </config>'; $this->assertEquals(static::$jarvesObjectsXml, $testBundleConfig->getPropertyFilePath('objects')); $this->assertStringEqualsFile($this->getRoot() . $testBundleConfig->getPropertyFilePath('objects'), $xml); $this->assertEquals(static::$jarvesXml, $testBundleConfig->getPropertyFilePath('caches')); $this->assertEquals(static::$jarvesXml, $testBundleConfig->getPropertyFilePath('events')); $this->getConfigurationOperator()->saveFileBased($testBundleConfig, 'caches'); $xmlCaches = '<config> <bundle> <caches> <cache>core/contents</cache> <cache method="testMethod2">core/contents2</cache> </caches> <events> <event key="core/object/modify"> <desc>Fires on every object modification (add/delete/update). Subject is the normalized object key.</desc> </event> <event key="core/object/update"> <desc>Fires on every object update. Subject is the normalized object key.</desc> </event> </events> <listeners> <event key="core/object/modify" subject="core:domain"> <clearCache>core/domains.created</clearCache> <clearCache>core/domains</clearCache> </event> <event key="core/object/modify" subject="core:content"> <clearCache>core/contents</clearCache> </event> <event key="core/object/modify" subject="core:node"> <clearCache>core/contents</clearCache> </event> </listeners> </bundle> </config>'; $this->assertStringEqualsFile($this->getRoot() . $testBundleConfig->getPropertyFilePath('caches'), $xmlCaches); $this->getConfigurationOperator()->saveFileBased($testBundleConfig, 'events'); $xmlEvents = '<config> <bundle> <caches> <cache>core/contents</cache> <cache method="testMethod2">core/contents2</cache> </caches> <events> <event key="core/object/modify"> <desc>Fires on every object modification (add/delete/update). Subject is the normalized object key.</desc> </event> <event key="core/object/updateModified"> <desc>Fires on every object update. Subject is the normalized object key.</desc> </event> </events> <listeners> <event key="core/object/modify" subject="core:domain"> <clearCache>core/domains.created</clearCache> <clearCache>core/domains</clearCache> </event> <event key="core/object/modify" subject="core:content"> <clearCache>core/contents</clearCache> </event> <event key="core/object/modify" subject="core:node"> <clearCache>core/contents</clearCache> </event> </listeners> </bundle> </config>'; $this->assertStringEqualsFile($this->getRoot() . $testBundleConfig->getPropertyFilePath('events'), $xmlEvents); $bundle = new TestsFileImportBundle(); $configStrings = $configs->getXmlConfigsForBundle($bundle); $configObjects = $configs->parseConfig($configStrings); $testBundleConfig = $configObjects['testsfileimport']; $this->assertNotNull($testBundleConfig); $this->assertCount(1, $testBundleConfig->getObjects()); $this->assertCount(2, $testBundleConfig->getCaches()); $this->assertCount(2, $testBundleConfig->getEvents()); $this->assertEquals('TestChanged', current($testBundleConfig->getObjects())->getId()); $this->assertEquals('testMethod2', $testBundleConfig->getCaches()[1]->getMethod()); $this->assertEquals('core/object/updateModified', $testBundleConfig->getEvents()[1]->getKey()); unlink($this->getJarvesXmlFile()); unlink($this->getJarvesObjectsXmlFile()); }
/** * All bundle configs have been loaded. * * @param Configs $configs */ public function boot(Configs $configs) { if ($this->objectAttributes) { foreach ($this->objectAttributes as $attribute) { $key = $attribute->getId(); try { $targetObject = $configs->getObject($attribute->getTarget()); } catch (BundleNotFoundException $e) { continue; } if (!$attribute->getTarget() || !$targetObject) { continue; } $field = $targetObject->getField($key); if (!$field) { //does not exists, so attach it $attribute->setAttribute(true); $targetObject->addField($attribute); $configs->addReboot(sprintf('Added field attribute %s to %s', $key, $targetObject->getId())); } } } if ($this->getObjects()) { foreach ($this->getObjects() as $object) { $object->bootRunTime($configs); } } }