Custom Extensions

Create your own Shard Extensions.

Follow this tutorial to create a simple extension that defines a Color annotation that can be added to a document and can filter by color.

At bare minimum, an extension must have an instance of Zoop\Shard\AbstractExtension. This class provides all the hooks and configuration required to create your extension. It has these properties, and you can add your own custom configuration properties:

Name type description
documents array An array of document namespaces and directories to register.
subscribers array An array of subscribers, or subscriber service names to register.
cliCommands array An array of cli command service names to register with the doctrine cli.
cliHelpers array An array of cli helper service names to register with the doctrine cli.
serviceManagerConfig array Any service manager configuration.
dependencies array An array of service names of other extensions that must be loaded for this extension to work.

For example, the Color extension class would look like this:

namespace My\Color;

use Zoop\Shard\AbstractExtension;

class Extension extends AbstractExtension
{

    protected $subscribers = [
        'subscriber.color.annotationsubscriber' //annotation subscriber to listen to @Color annotation events
    ];

    protected $serviceManagerConfig = [
        'invokables' => [
            'subscriber.color.annotationsubscriber' => 'My\Color\AnnotationSubscriber' //register the annotation subscriber service
        ]
    ];

    protected $filters = [
        'color' => 'My\Color\Filter' //register filter
    ];

    protected $dependencies = [
        'extension.annotation' => true //require the annotation extension to make annotation events work
    ];
}

Create a small factory class to return an instance of your extension. Eg:

namespace My\Color;

use Zoop\Shard\AbstractExtensionFactory;
use Zend\ServiceManager\ServiceLocatorInterface;

class ExtensionFactory extends AbstractExtensionFactory
{
    protected $extensionServiceName = 'my.extension.color';

    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        return new Extension($this->getConfig($serviceLocator));
    }
}

The color extension is using an annotation, so we need to define that annotation:

namespace My\Color;

use Doctrine\Common\Annotations\Annotation;

final class Color extends Annotation
{
    const event = 'annotationColor';
}

Add an annotation subscriber to listen to the annotationColor event and augment the metadata:

namespace My\Color;

use Doctrine\Common\EventSubscriber;
use Zoop\Shard\Annotation\AnnotationEventArgs;

class AnnotationSubscriber implements EventSubscriber
{

    public function getSubscribedEvents(){
        return [Color::event];
    }

    public function annotationColorZones(AnnotationEventArgs $eventArgs)
    {
        $eventArgs->getMetadata()->color = $eventArgs->getReflection()->getName();
    }
}

Add a filter that can filter by color:

namespace My\Color;

use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
use Doctrine\ODM\MongoDB\Query\Filter\BsonFilter;

class Filter extends BsonFilter
{
    protected $color;

    public function setColor($color){
        $this->color = $color;
    }

    public function addFilterCriteria(ClassMetadata $metadata)
    {
        if (isset($metadata->color)) {
            return array($metadata->color => $this->color);
        }
        return array();
    }
}

That's it!

Config

Now register and enable you extension when you create a manifest:

$manifest = new Zoop\Shard\Manifest([
    ...
    'extension_configs' => [
        'my.extension.color' => true
    ],
    'service_manager_config' => [
        'factories' => [
            'my.extension.color' => 'My\Color\ExtensionFactory'
        ],
    ]
]);

@Color

Use your @Color annotation in a document:

use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use My\Color\Color;

/**
 * @ODM\Document
 */
class DocWithColor {

    /**
     * @ODM\String
     * @Color
     */
    protected $color;
    ...
}

Filter

Use your filter to filter documents by color:

$documentManager->getFilterCollection()->enable('color');
$filter = $documentManager->getFilterCollection()->getFilter('color');
$filter->setColor('blue');

Now package up your rocking extension and share it with others! Or, contribute it back into Shard if you're feeling kind.