Sfoglia il codice sorgente

Merge pull request #3183 from wodka/jms-annotation

add Admin annotation
Oskar Stark 9 anni fa
parent
commit
139d11065b

+ 160 - 0
Annotation/Admin.php

@@ -0,0 +1,160 @@
+<?php
+
+/*
+ * This file is part of the Sonata Project package.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Sonata\AdminBundle\Annotation;
+
+use JMS\DiExtraBundle\Annotation\MetadataProcessorInterface;
+use JMS\DiExtraBundle\Metadata\ClassMetadata;
+use Sonata\AdminBundle\Admin\Admin as AdminClass;
+
+/**
+ * Use annotations to define admin classes.
+ *
+ * @Annotation
+ * @Target("CLASS")
+ */
+class Admin implements MetadataProcessorInterface
+{
+    /**
+     * Service id - autogenerated per default.
+     *
+     * @var string
+     */
+    public $id;
+
+    /**
+     * Admin class.
+     *
+     * @var string
+     */
+    public $class;
+
+    /**
+     * Data storage.
+     *
+     * @var string
+     */
+    public $managerType = 'orm';
+
+    /**
+     * @var string
+     */
+    public $pagerType;
+
+    /**
+     * @var string
+     */
+    public $persistFilters;
+
+    /**
+     * Admin group with fallback to class.
+     *
+     * @var string
+     */
+    public $group;
+
+    /**
+     * Icon for admin group default is '<i class="fa fa-folder"></i>'.
+     *
+     * @var string
+     */
+    public $icon;
+
+    /**
+     * Admin label with fallback to class.
+     *
+     * @var string
+     */
+    public $label;
+
+    /**
+     * @var string
+     */
+    public $baseControllerName = 'SonataAdminBundle:CRUD';
+
+    /**
+     * @var string
+     */
+    public $translationDomain;
+
+    /**
+     * @var bool
+     */
+    public $showInDashboard = true;
+
+    /**
+     * @param ClassMetadata $metadata
+     */
+    public function processMetadata(ClassMetadata $metadata)
+    {
+        $this->generateFallback($this->class);
+        $this->validate();
+
+        $tag = array(
+            'manager_type'      => $this->managerType,
+            'group'             => $this->group,
+            'label'             => $this->label,
+            'show_in_dashboard' => $this->showInDashboard,
+            'icon'              => $this->icon,
+            'pager_type'        => $this->pagerType,
+            'persist_filters'   => $this->persistFilters,
+        );
+
+        $tag = array_filter($tag, function ($v) { return !is_null($v); });
+        $metadata->tags['sonata.admin'][] = $tag;
+        $metadata->arguments = array($this->id, $this->class, $this->baseControllerName);
+
+        if ($this->translationDomain) {
+            $metadata->methodCalls[] = array('setTranslationDomain', array($this->translationDomain));
+        }
+    }
+
+    /**
+     * Check if all the required fields are given.
+     */
+    private function validate()
+    {
+        if (!$this->showInDashboard) {
+            return;
+        }
+
+        if (empty($this->group) || empty($this->label)) {
+            throw new \LogicException(
+                sprintf(
+                    'Unable to generate admin group and label for class %s.',
+                    $this->class
+                )
+            );
+        }
+    }
+
+    /**
+     * Set group and label from class name it not set.
+     *
+     * @param $name
+     */
+    private function generateFallback($name)
+    {
+        if (empty($name)) {
+            return;
+        }
+
+        if (preg_match(AdminClass::CLASS_REGEX, $name, $matches)) {
+            if (empty($this->group)) {
+                $this->group = $matches[3];
+            }
+
+            if (empty($this->label)) {
+                $this->label = $matches[5];
+            }
+        }
+    }
+}

+ 23 - 1
DependencyInjection/SonataAdminExtension.php

