diff --git a/.travis.yml b/.travis.yml index e1d05d96..f8958f48 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,7 @@ matrix: fast_finish: true before_install: + - if [[ ! -z "$GITHUB_OAUTH_TOKEN" ]]; then composer config -g github-oauth.github.com "$GITHUB_OAUTH_TOKEN" >/dev/null 2>&1; fi; - if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then phpenv config-rm xdebug.ini; fi; - if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then echo "memory_limit=4096M" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; fi; - composer self-update diff --git a/src/EavBundle/Controller/SchemaController.php b/src/EavBundle/Controller/SchemaController.php index 0eb25c23..7c8fdb1d 100644 --- a/src/EavBundle/Controller/SchemaController.php +++ b/src/EavBundle/Controller/SchemaController.php @@ -9,9 +9,7 @@ use Symfony\Component\HttpFoundation\Response; /** - * Class SchemaController - * - * @package Opifer\EavBundle\Controller + * Schema Controller */ class SchemaController extends Controller { diff --git a/src/EavBundle/DependencyInjection/Configuration.php b/src/EavBundle/DependencyInjection/Configuration.php index cb12039f..2fa8970d 100644 --- a/src/EavBundle/DependencyInjection/Configuration.php +++ b/src/EavBundle/DependencyInjection/Configuration.php @@ -29,9 +29,6 @@ public function getConfigTreeBuilder() ->scalarNode('media_class') ->defaultValue('') ->end() - ->scalarNode('nestable_class') - ->defaultValue('') - ->end() ->scalarNode('option_class') ->isRequired() ->end() diff --git a/src/EavBundle/DependencyInjection/OpiferEavExtension.php b/src/EavBundle/DependencyInjection/OpiferEavExtension.php index a7d268c8..9076513a 100644 --- a/src/EavBundle/DependencyInjection/OpiferEavExtension.php +++ b/src/EavBundle/DependencyInjection/OpiferEavExtension.php @@ -37,7 +37,6 @@ public function getParameters(array $config) $params = [ 'opifer_eav.attribute_class' => $config['attribute_class'], 'opifer_eav.media_class' => $config['media_class'], - 'opifer_eav.nestable_class' => $config['nestable_class'], 'opifer_eav.option_class' => $config['option_class'], 'opifer_eav.schema_class' => $config['schema_class'], 'opifer_eav.valueset_class' => $config['valueset_class'], @@ -75,10 +74,6 @@ public function prepend(ContainerBuilder $container) 'Opifer\EavBundle\Model\ValueSetInterface' => $config['valueset_class'], ]; - if ($config['nestable_class'] != '') { - $resolvableEntities['Opifer\EavBundle\Model\Nestable'] = $config['nestable_class']; - } - if ($config['media_class'] != '') { $resolvableEntities['Opifer\EavBundle\Model\MediaInterface'] = $config['media_class']; } diff --git a/src/EavBundle/README.md b/src/EavBundle/README.md index a52d0773..3663cd97 100644 --- a/src/EavBundle/README.md +++ b/src/EavBundle/README.md @@ -1,2 +1,220 @@ EavBundle ========= + +This bundle eases the implementation of an [entity-attribute-value model](https://en.wikipedia.org/wiki/Entity-attribute-value_model) +on an entity. + +Model summary + +- *EntityInterface.* Implemented by one or more of your own entities. +- *Attribute.* Defines the type of value. +- *Value.* The saved value. +- *Schema.* Defines the attributes for an EntityInterface. +- *ValueSet.* Functions as join table between the entity and its values. +- *Option.* Defines the options for Select-, Checklist- or RadioValues. + +Installation +------------ + +Add OpiferEavBundle to your composer.json: + + $ composer require opifer/eav-bundle + +Register the bundle in `app/AppKernel.php`: + +```php +public function registerBundles() +{ + $bundles = array( + // ... + new Opifer\EavBundle\OpiferEavBundle(), + ); +} + +``` + +Create the `Attribute`, `Schema`, `ValueSet` and `Option` entities: + +```php +namespace AppBundle\Entity; + +use Doctrine\ORM\Mapping as ORM; +use Opifer\EavBundle\Model\Attribute as BaseAttribute; + +/** + * @ORM\Entity() + * @ORM\Table(name="attribute") + */ +class Attribute extends BaseAttribute +{ + +} + +``` + +```php +namespace AppBundle\Entity; + +use Doctrine\ORM\Mapping as ORM; +use Opifer\EavBundle\Model\Schema as BaseSchema; + +/** + * @ORM\Entity() + * @ORM\Table(name="schema") + */ +class Schema extends BaseSchema +{ + +} + +``` + +```php +namespace AppBundle\Entity; + +use Doctrine\ORM\Mapping as ORM; +use Opifer\EavBundle\Model\ValueSet as BaseValueSet; + +/** + * @ORM\Entity() + * @ORM\Table(name="valueset") + */ +class ValueSet extends BaseValueSet +{ + +} + +``` + +```php +namespace AppBundle\Entity; + +use Doctrine\ORM\Mapping as ORM; +use Opifer\EavBundle\Model\Option as BaseOption; + +/** + * @ORM\Entity() + * @ORM\Table(name="option") + */ +class Option extends BaseOption +{ + +} + +``` + +Define these entities in your config: + +```yml +opifer_eav: + attribute_class: AppBundle\Entity\Attribute + schema_class: AppBundle\Entity\Schema + valueset_class: AppBundle\Entity\ValueSet + option_class: AppBundle\Entity\Option +``` + +Usage +----- + +Connecting the EAV-model to an entity is probably best explained by example. +Say, we got a Page entity that should have dynamic properties. We want to create +the following types of pages: + +- Default page (just a title and a textarea) +- News page (title, textarea, author and a date) + +First, we'll create the Page entity that implements `EntityInterface`: + +```php +namespace AppBundle\Entity; + +use Doctrine\ORM\Mapping as ORM; +use Opifer\EavBundle\Model\EntityInterface; +use Opifer\EavBundle\Model\ValueSetInterface; + +/** + * @ORM\Entity() + * @ORM\Table(name="page") + */ +class Page implements EntityInterface +{ + /** + * @var int + * + * @ORM\Id + * @ORM\Column(name="id", type="integer") + * @ORM\GeneratedValue(strategy="AUTO") + */ + protected $id; + + /** + * @var \Opifer\EavBundle\Model\ValueSet + * + * @ORM\ManyToOne(targetEntity="Opifer\EavBundle\Model\ValueSetInterface", cascade={"persist"}) + * @ORM\JoinColumn(name="valueset_id", referencedColumnName="id") + */ + protected $valueSet; + + public function setValueSet(ValueSetInterface $valueSet) + { + $this->valueSet = $valueSet; + } + + public function getValueSet() + { + return $this->valueSet; + } +} + +``` + +Define the `Page` entity in the config: + +```yml +opifer_eav: + # ... + entities: + page: AppBundle\Entity\Page +``` + +Create a the PageController with a createAction: + +```php +namespace AppBundle\Controller; + +use Opifer\EavBundle\Form\Type\ValueSetType; +use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Component\HttpFoundation\Request; + +class PageController extends Controller +{ + public function createAction(Request $request) + { + $em = $this->getDoctrine()->getManager(); + + // Fetch a the schema with the predefined attributes + $schema = $em->getRepository('AppBundle:Schema')->find(1); + + // Initialize a new Page entity + $page = $this->get('opifer.eav.eav_manager')->initializeEntity($schema); + + // Add the valueset type to the form + $form = $this->createFormBuilder($page) + ->add('valueset', ValueSetType::class) + ->getForm(); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $em->persist($page); + $em->flush(); + + // Redirect to the page edit/index + } + + return $this->render('Page/create.html.twig', [ + 'form' => $form->createView() + ]); + } +} + +``` diff --git a/src/EavBundle/Tests/TestData/Entity.php b/src/EavBundle/Tests/TestData/Entity.php index a879a7ee..fede145c 100644 --- a/src/EavBundle/Tests/TestData/Entity.php +++ b/src/EavBundle/Tests/TestData/Entity.php @@ -2,9 +2,7 @@ namespace Opifer\EavBundle\Tests\TestData; -use Opifer\EavBundle\Entity\NestedValue; use Opifer\EavBundle\Model\EntityInterface; -use Opifer\EavBundle\Model\Nestable; use Opifer\EavBundle\Model\SchemaInterface; use Opifer\EavBundle\Model\ValueSetInterface; @@ -14,8 +12,6 @@ class Entity implements EntityInterface protected $schema; - protected $nestedSort; - public function setValueSet(ValueSetInterface $valueSet) { $this->valueSet = $valueSet;