@@ -13,6 +13,7 @@ namespace Sonata\AdminBundle\DependencyInjection;
 
 use Symfony\Component\Config\FileLocator;
 use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
 use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\HttpKernel\DependencyInjection\Extension;
@@ -23,7 +24,7 @@ use Symfony\Component\HttpKernel\DependencyInjection\Extension;
  * @author  Thomas Rabaix <thomas.rabaix@sonata-project.org>
  * @author  Michael Williams <michael.williams@funsational.com>
  */
-class SonataAdminExtension extends Extension
+class SonataAdminExtension extends Extension implements PrependExtensionInterface
 {
     /**
      * @param array            $configs   An array of configuration settings
@@ -207,6 +208,27 @@ BOOM
         $this->replacePropertyAccessor($container);
     }
 
+    /**
+     * Allow an extension to prepend the extension configurations.
+     *
+     * @param ContainerBuilder $container
+     */
+    public function prepend(ContainerBuilder $container)
+    {
+        $bundles = $container->getParameter('kernel.bundles');
+
+        if (!isset($bundles['JMSDiExtraBundle'])) {
+            $container->prependExtensionConfig(
+                'jms_di_extra',
+                array(
+                    'annotation_patterns' => array(
+                        'Sonata\AdminBundle\Annotation',
+                    ),
+                )
+            );
+        }
+    }
+
     public function configureClassesToCompile()
     {
         $this->addClassesToCompile(array(

+ 1 - 0
Resources/doc/index.rst

@@ -64,6 +64,7 @@ Advanced Options
    reference/extensions
    reference/events
    reference/advanced_configuration
+   reference/annotations
    reference/preview_mode
 
 Cookbook

+ 1 - 0
Resources/doc/reference/advanced_configuration.rst

@@ -120,6 +120,7 @@ application's config file:
                     model_manager:          # dependency name, from the table above
                         sonata.order.admin.order.manager  # customised service id
 
+
 Creating a custom RouteBuilder
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 

+ 41 - 0
Resources/doc/reference/annotations.rst

@@ -0,0 +1,41 @@
+Annotations
+===========
+
+All annotations require jms/di-extra-bundle, it can easily be installed by composer:
+
+.. code-block:: bash
+
+    composer require jms/di-extra-bundle
+
+
+if you want to know more: http://jmsyst.com/bundles/JMSDiExtraBundle
+
+
+Define Admins
+^^^^^^^^^^^^^
+
+All you have to do is include Sonata\AdminBundleAnnotations and define the values you need.
+
+.. code-block:: php
+
+    <?php
+
+    namespace AcmeBundle\Admin;
+
+    use Sonata\AdminBundle\Admin\Admin;
+    use Sonata\AdminBundle\Annotation as Sonata;
+
+    /**
+     * @Sonata\Admin(
+     *   class="AcmeBundle\Entity\MyEntity"
+     * )
+     */
+    class MyAdmin extends Admin
+    {
+    }
+
+
+.. note::
+
+    If you need to define custom controllers you can also use jms/di-extra-bundle by using
+    the DI\Service annotation.

+ 121 - 0
Tests/DependencyInjection/Compiler/AnnotationCompilerPassTest.php

@@ -0,0 +1,121 @@
+<?php
+
+/*
+ * This file is part of the Sonata Project package.
+ *
+ * (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Sonata\AdminBundle\Tests\DependencyInjection;
+
+use JMS\DiExtraBundle\Metadata\ClassMetadata;
+use Sonata\AdminBundle\Annotation\Admin;
+
+class AnnotationCompilerPassTest extends \PHPUnit_Framework_TestCase
+{
+    public function testInvalidAdminAnnotation()
+    {
+        /*
+         * @Admin(class="Sonata\AdminBundle\Tests\Fixtures\Foo")
+         */
+
+        $this->setExpectedException(
+            'LogicException',
+            'Unable to generate admin group and label for class Sonata\AdminBundle\Tests\Fixtures\Foo.'
+        );
+
+        $annotation = new Admin();
+        $annotation->class = 'Sonata\AdminBundle\Tests\Fixtures\Foo';
+
+        $meta = new ClassMetadata('Sonata\AdminBundle\Tests\Fixtures\Entity\Foo');
+
+        $annotation->processMetadata($meta);
+    }
+
+    public function testEmbeddedAdmin()
+    {
+        /*
+         * @Admin(
+         *   class="Sonata\Admin\Entity\Tests\Fixtures\Foo",
+         *   showInDashboard=false
+         * )
+         */
+        $annotation = new Admin();
+        $annotation->class = 'Sonata\Admin\Entity\Tests\Fixtures\Foo';
+        $annotation->showInDashboard = false;
+
+        $meta = new ClassMetadata('Sonata\AdminBundle\Tests\Fixtures\Entity\Foo');
+
+        $annotation->processMetadata($meta);
+
+        $this->assertSame(
+            $meta->tags['sonata.admin'][0],
+            array(
+                'manager_type'      => 'orm',
+                'show_in_dashboard' => false,
+            )
+        );
+    }
+
+    public function testMinimalAdmin()
+    {
+        /*
+         * @Admin(class="Sonata\AdminBundle\Entity\Foo")
+         */
+        $annotation = new Admin();
+        $annotation->class = 'Sonata\AdminBundle\Entity\Foo';
+
+        $meta = new ClassMetadata('Sonata\AdminBundle\Tests\Fixtures\Entity\Foo');
+
+        $annotation->processMetadata($meta);
+
+        $this->assertSame(
+            $meta->tags['sonata.admin'][0],
+            array(
+                'manager_type'      => 'orm',
+                'group'             => 'Admin',
+                'label'             => 'Foo',
+                'show_in_dashboard' => true,
+            )
+        );
+    }
+
+    public function testAdmin()
+    {
+        /*
+         * @Admin(
+         *      class="Sonata\AdminBundle\Entity\Foo",
+         *      managerType="doctrine_mongodb",
+         *      group="myGroup",
+         *      label="myLabel",
+         *      translationDomain="OMG"
+         * )
+         */
+        $annotation = new Admin();
+        $annotation->class = 'Sonata\AdminBundle\Entity\Foo';
+        $annotation->managerType = 'doctrine_mongodb';
+        $annotation->group = 'myGroup';
+        $annotation->label = 'myLabel';
+        $annotation->showInDashboard = false;
+        $annotation->translationDomain = 'OMG';
+
+        $meta = new ClassMetadata('Sonata\AdminBundle\Tests\Fixtures\Entity\Foo');
+
+        $annotation->processMetadata($meta);
+
+        $this->assertSame(
+            $meta->tags['sonata.admin'][0],
+            array(
+                'manager_type'      => 'doctrine_mongodb',
+                'group'             => 'myGroup',
+                'label'             => 'myLabel',
+                'show_in_dashboard' => false,
+            )
+        );
+
+        $this->assertSame($meta->methodCalls[0], array('setTranslationDomain', array('OMG')));
+    }
+}

+ 5 - 0
composer.json

@@ -41,12 +41,17 @@
         "knplabs/knp-menu-bundle": "^2.1.1"
     },
     "require-dev": {
+        "jms/di-extra-bundle": "~1.7",
         "sensio/generator-bundle": "~2.3|~3.0",
         "symfony/yaml": "~2.3|~3.0",
         "sonata-project/intl-bundle": "^2.2.4",
         "symfony/phpunit-bridge": "~2.7|~3.0"
     },
+    "conflict": {
+        "jms/di-extra-bundle": "<1.7.0"
+    },
     "suggest": {
+        "jms/di-extra-bundle": "Annotations for Admin definition",
         "jms/translation-bundle": "Extract message keys from Admins",
         "sensio/generator-bundle": "Add sonata:admin:generate command",
         "sonata-project/intl-bundle": "Add localized date and number into the list"