<?php
/**
 * YAWIK
 *
 * @filesource
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
 * @license   MIT
 */

/** Core forms */
namespace Core\Form;

/**
 * Form which provides alternate rendering (summary).
 *
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 */
class SummaryForm extends BaseForm implements SummaryFormInterface
{

    /**
     * Which representation to render.
     *
     * @var string
     */
    protected $renderMode = self::RENDER_ALL;

    /**
     * Hint, which representation to show in view
     *
     * @var string
     */
    protected $displayMode = self::DISPLAY_FORM;

    /**
     * {@inheritDoc}
     * @see \Core\Form\SummaryFormInterface::setRenderMode()
     */
    public function setRenderMode($mode)
    {
        $this->renderMode = $mode;
        return $this;
    }

    /**
     * {@inheritDoc}
     * @see \Core\Form\SummaryFormInterface::getRenderMode()
     */
    public function getRenderMode()
    {
        return $this->renderMode;
    }

    /**
     * {@inheritDoc}
     * @see \Core\Form\SummaryFormInterface::setDisplayMode()
     */
    public function setDisplayMode($mode)
    {
        $this->displayMode = $mode;
        return $this;
    }

    /**
     * {@inheritDoc}
     * @see \Core\Form\SummaryFormInterface::getDisplayMode()
     */
    public function getDisplayMode()
    {
        return $this->displayMode;
    }

    /**
     * {@inheritDoc}
     *
     * Uses {@link \Core\Form\SummaryFormButtonsFieldset} as buttons fieldset.
     *
     * @see \Core\Form\BaseForm::addButtonsFieldset()
     */
    protected function addButtonsFieldset()
    {
        $this->add(
            array(
            'type' => 'SummaryFormButtonsFieldset'
            )
        );
    }

    /**
     * {@inheritDoc}
     *
     * Sets render mode to {@link RENDER_SUMMARY}, if validation succeeded.
     *
     * @see \Zend\Form\Form::isValid()
     */
    public function isValid()
    {
        $isValid = parent::isValid();
        if ($isValid) {
            $this->setRenderMode(self::RENDER_SUMMARY);
        }

        return $isValid;
    }

    public function setOptions($options)
    {
        parent::setOptions($options);

        if (isset($options['display_mode'])) {
            $this->setDisplayMode($options['display_mode']);
        }
    }
}


<?php
/**
 * @author Gerard van Helden <gerard@zicht.nl>
 * @copyright Zicht Online <http://zicht.nl>
 */

namespace Zicht\Bundle\PageBundle\Validator\Constraints;

use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Zicht\Bundle\PageBundle\Entity\ContentItem;

/**
 * Class ContentItemMatrixValidator
 *
 * @package Zicht\Bundle\PageBundle\Validator\Constraints
 */
class ContentItemMatrixValidator extends ConstraintValidator
{
    /**
     * @var TranslatorInterface
     */
    protected $translator;

    /**
     * ContentItemMatrixValidator constructor.
     *
     * @param TranslatorInterface $translator
     */
    public function __construct(TranslatorInterface $translator)
    {
        $this->translator = $translator;
    }

    /**
     * Validate
     *
     * @param mixed $value
     * @param Constraint $constraint
     */
    public function validate($value, Constraint $constraint)
    {
        /** @var \Zicht\Bundle\PageBundle\Model\ContentItemMatrix $matrix */
        $matrix = $value->getContentItemMatrix();

        if (null !== $matrix) {
            /**
             * @var int $i
             * @var ContentItem $contentItem
             */
            foreach ($value->getContentItems() as $i => $contentItem) {
                $type = get_class($contentItem);

                if (!in_array($contentItem->getRegion(), $matrix->getRegions($type))) {
                    $message = $this->translator->trans('content_item.invalid.region_type_combination', ['%region%' => $contentItem->getRegion(), '%type%' => $type], 'validators');
                    $this->context->buildViolation($message)
                        ->atPath(sprintf('contentItems[%d]', $i))
                        ->addViolation();
                }
            }
        }
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @license MIT
 * @copyright  2013 - 2016 Cross Solution <http://cross-solution.de>
 */

/** */
namespace Core\Form\Hydrator\Strategy;

use Core\Entity\Tree\AbstractLeafs;
use Core\Entity\Tree\EmbeddedLeafs;
use Core\Entity\Tree\NodeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Zend\Hydrator\Strategy\StrategyInterface;

/**
 * Hydrator strategy for TreeSelect form element.
 *
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 * @since 0.29
 */
class TreeSelectStrategy implements StrategyInterface
{

    /**
     * The selected leafs.
     *
     * @var AbstractLeafs
     */
    private $attachedLeafs;

    /**
     * The root node.
     *
     * @var NodeInterface
     */
    private $treeRoot;

    /**
     * Flag wether multiple selections are allowed.
     *
     * @var bool|callable
     */
    private $allowSelectMultipleItems = false;

    private $shouldCreateLeafs = false;

    private $shouldUseNames = false;

    /**
     * Set the selected leafs.
     *
     * @param AbstractLeafs $attachedLeafs
     *
     * @return self
     */
    public function setAttachedLeafs(AbstractLeafs $attachedLeafs)
    {
        $this->attachedLeafs = $attachedLeafs;

        return $this;
    }

    /**
     * Get the selected leafs.
     *
     * @return AbstractLeafs
     */
    public function getAttachedLeafs()
    {
        return $this->attachedLeafs ?: new EmbeddedLeafs();
    }

    /**
     * Set the root node.
     *
     * @param NodeInterface $treeRoot
     *
     * @return self
     */
    public function setTreeRoot(NodeInterface $treeRoot)
    {
        $this->treeRoot = $treeRoot;

        return $this;
    }

    /**
     * Get the root node.
     *
     * @return NodeInterface
     */
    public function getTreeRoot()
    {
        return $this->treeRoot;
    }

    /**
     * Set the allow multiple selections flag.
     *
     * @param Callable|bool $flagOrCallback When a Callable is passed, it must return bool.
     *
     * @return self
     */
    public function setAllowSelectMultipleItems($flagOrCallback)
    {
        $this->allowSelectMultipleItems = $flagOrCallback;

        return $this;
    }

    /**
     * Are multiple selections allowed?
     *
     * @return bool
     */
    public function allowSelectMultipleItems()
    {
        $flagOrCallback = $this->allowSelectMultipleItems;

        return is_callable($flagOrCallback) ? (bool) $flagOrCallback() : (bool) $flagOrCallback;
    }

    public function setShouldCreateLeafs($flagOrCallback)
    {
        $this->shouldCreateLeafs = $flagOrCallback;

        return $this;
    }

    public function shouldCreateLeafs()
    {
        $flagOrCallback = $this->shouldCreateLeafs;

        return is_callable($flagOrCallback) ? (bool) $flagOrCallback() : (bool) $flagOrCallback;
    }

    /**
     * @return bool
     */
    public function shouldUseNames()
    {
        return $this->shouldUseNames;
    }

    /**
     * @param bool $flag
     *
     * @return self
     */
    public function setShouldUseNames($flag)
    {
        $this->shouldUseNames = (bool) $flag;

        return $this;
    }

    public function extract($value)
    {
        if (empty($value)) {
            return $this->allowSelectMultipleItems() ? [] : null;
        }

        if (!$value instanceof AbstractLeafs) {
            return $value;
        }

        /* @var AbstractLeafs $value
         * @var NodeInterface $item */

        $this->setAttachedLeafs($value);

        if (!$this->allowSelectMultipleItems()) {
            $item = $value->getItems()->first();
            return $item ? $item->getValueWithParents(false, $this->shouldUseNames()) : null;
        }

        $data = [];
        foreach ($value->getItems() as $item) {
            $data[] = $item->getValueWithParents(false, $this->shouldUseNames());
        }

        return $data;
    }

    public function hydrate($value)
    {
        $object = $this->getAttachedLeafs();

        $root = $this->getTreeRoot();
        $items = new ArrayCollection();

        if (!$this->allowSelectMultipleItems()) {
            $value = [$value];
        }

        foreach ($value as $itemValue) {
            $leaf = $this->findLeaf($root, $itemValue);

            if ($leaf) {
                $items->add($leaf);
            }
        }

        $object->setItems($items);

        return $object;
    }

    /**
     * Find a leaf with a concrete value in the tree.
     *
     * @param NodeInterface $leaf
     * @param string        $value
     *
     * @return NodeInterface|null
     */
    private function findLeaf(NodeInterface $leaf, $value)
    {
        $parts = is_array($value) ? $value : explode($this->shouldUseNames() ? ' | ': '-', $value);
        $value = array_shift($parts);

        /* @var NodeInterface $item */
        foreach ($leaf->getChildren() as $item) {
            $compare = $this->shouldUseNames() ? $item->getName() : $item->getValue();
            if ($compare == $value) {
                if (count($parts)) {
                    return $this->findLeaf($item, $parts);
                }

                return $item;
            }
        }

        if ($value && $this->shouldCreateLeafs()) {
            $nodeClass = get_class($leaf);
            $node = new $nodeClass($value);
            $leaf->addChild($node);
            if (count($parts)) {
                return $this->findLeaf($node, $parts);
            }

            return $node;
        }

        return null;
    }
}


<?php

namespace Core\Form\Element;

use Zend\Form\Element;
use Zend\InputFilter\InputProviderInterface;
use Zend\Validator\Regex as RegexValidator;

class Phone extends Element implements InputProviderInterface
{
    /**
     * @var \Zend\Validator\ValidatorInterface
     */
    protected $validator;

    /**
    * Get a validator if none has been set.
    * https://github.com/posabsolute/jQuery-Validation-Engine/issues/265
    * @return RegexValidator
    */
    public function getValidator()
    {
        if (null === $this->validator) {
            $validator = new RegexValidator('/^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{1,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/');
            $validator->setMessage(
                /*@translate */ 'Please enter a phone Number. You can use the intenational format. Only digits and \'+\'.',
                RegexValidator::NOT_MATCH
            );

            $this->validator = $validator;
        }

        return $this->validator;
    }

    /**
     * Sets the validator to use for this element
     *
     * @param  RegexValidator $validator
     * @return Phone
     */
    public function setValidator(RegexValidator $validator)
    {
        $this->validator = $validator;
        return $this;
    }

    /**
     * Provide default input rules for this element
     *
     * Attaches a phone number validator.
     *
     * @return array
     */
    public function getInputSpecification()
    {
        return array(
            'name' => $this->getName(),
            'required' => true,
            'filters' => array(
                array('name' => 'Zend\Filter\StringTrim'),
            ),
            'validators' => array(
                $this->getValidator(),
            ),
        );
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
 * @license       MIT
 */

/**  */
namespace Core\Form\View\Helper;

use Zend\Form\View\Helper\FormFile;
use Zend\Form\ElementInterface;
use Core\Form\Element\FileUpload;

/**
 * View helper to render a file upload element.
 *
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 * @author Miroslav Fedeleš <miroslav.fedeles@gmail.com>
 */
class FormFileUpload extends FormFile
{
    /**
     * Javascript file to inject to headscript helper
     *
     * @var string
     */
    protected $scriptFile = 'modules/Core/js/forms.file-upload.js';

    /**
     * @var string
     */
    protected $emptyNotice;

    /**
     * @var string
     */
    protected $nonEmptyNotice;

    /**
     * @var bool
     */
    protected $allowRemove = true;

    /**
     * @var bool
     */
    protected $allowClickableDropZone = true;

    public function render(ElementInterface $element)
    {
        if (!$element instanceof FileUpload) {
            throw new \InvalidArgumentException('Expects element of type "Core\Form\Element\FileUpload"');
        }

        $markup = $this->renderMarkup($element);
        $markup = str_replace('__input__', $this->renderFileElement($element), $markup);

        return $markup;
    }

    /**
     * @param FileUpload $element
     * @return string
     * @since 0.27
     */
    public function renderFileList(FileUpload $element)
    {
        $this->setupAssets();

        $file       = $element->getFileEntity();
        $preview    = '';
        $translator = $this->getTranslator();
        $textDomain = $this->getTranslatorTextDomain();

        $template = '

'.($this->allowRemove ? '

    ' : '').'

        0 %

        __file-name__
 (__file-size__)

' . $translator->translate('The file is too big', $textDomain) . '

' . $translator->translate('The file type is not supported', $textDomain) . '

' . sprintf(
    $translator->translate('You may only upload %d files', $textDomain),
    $element->getAttribute('data-maxfilecount')
) . '

' . $translator->translate('An unknown error occured.') . '

';
        /* @var $renderer \Zend\View\Renderer\PhpRenderer */
        /* @var $basepath \Zend\View\Helper\BasePath */
        $renderer          = $this->getView();
        $basepath          = $renderer->plugin('basepath');
        $createFileDisplay = function ($file) use ($template, $basepath) {
            /* @var $file \Core\Entity\FileInterface */
            $uri  = $basepath($file->getUri());
            $name = $file->getName();
            $size = $file->getPrettySize();
            $icon = 0 === strpos($file->getType(), 'image/')
                ? 'fa-file-image-o' : 'fa-file-o';

            return str_replace(
                array('#abort',
                      '__file-uri__',
                      '__file-name__',
                      '__file-size__',
                      'fu-working',
                      'fa-file-o'
                ),
                array("$uri?do=delete", $uri, $name, $size, '', $icon),
                $template
            );
        };

        if ($element->isMultiple()) {
            if (count($file)) {
                foreach ($file as $f) {
                    $preview .= $createFileDisplay($f);
                }
            }
        } else {
            if ($file) {
                $preview = $createFileDisplay($file);
            }
        }

        $nonemptynotice =
            '
'
            . $this->getNonEmptyNotice() . '
';
        $emptynotice    = '

                       ' . $this->getEmptyNotice() . '

';

        $markup = '

    %4$s

    %1$s

    %3$s';

        $markup = sprintf(
            $markup,
            $preview,
            $renderer->escapeHtmlAttr(trim($template)),
            $emptynotice,
            $nonemptynotice
        );

        return $markup;
    }

    /**
     * @param FileUpload $element
     * @return string
     * @throws \DomainException
     * @since 0.27
     */
    public function renderFileElement(FileUpload $element)
    {
        $name = $element->getName();
        if ($name === null || $name === '') {
            throw new \DomainException(
                sprintf(
                    '%s requires that the element has an assigned name; none discovered',
                    __METHOD__
                )
            );
        }

        $attributes         = $element->getAttributes();
        $attributes['type'] = $this->getType($element);
        $attributes['name'] = $name;

        return sprintf(
            '<input %s%s',
            $this->createAttributesString($attributes),
            $this->getInlineClosingBracket()
        );
    }

    /**
     * Renders the markup for the file upload element.
     *
     * @param FileUpload $element
     *
     * @return string
     */
    protected function renderMarkup(FileUpload $element)
    {
        $markup = '

    %s
   __input__

';

        return sprintf(
            $markup,
            $this->getDropZoneClass($element),
            $element->getAttribute('id'),
            $this->renderFileList($element)
        );
    }

    /**
     * @param FileUpload $element
     * @return string
     * @since 0.27
     */
    public function getDropZoneClass(FileUpload $element)
    {
        return sprintf(
            'fu-dropzone fu-%s%s',
            $element->isMultiple() ? 'multiple' : 'single',
            $this->allowClickableDropZone ? '' : ' fu-non-clickable'
        );
    }

    /**
     * @param string $emptyNotice
     * @return FormFileUpload
     * @since 0.27
     */
    public function setEmptyNotice($emptyNotice)
    {
        $this->emptyNotice = $emptyNotice;

        return $this;
    }

    /**
     * @return string
     * @since 0.27
     */
    protected function getEmptyNotice()
    {
        if (!isset($this->emptyNotice)) {
            $this->emptyNotice = '

' . $this->getDefaultNotice();
        }

        return $this->emptyNotice;
    }

    /**
     * @param string $nonEmptyNotice
     * @return FormFileUpload
     * @since 0.27
     */
    public function setNonEmptyNotice($nonEmptyNotice)
    {
        $this->nonEmptyNotice = $nonEmptyNotice;

        return $this;
    }

    /**
     * @return string
     * @since 0.27
     */
    protected function getNonEmptyNotice()
    {
        if (!isset($this->nonEmptyNotice)) {
            $this->nonEmptyNotice = $this->getDefaultNotice();
        }

        return $this->nonEmptyNotice;
    }

    /**
     * @return string
     * @since 0.27
     */
    protected function getDefaultNotice()
    {
        return '' . $this->getTranslator()->translate('Click here to add files or use drag and drop.') . '';
    }

    /**
     * @param boolean $allowRemove
     * @return FormFileUpload
     * @since 0.27
     */
    public function setAllowRemove($allowRemove)
    {
        $this->allowRemove = (bool)$allowRemove;

        return $this;
    }

    /**
     * @param boolean $allowClickableDropZone
     * @return FormFileUpload
     * @since 0.27
     */
    public function setAllowClickableDropZone($allowClickableDropZone)
    {
        $this->allowClickableDropZone = (bool)$allowClickableDropZone;

        return $this;
    }

    /**
     * @since 0.27
     */
    protected function setupAssets()
    {
        /* @var $renderer \Zend\View\Renderer\PhpRenderer */
        /* @var $basepath \Zend\View\Helper\BasePath */
        $renderer = $this->getView();
        $basepath = $renderer->plugin('basepath');
        $renderer->headscript()
            //->appendFile($basepath('assets/blueimp-file-upload/js/vendor/jquery.ui.widget.js'))
            //->appendFile($basepath('assets/blueimp-file-upload/js/jquery.iframe-transport.js'))
            //->appendFile($basepath('assets/blueimp-file-upload/js/jquery.fileupload.js'))
            ->appendFile($basepath($this->scriptFile));
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @license MIT
 * @copyright  2013 - 2017 Cross Solution <http://cross-solution.de>
 */

/** */
namespace Core\Factory\Form;

use Core\Form\CustomizableFieldsetInterface;
use Interop\Container\ContainerInterface;
//use Zend\ServiceManager\FactoryInterface;
//use Zend\ServiceManager\MutableCreationOptionsInterface;
use Interop\Container\Exception\ContainerException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Zend\ServiceManager\Exception;
use Zend\ServiceManager\Exception\InvalidServiceException;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\ServiceManager\PluginManagerInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

/**
 * Factory boilerplate for customizable Fieldsets
 *
 * Ideally, you just need to extends this and set the values of the two constants.
 *
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 * @since 0.29
 */
abstract class AbstractCustomizableFieldsetFactory implements FactoryInterface, PluginManagerInterface
{
    /**
     * Name of the options service
     * @var string
     */
    const OPTIONS_NAME = '';

    /**
     * The target fieldset class FQN
     *
     * @var string
     */
    const CLASS_NAME   = '';

    /**
     * Creation options.
     *
     * @var array
     */
    protected $options;

    public function setCreationOptions(array $options)
    {
        $this->options = $options;
    }

    /**
     * Reset the creation options.
     */
    protected function resetCreationOptions()
    {
        $this->options = null;
    }

    /**
     * Creates an instance.
     *
     * @param ContainerInterface $container
     * @param string             $requestedName
     * @param array              $options
     *
     * @return CustomizableFieldsetInterface
     * @throws \RuntimeException
     */
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        /* @var CustomizableFieldsetInterface $instance */
        $instance = $this->createFormInstance($container, $requestedName, $options);

        if (!$instance instanceof CustomizableFieldsetInterface) {
            throw new \RuntimeException('Form or Fieldset instance must implement ' . CustomizableFieldsetInterface::class);
        }

        $customizeOptions = $this->getCustomizationOptions($container, $requestedName, $options);
        $instance->setCustomizationOptions($customizeOptions);

        return $instance;
    }

    /**
     * Get the customization options.
     *
     * @param ContainerInterface $container
     * @param string             $requestedName
     * @param array              $options
     *
     * @return \Core\Options\FieldsetCustomizationOptions
     * @throws \RuntimeException
     */
    protected function getCustomizationOptions(ContainerInterface $container, $requestedName, array $options = null)
    {
        if (!static::OPTIONS_NAME) {
            throw new \RuntimeException('The class constants "OPTIONS_NAME" must be non empty.');
        }

        return $container->get(static::OPTIONS_NAME);
    }

    /**
     * Create the form/fieldset instance
     *
     * @param ContainerInterface $container
     * @param string             $name
     * @param array              $options
     *
     * @return \Zend\Form\Fieldset
     * @throws \RuntimeException
     */
    protected function createFormInstance(ContainerInterface $container, $name, array $options = null)
    {
        if (!static::CLASS_NAME || !class_exists(static::CLASS_NAME)) {
            throw new \RuntimeException('The class constants "CLASS_NAME" must be non empty and name an existent class.');
        }

        $class = static::CLASS_NAME;

        return new $class(null, $options);
    }

    /**
     * Create service
     *
     * @internal
     *      proxies to {@link __invoke()}
     *
     * @param ServiceLocatorInterface|\Zend\ServiceManager\AbstractPluginManager $serviceLocator
     *
     * @return CustomizableFieldsetInterface
     */
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $instance = $this($serviceLocator, '', $this->options);
        $this->resetCreationOptions();

        return $instance;
    }

    public function get($id)
    {
        // TODO: Implement get() method.
    }

    public function has($id)
    {
        // TODO: Implement has() method.
    }

    public function validate($instance)
    {
        // TODO: Implement validate() method.
    }

    public function build($name, array $options = null)
    {
        // TODO: Implement build() method.
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @license MIT
 * @copyright  2013 - 2019 Cross Solution <http://cross-solution.de>
 */

/** */
namespace Core\Queue\Worker;

use Core\Queue\Exception\FatalJobException;
use Core\Queue\Exception\RecoverableJobException;
use Core\Queue\Job\ExceptionJobResult;
use Core\Queue\Job\JobResult;
use Core\Queue\Job\ResultProviderInterface;
use Core\Queue\LoggerAwareJobTrait;
use Core\Queue\MongoQueue;
use SlmQueue\Job\JobInterface;
use SlmQueue\Queue\QueueAwareInterface;
use SlmQueue\Queue\QueueInterface;
use SlmQueue\Worker\AbstractWorker;
use SlmQueue\Worker\Event\ProcessJobEvent;
use Zend\Log\LoggerAwareInterface;

/**
 * Queue worker for the mongo queue.
 *
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 */
class MongoWorker extends AbstractWorker implements LoggerAwareInterface
{
    use LoggerAwareJobTrait;

    /**
     * Process job handler.
     *
     * @param JobInterface   $job
     * @param QueueInterface $queue
     *
     * @return int|void
     */
    public function processJob(JobInterface $job, QueueInterface $queue)
    {
        if (!$queue instanceof MongoQueue) {
            return;
        }

        if ($job instanceOf QueueAwareInterface) {
            $job->setQueue($queue);
        }

        try {
            return $job->execute();
        } catch (\Exception $exception) {
            $this->getLogger()->err('Job execution thrown exception: ' . get_class($exception));

            if ($job instanceOf ResultProviderInterface) {
                $job->setResult(JobResult::failure($exception->getMessage(), [$exception->getTraceAsString()]));
            } else {
                $this->getLogger()->err($exception->getMessage(), [$exception->getTraceAsString()]);
            }

            return ProcessJobEvent::JOB_STATUS_FAILURE;
        }
    }
}


<?php
/**
 * @copyright Zicht Online <http://zicht.nl>
 */

namespace Zicht\Bundle\PageBundle\Manager;

use Doctrine\Bundle\DoctrineBundle\Registry;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\Common\Persistence\ObjectRepository;
use Doctrine\Common\Util\ClassUtils;
use Doctrine\ORM\Mapping\ClassMetadata;
use Symfony\Component\EventDispatcher\Event as SymfonyEvent;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Zicht\Bundle\PageBundle\Entity\ViewablePageRepository;
use Zicht\Bundle\PageBundle\Event;
use Zicht\Bundle\PageBundle\Model\PageInterface;
use Zicht\Util\Str;

/**
 * Main service for page management
 */
class PageManager
{
    /**
     * @var array
     */
    private $mappings;

    /**
     * @var null|PageInterface
     */
    private $loadedPage;

    /**
     * @var Registry
     */
    private $doctrine;

    /**
     * @var ObjectManager
     */
    private $em;

    /**
     * @var EventDispatcher
     */
    private $eventDispatcher;

    /**
     * @var string
     */
    private $pageClassName;

    /**
     * @var string
     */
    private $contentItemClassName;

    /**
     * Construct the page manager with the specified dependencies.
     *
     * @param Registry $doctrine
     * @param EventDispatcher $dispatcher
     * @param string $pageClassName
     * @param string $contentItemClassName
     */
    public function __construct(Registry $doctrine, $dispatcher, $pageClassName, $contentItemClassName)
    {
        $this->mappings = [];
        $this->doctrine = $doctrine;
        $this->em = $doctrine->getManager();
        $this->eventDispatcher = $dispatcher;

        $this->pageClassName = $pageClassName;
        $this->contentItemClassName = $contentItemClassName;

        $this->mappings[$pageClassName] = [];
        $this->mappings[$contentItemClassName] = [];
    }

    /**
     * Returns the template of the page from the bundle the entity is part of.
     *
     * @param PageInterface $page
     * @return string
     *
     * @throws \RuntimeException
     */
    public function getTemplate($page)
    {
        // determine page bundle name.
        $bundle = $this->getBundleName(ClassUtils::getRealClass(get_class($page)));
        return sprintf('%s:Page:%s.html.twig', $bundle, $page->getTemplateName());
    }

    /**
     * @param string $className
     * @return string
     * @throws \RuntimeException
     */
    protected function getBundleName($className)
    {
        $parts = explode('\\', $className);
        $vendor = array_shift($parts);
        $bundleName = null;
        foreach ($parts as $part) {
            if ($part === 'Entity') {
                break;
            }
            $bundleName = $part;
        }
        if (null === $bundleName) {
            $parentClass = get_parent_class($className);
            if ($parentClass) {
                return $this->getBundleName($parentClass);
            }

            throw new \RuntimeException("Could not determine bundle name for " . $className);
        }
        $bundle = $vendor . $bundleName;

        return $bundle;
    }

    /**
     * Returns the page class
     *
     * @return string
     */
    public function getPageClass()
    {
        return $this->pageClassName;
    }

    /**
     * Returns the base repository, i.e. the repository of the page class.
     *
     * @return ObjectRepository
     */
    public function getBaseRepository()
    {
        return $this->em->getRepository($this->pageClassName);
    }

    /**
     * Sets the available page types
     *
     * @param array $pageTypes
     */
    public function setPageTypes($pageTypes)
    {
        $this->mappings[$this->pageClassName] = $pageTypes;
    }

    /**
     * @return array
     */
    public function getPageTypes()
    {
        return $this->mappings[$this->pageClassName];
    }

    /**
     * @return array
     */
    public function getMappings()
    {
        return $this->mappings;
    }

    /**
     * Sets the available content item types.
     *
     * @param array $contentItemTypes
     */
    public function setContentItemTypes($contentItemTypes)
    {
        $this->mappings[$this->contentItemClassName] = $contentItemTypes;
    }

    /**
     * Adds the available page types and content item types to the class metadata's discriminatorMap
     *
     * @param ClassMetadata $c
     */
    public function decorateClassMetaData(ClassMetadata $c)
    {
        $parentClassName = $c->getName();

        if (isset($this->mappings[$parentClassName])) {
            $c->discriminatorMap = array();
            $c->discriminatorMap[strtolower(Str::classname($parentClassName))] = $parentClassName;
            foreach ($this->mappings[$parentClassName] as $className) {
                $bundlePrefix = Str::infix($this->getBundleName($className), '-');
                $name = Str::infix(Str::classname(Str::rstrip($className, Str::classname($parentClassName))), '-');
                $combinedDiscriminator = sprintf('%s-%s', $bundlePrefix, $name);
                $c->discriminatorMap[$combinedDiscriminator] = $className;
                $c->subClasses[] = $className;
            }
            $c->subClasses = array_unique($c->subClasses);
        }
    }

    /**
     * Find a page in the repository and trigger a view event.
     *
     * @param string $id
     * @return mixed
     *
     * @throws NotFoundHttpException
     */
    public function findForView($id)
    {
        $type = $this->doctrine->getConnection()->fetchColumn('SELECT type FROM page WHERE id=:id', array('id' => $id));
        if (!$type) {
            throw new NotFoundHttpException;
        }
        $types = $this->em->getClassMetadata($this->pageClassName)->discriminatorMap;

        $class = $types[$type];
        $repos = $this->em->getRepository($class);

        if ($repos instanceof ViewablePageRepository) {
            $ret = $repos->findForView($id);
        } else {
            $ret = $repos->find($id);
        }

        if (!$ret) {
            throw new NotFoundHttpException;
        }
        $this->setLoadedPage($ret);
        return $ret;
    }

    /**
     * Finds a page in the specified repository by the specified conditions.
     *
     * @param string $repository
     * @param array $conditions
     * @return null|object
     *
     * @throws NotFoundHttpException
     */
    public function findPageBy($repository, $conditions)
    {
        $ret = $this->em->getRepository($repository)->findOneBy($conditions);
        if (!$ret) {
            throw new NotFoundHttpException;
        }
        return $ret;
    }

    /**
     * Returns all pages from the base repository
     *
     * @return array
     */
    public function findAll()
    {
        return $this->getBaseRepository()->findAll();
    }

    /**
     * Set the loaded page, and trigger a view event
     *
     * @param PageInterface $loadedPage
     */
    public function setLoadedPage($loadedPage)
    {
        $this->dispatch(Event\PageEvents::PAGE_VIEW, new Event\PageViewEvent($loadedPage));
        $this->loadedPage = $loadedPage;
    }

    /**
     * Returns the currently loaded page, or default to the specified callback for loading it.
     *
     * @param callable $default
     * @return PageInterface
     * @throws NotFoundHttpException
     */
    public function getLoadedPage($default = null)
    {
        if (!$this->loadedPage) {
            if (is_callable($default)) {
                $page = call_user_func($default, $this);
                if ($page !== null) {
                    $this->setLoadedPage($page);
                }
            }

            if (!$this->loadedPage) {
                throw new NotFoundHttpException("There is no page currently loaded, but it was expected");
            }
        }
        return $this->loadedPage;
    }

    /**
     * Dispatch an event
     *
     * @param string $type
     * @param SymfonyEvent $event
     *
     * @return SymfonyEvent
     */
    public function dispatch($type, $event)
    {
        return $this->eventDispatcher->dispatch($type, $event);
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
 * @license   MIT
 */

/** Core entity hydrator strategies */
namespace Core\Entity\Hydrator\Strategy;

use Zend\Hydrator\Strategy\StrategyInterface;
use Core\Entity\FileInterface;

/**
 * This strategy copies file entities from on mongo collection to another.
 *
 * This copy process must be done in the same request (means extracting the old
 * entity and hydrating the new entity), because the temporarily file will be
 * removed on script shutdown.
 *
 *
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 */
class FileCopyStrategy implements StrategyInterface
{
    /**
     * Target entity.
     *
     * @var FileInterface
     */
    protected $targetEntity;

    /**
     * Creates a new FileCopyStrategy.
     *
     * @param FileInterface $targetEntity
     */
    public function __construct(FileInterface $targetEntity)
    {
        $this->targetEntity = $targetEntity;
    }

    /**
     * Returns a clone of the target entity.
     *
     * @return FileInterface
     */
    public function getTargetEntity()
    {
        return clone $this->targetEntity;
    }

    /**
     * Extracts the source file entity.
     *
     * Stores the binary content in a temporarily file.
     * Returns the meta data along the name of the temporarily file as an array.
     *
     * If $value is not of the type FileInterface, nothing will be done,
     * and NULL is returned.
     *
     * @param FileInterface|null $value
     * @return array|null
     * @see \Zend\Hydrator\Strategy\StrategyInterface::extract()
     */
    public function extract($value)
    {
        if (!$value instanceof FileInterface) {
            return null;
        }

        // Store binary data in temporary file.
        $tmp = tempnam(sys_get_temp_dir(), 'yk-copy.');
        $out = fopen($tmp, 'w');
        $in  = $value->getResource();

        // ensures garbage removal
        register_shutdown_function(
            function ($filename) {
                @unlink($filename);
            },
            $tmp
        );

        while (!feof($in)) {
            fputs($out, fgets($in, 1024));
        }
        fclose($in);
        fclose($out);

        $return = ["file" => $tmp];

        foreach (['user', 'name', 'type'] as $key) {
            $v = $value->{"get$key"}();
            if ($v) {
                $return[$key]=$v;
            }
        }

        return $return;
    }

    /**
     * Hydrates and returns a clone of the target entity.
     *
     * $value must be either null or the array returned from
     * {@link extract()}.
     *
     * if $value is null, nothing is done and NULL is returned.
     *
     * @param array|null $value
     * @return FileInterface
     * @see \Zend\Hydrator\Strategy\StrategyInterface::hydrate()
     */
    public function hydrate($value)
    {
        if (!is_array($value)) {
            return null;
        }

        $entity = $this->getTargetEntity();

        foreach ($value as $key=>$v) {
            $entity->{"set$key"}($v);
        }
        return $entity;
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
 * @license       MIT
 */

/** */
namespace Core\Mail;

use Core\Factory\ContainerAwareInterface;
use Interop\Container\ContainerInterface;
use Zend\I18n\Translator\TranslatorAwareInterface;
use Zend\Mail\Address;
use Zend\Mail\AddressList;
use Zend\Mail\Message as MailMessage;
use Zend\Mail\Transport\TransportInterface;
use Zend\ServiceManager\AbstractPluginManager;
use Zend\ServiceManager\ConfigInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

/**
 * Mail Plugin Manager
 *
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 * @author Mathias Weitz <weitz@cross-solution.de>
 * @author Carsten Bleek <bleek@cross-solution.de>
 * @author Anthonius Munthi <me@itstoni.com>
 */
class MailService extends AbstractPluginManager
{
    /**
     * Define transport type to use
     */
    const TRANSPORT_SMTP        = 'smtp';
    const TRANSPORT_FILE        = 'file';
    const TRANSPORT_SENDMAIL    = 'sendmail';

    /**
     * The mail Transport
     *
     * @var TransportInterface
     */
    protected $transport;

    /**
     * Default from address to use if no from address is set in the mail.
     *
     * @var string
     */
    protected $from;

    /**
     * Value for the X-Mailer header.
     *
     * @var string
     */
    protected $mailer;

    /**
     * If set, all mails are send to the addresses in this list
     *
     * This is useful when developing.
     *
     * @var AddressList|null
     */
    protected $overrideRecipient;

    protected $language;

    protected $shareByDefault = false;

    protected $invokableClasses = array(
        'simple'         => '\Zend\Mail\Message',
        'stringtemplate' => '\Core\Mail\StringTemplateMessage',
    );

    protected $factories = array(
        'htmltemplate'   => [HTMLTemplateMessage::class,'factory'],
    );

    /**
     * Creates an instance.
     *
     * Adds two default initializers:
     * - Inject the translator to mails implementing TranslatorAwareInterface
     * - Call init() method on Mails if such method exists.
     *
     * @param ContainerInterface $container
     * @param mixed $configuration
     */
    public function __construct($container, $configuration = [])
    {
        parent::__construct($container, $configuration);

        $this->addInitializer(
            function ($context, $instance) {
                if ($instance instanceof TranslatorAwareInterface) {
                    $translator = $context->get('translator');
                    $instance->setTranslator($translator);
                    if (null === $instance->getTranslatorTextDomain()) {
                        $instance->setTranslatorTextDomain();
                    }
                    $instance->setTranslatorEnabled(true);
                }
                if ($instance instanceof ContainerAwareInterface) {
                    $instance->setContainer($context);
                }
            }
        );

        //@TODO: [ZF3] verify that removing this lines is save
        //$this->addInitializer(
        //   function ($context,$instance) {
        //        if (method_exists($instance, 'setServiceLocator')) {
        //            //$instance->setServiceLocator($this);
        //        }
        //   }
        //);

        $this->addInitializer(
            function ($context, $instance) {
                if (method_exists($instance, 'init')) {
                    $instance->init();
                }
            }
        );
    }

    /**
     * Checks that a plugin is a child of an email message.
     *
     * @throws \InvalidArgumentException
     */
    public function validate($plugin)
    {
        if (!$plugin instanceof MailMessage) {
            throw new \InvalidArgumentException(
                sprintf(
                    'Expected instance of \Zend\Mail\Message but received %s',
                    get_class($plugin)
                )
            );
        }
    }

    /**
     * Gets the default from address
     *
     * @return null|String|Address|AddressList|array
     */
    public function getFrom()
    {
        return $this->from;
    }

    /**
     * Sets the default from address.
     *
     * @param string|AddressList|Address $email
     * @param String|null                $name
     *
     * @return self
     */
    public function setFrom($email, $name = null)
    {
        if (is_array($email)) {
            $this->from = [$email['email'] => $email['name']];
        } else {
            $this->from = is_object($email) || null === $name
                ? $email
                : array($email => $name);
        }

        return $this;
    }

    /**
     * Sets override recipients.
     *
     * @param AddressList $recipients
     *
     * @return self
     */
    public function setOverrideRecipient(AddressList $recipients)
    {
        $this->overrideRecipient = $recipients;

        return $this;
    }

    /**
     * Sends a mail.
     *
     * Sets default values where needed.
     *
     * @param string|MailMessage $mail
     * @param array          $options
     */
    public function send($mail, array $options = array())
    {
        if (!$mail instanceof MailMessage) {
            $mail = $this->get($mail, $options);
        }

        $headers   = $mail->getHeaders();
        $transport = $this->getTransport();

        if (!$mail->isValid() && $this->from) {
            $mail->setFrom($this->from);
        }

        if ($this->overrideRecipient instanceof AddressList) {
            $originalRecipient = $headers->get('to')->toString();
            if ($headers->has('cc')) {
                $originalRecipient .= '; ' . $headers->get('cc')->toString();
                $headers->removeHeader('cc');
            }
            if ($headers->has('bcc')) {
                $originalRecipient .= '; ' . $headers->get('bcc')->toString();
                $headers->removeHeader('bcc');
            }
            $headers->addHeaderLine('X-Original-Recipients', $originalRecipient);
            $mail->setTo($this->overrideRecipient);
        }

        if (!$headers->has('X-Mailer')) {
            $mailerHeader = new \Zend\Mail\Header\GenericHeader('X-Mailer', $this->getMailer());
            $headers->addHeader($mailerHeader);
            $mailerHeader->setEncoding('ASCII'); // get rid of other encodings for this header!
        }

        /* Allow HTMLTemplateMails to alter subject in the view script.
         * As the Zend Transport class build subject before the getBodyText call,
         * we have to call it here.
         */
        if ($mail instanceof \Core\Mail\HTMLTemplateMessage) {
            $mail->getBodyText();
        }

        $transport->send($mail);
    }

    /**
     * Gets the transport.
     *
     * @return TransportInterface $transport
     */
    public function getTransport()
    {
        return $this->transport;
    }

    /**
     * Sets the transport
     *
     * @param TransportInterface $transport
     *
     * @return self
     */
    public function setTransport(TransportInterface $transport)
    {
        $this->transport = $transport;

        return $this;
    }

    /**
     * Gest the value of the X-Mailer header.
     *
     * @return string
     */
    public function getMailer()
    {
        return $this->mailer;
    }

    /**
     * Sets the value for the X-Mailer header
     *
     * @param string $mailer
     *
     * @return $this
     */
    public function setMailer($mailer)
    {
        $this->mailer = $mailer;

        return $this;
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @license MIT
 * @copyright  2013 - 2016 Cross Solution <http://cross-solution.de>
 */

/** */
namespace Core\Controller;

use Core\EventManager\EventManager;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

/**
 * Admin Dashboard controller.
 *
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 * @author Anthonius Munthi <me@itstoni.com>
 *
 * @since 0.25
 */
class AdminController extends AbstractActionController
{
    protected $adminControllerEvents;

    public function __construct(EventManager $eventManager)
    {
        $this->adminControllerEvents = $eventManager;
    }

    /**
     * Controls the admin dashboard page.
     *
     * @return ViewModel
     */
    public function indexAction()
    {
        /* @var \Core\EventManager\EventManager $events
         * @var AdminControllerEvent $event */
        $events = $this->adminControllerEvents;
        $event  = $events->getEvent(AdminControllerEvent::EVENT_DASHBOARD, $this);
        $events->trigger($event, $this);

        $model = new ViewModel();
        $widgets = [];
        foreach ($event->getViewModels() as $name => $child) {
            $model->addChild($child, $name);
            $widgets[] = $name;
        }

        $model->setVariable('widgets', $widgets);
        return $model;
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @license MIT
 * @copyright  2013 - 2017 Cross Solution <http://cross-solution.de>
 */

/** */
namespace Core\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;

/**
 * Manages a set of images which belongs together.
 *
 * @ODM\EmbeddedDocument
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 * @since 0.29
 */
class ImageSet implements ImageSetInterface
{
    use EntityTrait;

    /**
     * The id of this image set.
     *
     * @ODM\Field(type="string")
     * @var string
     */
    protected $id;

    /**
     * Images in this set.
     *
     * @ODM\ReferenceMany(discriminatorField="_entity", cascade="all", orphanRemoval=true)
     * @var Collection
     */
    protected $images;

    /**
     * @internal
     *      Creates a unique {@link $id} for this ImageSet
     */
    public function __construct()
    {
        $this->id = (string) new \MongoId();
    }

    /**
     * Provide convinient methods for get and set.
     *
     * - get<ImageKey> proxies to get(<imageKey>)
     * - set<ImageKey>($image) proxies to set(<imageKey>, $image)
     *
     * @param string $method
     * @param array $args
     *
     * @return $this|ImageInterface|null
     * @throws \BadMethodCallException
     */
    public function __call($method, $args)
    {
        if (0 === strpos($method, 'get')) {
            $key = lcfirst(substr($method, 3));
            $fallback = count($args) ? $args[0] : true;

            return $this->get($key, $fallback);
        }

        if (0 === strpos($method, 'set')) {
            if (1 > count($args)) {
                throw new \BadMethodCallException(sprintf(
                    'Missing argument 1 for "%s" in "%s"', $method, get_class($this)
                ));
            }
            $key = lcfirst(substr($method, 3));
            return $this->set($key, $args[0]);
        }

        throw new \BadMethodCallException(sprintf(
            'Unknown method "%s" in "%s"', $method, get_class($this)
        ));
    }

    /**
     * Clear all the images in this set.
     *
     * @return self
     */
    public function clear()
    {
        if ($this->images) {
            $this->images->clear();
        }

        return $this;
    }

    /**
     * @param Collection $images
     *
     * @return self
     */
    public function setImagesCollection(Collection $images)
    {
        $this->clear();
        $this->images = $images;

        return $this;
    }

    /**
     * Set images and permissions.
     *
     * Replaces the whole set!
     *
     * @param array                $images
     * @param PermissionsInterface $permissions
     *
     * @return self
     */
    public function setImages(array $images, PermissionsInterface $permissions = null)
    {
        $this->clear();

        foreach ($images as $prop => $image) {
            $this->set($prop, $image, /* check */ false);
        }

        if ($permissions) {
            $this->setPermissions($permissions);
        }

        return $this;
    }

    /**
     * @return ArrayCollection|Collection
     */
    protected function getImages()
    {
        if (!$this->images) {
            $this->images = new ArrayCollection();
        }

        return $this->images;
    }

    /**
     * Get an image
     *
     * If no image with the $key is found, the image with the key
     * self::ORIGINAL is returned. Unless self::ORIGINAL is requested
     * or $fallback is false - in that case NULL is returned.
     *
     * @param string $key
     * @param bool   $fallback true: Return ORIGINAL image, if not found.
     *
     * @return ImageInterface|null
     */
    public function get($key, $fallback = true)
    {
        foreach ($this->getImages() as $image) {
            /* @var ImageInterface $image */
            if ($key == $image->getKey()) {
                return $image;
            }
        }

        return !$fallback || self::ORIGINAL == $key ? null : $this->get(self::ORIGINAL);
    }

    /**
     * Set an image.
     *
     * Replaces any image with the same $key, unless $check is false.
     *
     * @param string         $key
     * @param ImageInterface $image
     * @param bool           $check
     *
     * @return self
     */
    public function set($key, ImageInterface $image, $check = true)
    {
        $images = $this->getImages();
        if ($check && ($img = $this->get($key))) {
            $images->removeElement($img);
        }

        $image->setBelongsTo($this->id);
        $image->setKey($key);

        $images->add($image);

        return $this;
    }

    /**
     * Set permissions for all images in this set.
     *
     * @param PermissionsInterface $permissions
     *
     * @return self
     */
    public function setPermissions(PermissionsInterface $permissions)
    {
        foreach ($this->getImages() as $file) {
            /* @var PermissionsInterface $filePermissions */
            /* @var \Core\Entity\FileInterface $file */
            $filePermissions = $file->getPermissions();
            $filePermissions->clear();
            $filePermissions->inherit($permissions);
        }

        return $this;
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
 * @license   MIT
 */

/** DoctrineMongoCursor.php */
namespace Core\Paginator\Adapter;

use Zend\Paginator\Adapter\AdapterInterface;
use Doctrine\ODM\MongoDB\Cursor;

/**
 * @license MIT
 * @link    http://www.doctrine-project.org/
 * @author  Roman Konz <roman@konz.me>
 */
class DoctrineMongoCursor implements AdapterInterface
{
    /**
     * @var \Doctrine\ODM\MongoDB\Cursor
     */
    protected $cursor;

    /**
     * Constructor
     *
     * @param Cursor $cursor
     */
    public function __construct(Cursor $cursor)
    {
        $this->cursor = $cursor;
    }

    /**
     * {@inheritDoc}
     */
    public function count()
    {
        return $this->cursor->count();
    }

    /**
     * {@inheritDoc}
     */
    public function getItems($offset, $itemCountPerPage)
    {
        return $this->cursor
                    ->skip($offset)
                    ->limit($itemCountPerPage)
                    ->toArray();
    }
}


<?php
/**
*
 */

namespace Core\Form\View\Helper\Element;

use Zend\Form\View\Helper\FormButton;
use Zend\Form\ElementInterface;
use Zend\Form\Exception;

class SpinnerButton extends FormButton
{
    /**
     * Render a form <input> element from the provided $element
     *
     * @param  ElementInterface $element
     * @throws Exception\DomainException
     * @return string
     */
    public function render(ElementInterface $element, $buttonContent = null)
    {
        $openTag = $this->openTag($element);

        if (null === $buttonContent) {
            $buttonContent = $element->getLabel();
            if (null === $buttonContent) {
                throw new Exception\DomainException(
                    sprintf(
                        '%s expects either button content as the second argument, ' .
                        'or that the element provided has a label value; neither found',
                        __METHOD__
                    )
                );
            }

            if (null !== ($translator = $this->getTranslator())) {
                $buttonContent = $translator->translate(
                    $buttonContent,
                    $this->getTranslatorTextDomain()
                );
            }
            $element->setLabel('');
        }

        $escape = $this->getEscapeHtmlHelper();
        $translator = $this->getTranslator();
        $buttonContent = '

 ' . $translator->translate('processing', $this->getTranslatorTextDomain()) . '

' . $escape($buttonContent) . '

';

        return $openTag . $buttonContent . $this->closeTag();
    }
}


<?php
/**
 * YAWIK
 * Core Module Bootstrap
 *
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
 * @license   MIT
 * @author Carsten Bleek <bleek@cross-solution.de>
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 * @author Miroslav Fedeleš <miroslav.fedeles@gmail.com>
 */

/** Core */
namespace Core;

use Core\Listener\AjaxRouteListener;
use Core\Options\ModuleOptions;
use Yawik\Composer\RequireDirectoryPermissionInterface;
use Yawik\Composer\RequireFilePermissionInterface;
use Zend\ModuleManager\Feature\ConsoleUsageProviderInterface;
use Zend\ModuleManager\ModuleEvent;
use Zend\ModuleManager\ModuleManager;
use Zend\Mvc\MvcEvent;
use Core\Listener\LanguageRouteListener;
use Core\Listener\AjaxRenderListener;
use Core\Listener\XmlRenderListener;
use Core\Listener\EnforceJsonResponseListener;
use Core\Listener\StringListener;
use Zend\ModuleManager\Feature\ConsoleBannerProviderInterface;
use Zend\Console\Adapter\AdapterInterface as Console;
use Core\Listener\ErrorHandlerListener;
use Core\Listener\NotificationAjaxHandler;
use Core\Listener\Events\NotificationEvent;
use Doctrine\ODM\MongoDB\Types\Type as DoctrineType;
use Zend\Stdlib\ArrayUtils;

/**
 * Bootstrap class of the Core module
 */
class Module implements
    ConsoleBannerProviderInterface,
    ConsoleUsageProviderInterface,
    RequireFilePermissionInterface,
    RequireDirectoryPermissionInterface
{
    const VERSION = '0.33.2';

    /**
     * @param ModuleOptions $options
     * @inheritdoc
     * @return array
     */
    public function getRequiredFileLists(ModuleOptions $options)
    {
        return [
            $options->getLogDir().'/yawik.log'
        ];
    }

    /**
     * @param ModuleOptions $options
     * @return array
     */
    public function getRequiredDirectoryLists(ModuleOptions $options)
    {
        return [
            $options->getConfigDir().'/autoload',
            $options->getCacheDir(),
            $options->getLogDir(),
            $options->getLogDir().'/tracy'
        ];
    }

    public function getConsoleBanner(Console $console)
    {
        $name = Application::getCompleteVersion();
        $width = $console->getWidth();
        return sprintf(
            "==%1\$s==\n%2\$s%3\$s\n**%1\$s**\n",
            str_repeat('-', $width - 4),
            str_repeat(' ', floor(($width - strlen($name)) / 2)),
            $name
        );
    }

    public function getConsoleUsage(Console $console)
    {
        return [
            'purge [--no-check] [--options=] <entity> [<id>]'  => 'Purge entities',
            'This command will load entities to be purged, checks the dependency of each and removes all entities completely from the',
            'database. However, called with no <entity> and options it will output a list of all available entity loaders and its options.',
            '',
            ['--no-check', 'Skip the dependency check and remove all entities and dependencies straight away.'],
            ['--options=STRING', 'JSON string represents options for the specific entity loader used.'],
            "",
            // assets-install info
            'assets-install [--symlink] [--relative] <target>' => 'Install assets in the given target',
            'The assets-install command will install assets in the given <target> directory. If no option given this command will copy assets into the target.',
            ['--symlink','This option will install assets using absolute symlink directory'],
            ['--relative','This option will install assets using relative symlink'],
            ""
        ];
    }

    /**
     * Sets up services on the bootstrap event.
     *
     * @internal
     *     Creates the translation service and a ModuleRouteListener
     *
     * @param MvcEvent $e
     * @throws \Doctrine\ODM\MongoDB\Mapping\MappingException
     */
    public function onBootstrap(MvcEvent $e)
    {
        // Register the TimezoneAwareDate type with DoctrineMongoODM
        // Use it in Annotations ( @Field(type="tz_date") )
        if (!DoctrineType::hasType('tz_date')) {
            DoctrineType::addType(
                'tz_date',
                '\Core\Repository\DoctrineMongoODM\Types\TimezoneAwareDate'
            );
        }

        $sm = $e->getApplication()->getServiceManager();
        $translator = $sm->get('translator'); // initialize translator!
        \Zend\Validator\AbstractValidator::setDefaultTranslator($translator);
        $eventManager        = $e->getApplication()->getEventManager();
        $sharedManager       = $eventManager->getSharedManager();

        if (!\Zend\Console\Console::isConsole()) {
            (new ErrorHandlerListener())->attach($eventManager);

            /* @var \Core\Options\ModuleOptions $options */
            $languageRouteListener = new LanguageRouteListener(
                $sm->get('Core/Locale'),
                $sm->get('Core/Options')
            );
            $languageRouteListener->attach($eventManager);

            $ajaxRenderListener = new AjaxRenderListener();
            $ajaxRenderListener->attach($eventManager);

            $ajaxRouteListener = $sm->get(AjaxRouteListener::class);
            $ajaxRouteListener->attach($eventManager);

            $xmlRenderListener = new XmlRenderListener();
            $xmlRenderListener->attach($eventManager);

            $enforceJsonResponseListener = new EnforceJsonResponseListener();
            $enforceJsonResponseListener->attach($eventManager);

            $stringListener = new StringListener();
            $stringListener->attach($eventManager);
        }

        $notificationListener = $sm->get('Core/Listener/Notification');
        $notificationListener->attachShared($sharedManager);
        $notificationAjaxHandler = new NotificationAjaxHandler();
        $eventManager->attach(MvcEvent::EVENT_DISPATCH, array($notificationAjaxHandler, 'injectView'), -20);
        $notificationListener->attach(NotificationEvent::EVENT_NOTIFICATION_HTML, array($notificationAjaxHandler, 'render'), -20);

        $eventManager->attach(
            MvcEvent::EVENT_DISPATCH_ERROR,
            function ($event) {
                if ($event instanceof MvcEvent) {
                    $application = $event->getApplication();

                    if ($application::ERROR_EXCEPTION == $event->getError()) {
                        $ex = $event->getParam('exception');
                        if (404 == $ex->getCode()) {
                            $event->setError($application::ERROR_CONTROLLER_NOT_FOUND);
                        }
                    }
                }
            },
            500
        );
        $eventManager->attach(
            MvcEvent::EVENT_DISPATCH,
            function ($event) use ($eventManager) {
                $eventManager->trigger('postDispatch', $event);
            },
            -150
        );

        $sm->get('Tracy')->startDebug();
    }

    /**
     * Loads module specific configuration.
     *
     * @return array
     */
    public function getConfig()
    {
        $config = include __DIR__ . '/../config/module.config.php';
        return $config;
    }

    /**
     * @param ModuleManager $manager
     */
    public function init(ModuleManager $manager)
    {
        $events = $manager->getEventManager();
        $events->attach(ModuleEvent::EVENT_MERGE_CONFIG, [$this,'onMergeConfig']);
    }

    /**
     * Manipulate configuration
     * @param ModuleEvent $event
     */
    public function onMergeConfig(ModuleEvent $event)
    {
        $listener = $event->getConfigListener();
        $config = $listener->getMergedConfig(false);

        // disable subsplit command if we not in main development
        if (
            isset($config['console'])
            && !$this->isInMainDevelopment()
            && isset($config['console']['router']['routes']['subsplit'])
        ) {
            unset($config['console']['router']['routes']['subsplit']);
        }

        $listener->setMergedConfig($config);
    }

    /**
     * Returns true if this module in the main development mode
     * @return bool
     */
    private function isInMainDevelopment()
    {
        return strpos(__DIR__, 'module/Core') !== false;
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
 * @license   MIT
 */

/** Notification.php */
namespace Core\Controller\Plugin;

use Core\Listener\NotificationListener;
use Zend\I18n\Translator\TranslatorAwareInterface;
use Zend\I18n\Translator\TranslatorAwareTrait;
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
use Zend\Mvc\Plugin\FlashMessenger\FlashMessenger;
use Core\Listener\Events\NotificationEvent;
use Core\Log\Notification\NotificationEntity;
use Core\Log\Notification\NotificationEntityInterface;

/**
 *
 *
 *
 * @todo   [MG]: this needs to be heavily refactored! It's a PITA to test!
 */
class Notification extends AbstractPlugin implements TranslatorAwareInterface
{
    use TranslatorAwareTrait;

    const NAMESPACE_INFO = 'info';
    const NAMESPACE_WARNING = 'warning';
    const NAMESPACE_DANGER  = 'danger';
    const NAMESPACE_SUCCESS  = 'success';

    protected $namespace2priority = array(
        self::NAMESPACE_INFO => NotificationEntity::INFO,
        self::NAMESPACE_SUCCESS => NotificationEntity::NOTICE,
        self::NAMESPACE_WARNING => NotificationEntity::WARN,
        self::NAMESPACE_DANGER => NotificationEntity::ERR,
    );

    protected $priority2namespace = array(
        NotificationEntity::EMERG => self::NAMESPACE_DANGER,
        NotificationEntity::ALERT => self::NAMESPACE_DANGER,
        NotificationEntity::CRIT => self::NAMESPACE_DANGER,
        NotificationEntity::ERR => self::NAMESPACE_DANGER,
        NotificationEntity::WARN => self::NAMESPACE_WARNING,
        NotificationEntity::NOTICE => self::NAMESPACE_SUCCESS,
        NotificationEntity::INFO => self::NAMESPACE_INFO,
        NotificationEntity::DEBUG => self::NAMESPACE_INFO,
    );

    protected $namespace = self::NAMESPACE_INFO;

    protected $flashMessenger;

    /**
     * @var NotificationListener
     */
    protected $notificationListener;

    public function __construct(FlashMessenger $flashMessenger)
    {
        $this->flashMessenger = $flashMessenger;
    }

    /**
     * attach a Listener, that is liable for storing the notifications
     * @param $listener
     */
    public function setListener($listener)
    {
        $listener->getSharedManager()->attach('*', NotificationEvent::EVENT_NOTIFICATION_HTML, array($this,'createOutput'), 1);
        $this->notificationListener = $listener;
    }

    public function __invoke($message = null, $namespace = self::NAMESPACE_INFO)
    {
        if (null === $message) {
            return $this;
        }
        return $this->addMessage($message, $namespace);
    }

    /**
     * send a message to the notification-handler
     * @param $message
     * @param string $namespace
     * @return $this
     */
    public function addMessage($message, $namespace = self::NAMESPACE_INFO)
    {
        if (!$message instanceof NotificationEntityInterface) {
            $messageText = $this->isTranslatorEnabled()
                ? $this->getTranslator()->translate($message, $this->getTranslatorTextDomain())
                : $message;

            $message = new NotificationEntity();
            $message->setNotification($messageText);
            $message->setPriority($this->namespace2priority[$namespace]);
        }
        $nEvent = new NotificationEvent();
        $nEvent->setNotification($message);
        $this->notificationListener->trigger(NotificationEvent::EVENT_NOTIFICATION_ADD, $nEvent);

        return $this;
    }

    public function info($message)
    {
        return $this->addMessage($message, self::NAMESPACE_INFO);
    }

    public function warning($message)
    {
        return $this->addMessage($message, self::NAMESPACE_WARNING);
    }

    public function success($message)
    {
        return $this->addMessage($message, self::NAMESPACE_SUCCESS);
    }

    public function danger($message)
    {
        return $this->addMessage($message, self::NAMESPACE_DANGER);
    }

    public function error($message)
    {
        return $this->addMessage($message, self::NAMESPACE_DANGER);
    }

    public function createOutput(NotificationEvent $event)
    {
        $notifications = $event->getTarget()->getNotifications();
        if (is_array($notifications) && !empty($notifications)) {
            foreach ($notifications as $notification) {
                $this->renderMessage($notification->getNotification(), $this->priority2namespace[$notification->getPriority()]);
            }
        }
        return $this;
    }

    public function renderMessage($message, $namespace = self::NAMESPACE_INFO)
    {
        $origNamespace = $this->flashMessenger->getNamespace();
        $this->flashMessenger
            ->setNamespace($namespace)
            ->addMessage($message)
            ->setNamespace($origNamespace);

        return $this;
    }
}


<?php
/**
 * @filesource
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
 * @license MIT
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 * @author Miroslav Fedeleš <miroslav.fedeles@gmail.com>
 */
namespace Core\Listener;

use Core\Options\ModuleOptions;
use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\ListenerAggregateInterface;
use Zend\Mvc\MvcEvent;
use Zend\Mvc\Application;
use Zend\Router\Http\RouteMatch;
use Locale;
use Core\I18n\Locale as LocaleService;

/**
 * Class LanguageRouteListener
 *
 * @package Core\Listener
 * @authro Carsten Bleek <cbleek@yawik.org>
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 * @author Miroslav Fedeleš <miroslav.fedeles@gmail.com>
 * @author Anthonius Munthi <me@itstoni.com>
 */
class LanguageRouteListener implements ListenerAggregateInterface
{

    /**
     * @var \Zend\Stdlib\CallbackHandler[]
     */
    protected $listeners = array();

    /**
     * @var LocaleService
     */
    protected $localeService;

    /**
     * @var ModuleOptions
     */
    protected $moduleOptions;

    /**
     * LanguageRouteListener constructor.
     *
     * @param LocaleService $localeService
     * @param ModuleOptions $moduleOptions
     */
    public function __construct(LocaleService $localeService, ModuleOptions $moduleOptions)
    {
        $this->localeService = $localeService;
        $this->moduleOptions = $moduleOptions;
    }

    /**
     * Attach to an event manager
     *
     * @param  EventManagerInterface $events
     * @param  integer $priority
     */
    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $this->listeners[] = $events->attach(MvcEvent::EVENT_ROUTE, array($this, 'onRoute'), $priority);
        $this->listeners[] = $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, array($this, 'onDispatchError'), $priority);
    }

    /**
     * Detach all our listeners from the event manager
     *
     * @param  EventManagerInterface $events
     * @return void
     */
    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $listener) {
            if ($events->detach($listener)) {
                unset($this->listeners[$index]);
            }
        }
    }

    /**
     * Listen to the "route" event
     *
     * @param  MvcEvent $e
     * @return null
     */
    public function onRoute(MvcEvent $e)
    {
        $routeMatch = $e->getRouteMatch();
        if (0 !== strpos($routeMatch->getMatchedRouteName(), 'lang')) {
            // We do not have a language enabled route here.
            // but we need to provide a language to the navigation container
            $lang = $this->detectLanguage($e);
            $this->setLocale($e, $lang);
            return;
        }
        $language = $routeMatch->getParam('lang', '__NOT_SET__');
        if ($this->localeService->isLanguageSupported($language)) {
            $this->setLocale($e, $language);
        } else {
            $e->setError(Application::ERROR_ROUTER_NO_MATCH);
            $e->setTarget($this);
            $eventManager = $e->getApplication()->getEventManager();
            $eventManager->setEventPrototype($e);
            $result = $eventManager->trigger(MvcEvent::EVENT_DISPATCH_ERROR, $e);

            return $result->last();
        }
    }

    public function onDispatchError(MvcEvent $e)
    {
        if ($e->getRequest() instanceof \Zend\Console\Request
            || Application::ERROR_ROUTER_NO_MATCH != $e->getError()
        ) {
            return;
        }

        $router = $e->getRouter();
        $basePath=$router->getBaseUrl();
        $match = [];

        if (preg_match('~^' . $basePath . '/([a-z]{2})(?:/|$)~', $e->getRequest()->getRequestUri(), $match)) {
            /* It seems we have already a language in the URI
             * Now there are two possibilities:
             *
             * 1: The Language is not supported
             *    -> set translator locale to browser locale if supported
             *       or default. Do not forget to set the appropriate route param 'lang'
             *
             * 2: Language is supported, but the rest of the route
             *    does not match
             *    -> set translator locale to provided language
             */

            $lang = $this->localeService->isLanguageSupported($match[1])
                  ? $match[1]
                  : $this->detectLanguage($e);

            $this->setLocale($e, $lang);
            return;
        }

        /* We have no language key in the URI
         * Let's prepend the browser language locale if supported or
         * the default to the URI.
         *
         * If a route matches this prepended URI, we do a redirect,
         * else we set the translator locale and let the event propagate
         * to the ROUTE_NO_MATCH error renderer.
         */
        $request = clone $e->getRequest(); // clone the request, because maybe we
        $origUri = str_replace($basePath, '', $request->getRequestUri());

        $options = $this->moduleOptions;
        // using default language if detect language is disabled
        $lang = $options->isDetectLanguage() ? $this->detectLanguage($e):$options->getDefaultLanguage();
        $langUri = rtrim("$basePath/$lang$origUri", '/');
        if ($router->match($request->setUri($langUri)) instanceof RouteMatch) {
            $e->stopPropagation(true);
            //$e->setError(false);
            return $this->redirect($e->getResponse(), $langUri);
        }

        $this->setLocale($e, $lang);
    }

    /**
     * @param MvcEvent $e
     * @return string
     */
    protected function detectLanguage(MvcEvent $e)
    {
        $auth = $e->getApplication()
            ->getServiceManager()
            ->get('AuthenticationService');
        $user = $auth->hasIdentity() ? $auth->getUser() : null;

        return $this->localeService->detectLanguage($e->getRequest(), $user);
    }

    /**
     * @param $response
     * @param $uri
     *
     * @return mixed
     */
    protected function redirect($response, $uri)
    {
        $response->setStatusCode(302);
        $response->getHeaders()->addHeaderline('Location', $uri);
        return $response;
    }

    /**
     * @param MvcEvent $e
     * @param          $lang
     */
    protected function setLocale(MvcEvent $e, $lang)
    {
        $translator = $e->getApplication()->getServiceManager()->get('translator');
        $locale = $this->localeService->getLocaleByLanguage($lang);

        setlocale(
            LC_ALL,
            array(
            $locale . ".utf8",
            $locale . ".iso88591",
            $locale,
            substr($locale, 0, 2),
            'de_DE.utf8',
            'de_DE',
            'de'
            )
        );
        Locale::setDefault($locale);

        $translator->setLocale($locale);
        $translator->setFallbackLocale(substr($locale, 0, 2));
        $routeMatch = $e->getRouteMatch();
        if ($routeMatch && $routeMatch->getParam('lang') === null) {
            $routeMatch->setParam('lang', $lang);
        }
        $e->getRouter()->setDefaultParam('lang', $lang);
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @license MIT
 * @copyright  2013 - 2016 Cross Solution <http://cross-solution.de>
 */

/** */
namespace Core\Controller\Plugin;

use Zend\Mvc\Controller\Plugin\AbstractPlugin;
use Zend\Stdlib\Parameters;

/**
 * Collects pagination related configuration and passes it to the appropriate
 * controller plugin.
 *
 * In the controller, you only have to call one plugin to do all the YAWIK pagination magic.
 *
 * @see \Core\Controller\Plugin\PaginationParams
 * @see \Core\Controller\Plugin\SearchForm
 * @see \Core\Controller\Plugin\CreatePaginator
 *
 *
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 * @since 0.25
 */
class PaginationBuilder extends AbstractPlugin
{

    /**
     * The internal configuration stack.
     *
     * @var array
     */
    protected $stack = [];

    /**
     * The generated result array.
     *
     * @var array
     */
    protected $result = [];

    /**
     * Internal parameters.
     *
     * @var Parameters
     */
    protected $parameters;

    /**
     * Entry point.
     *
     * if $stack is provided, the internal stack is set to exact that value, so
     * please be sure what you're doing.
     *
     * If you pass a boolean TRUE as $stack, the internal stack is reset.
     *
     * @param null|array|bool $stack
     * @param bool $returnResult Should the result be immediately be returned instead of
     *                           self. Only affective when $stack is an array.
     *
     * @return self|array
     * @throws \InvalidArgumentException
     */
    public function __invoke($stack = null, $returnResult = true)
    {
        if (true === $stack) {
            $this->stack = [];
            return $this;
        }

        if (null === $stack) {
            return $this;
        }

        if (!is_array($stack)) {
            throw new \InvalidArgumentException('Expected argument to be of type array, but received ' . gettype($stack));
        }

        $stack = array_intersect_key($stack, ['params' => true, 'form' => true, 'paginator' => true]);
        foreach ($stack as $method => $args) {
            if (isset($args['as'])) {
                array_push($args, $args['as']);
                unset($args['as']);
            }
            call_user_func_array([$this, $method], $args);
        }

        return $returnResult ? $this->getResult() : $this;
    }

    /**
     * Add arguments for the call to the CreatePaginator plugin.
     *
     * @see \Core\Controller\Plugin\CreatePaginator::__invoke()
     *
     * @param string       $paginatorName
     * @param array  $defaultParams
     * @param string $as The name of the key in the result array.
     *
     * @return self
     */
    public function paginator($paginatorName, $defaultParams = [], $as = 'paginator')
    {
        if (is_string($defaultParams)) {
            $as = $defaultParams;
            $defaultParams = [];
        }

        $this->stack['paginator'] = ['as' => $as, $paginatorName, $defaultParams];
        return $this;
    }

    /**
     * Add arguments for the call to the SearchForm plugin.
     *
     * @see \Core\Controller\Plugin\SearchForm::get()
     *
     * @param        $elementsFieldset
     * @param null   $buttonsFieldset
     * @param string $as The name of the key in the result array.
     *
     * @return self
     */
    public function form($form, $options = null, $as = 'searchform')
    {
        if (is_string($options)) {
            $as = $options;
            $options = null;
        }

        $this->stack['form'] = ['as' => $as, $form, $options];
        return $this;
    }

    /**
     * Add arguments for the call to the PaginatorParams plugin.
     *
     * @see \Core\Controller\Plugin\PaginationParams::getParams()
     *
     * @param       $namespace
     * @param array $defaults
     *
     * @return self
     */
    public function params($namespace, $defaults = [ 'page' => 1 ])
    {
        $this->stack['params'] = [$namespace, $defaults];
        return $this;
    }

    /**
     * Calls the stacked plugins in the right order and returns the result array.
     *
     * The returned array can directly be returned from the controller or be used to populate a
     * view model.
     *
     * The search form plugin is only called (and thus the form only present in the result array)
     * if the request is NOT an ajax request. (as the  form is never rerendered on ajax requests)
     *
     * @param null|string $paginatorAlias Name of the paginator in the result array
     * @param null|string $formAlias Name of the search form in the result array
     *
     * @return array
     */
    public function getResult($paginatorAlias = null, $formAlias = null)
    {
        if (null === $paginatorAlias) {
            $paginatorAlias = isset($this->stack['paginator']['as'])
                            ? $this->stack['paginator']['as']
                            : 'paginator';
        }

        if (null === $formAlias) {
            $formAlias = isset($this->stack['form']['as']) ? $this->stack['form']['as'] : 'searchform';
        }

        /* @var \Zend\Mvc\Controller\AbstractController $controller
         * @var \Zend\Http\Request $request */
        $result = [];
        $controller = $this->getController();
        $request = $controller->getRequest();

        $this->setParameters($request->getQuery());

        if (isset($this->stack['params'])) {
            $this->callPlugin('paginationParams', $this->stack['params']);
        }

        if (isset($this->stack['form'])) {
            $form = $this->callPlugin('searchform', $this->stack['form']);
            if (!$request->isXmlHttpRequest()) {
                $result[$formAlias] = $form;
            }
        }

        if (isset($this->stack['paginator'])) {
            $result[$paginatorAlias] = $this->callPlugin('paginator', $this->stack['paginator']);
        }

        return $result;
    }

    /**
     * Calls an invokable controller plugin.
     *
     * @param string $name
     * @param array $args
     *
     * @return mixed The return value of the called plugin.
     */
    protected function callPlugin($name, $args)
    {
        /* @var \Zend\Mvc\Controller\AbstractController $controller */
        $controller = $this->getController();
        $plugin = $controller->plugin($name);

        /* We remove the array entry with the key "as" here.
         * because we want to keep it in the stack array */
        unset($args['as']);

        /* Inject the internal parameters as last argument.
         * This is needed to prevent messing with the original query params. */
        array_push($args, $this->parameters);

        return call_user_func_array($plugin, $args);
    }

    protected function setParameters($query)
    {
        $queryArray = $query->toArray();

        foreach ($queryArray as $key => $value) {
            if (preg_match('~^(?<separator>\W|_)(?<setArrayKeys>\W|_)?(?<name>.*)$~', $key, $match)) {
                $value = explode($match['separator'], $value);
                if ('' !== $match['setArrayKeys']) {
                    foreach ($value as $v) {
                        $queryArray[$match['name']][$v] = 1;
                    }
                } else {
                    $queryArray[ $match[ 'name' ] ] = $value;
                }
                unset($queryArray[$key]);
            }
        }

        $this->parameters = new Parameters($queryArray);
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
 * @license   MIT
 */

/** Core Entitys */
namespace Core\Entity;

use Core\Entity\Exception\OutOfBoundsException;

/**
 * Concrete implementation of \Core\Entity\EntityInterface.
 *
 * Provides some magic function for accessing properties
 * as class members, mirroring these calls to the
 * getter and setter methods.
 *
 */
abstract class AbstractEntity implements EntityInterface
{
    use EntityTrait;

    /**
     * Sets a property through the setter method.
     *
     * An exception is raised, when no setter method exists.
     *
     * @deprecated since 0.25 Use setter method directly.
     * @param string $property
     * @param mixed $value
     * @return mixed
     * @throws OutOfBoundsException
     */
    public function __set($property, $value)
    {
        trigger_error(
            sprintf(
                'Accessing entity properties is deprecated. Use setter method instead. ( Tried to access "%s" on %s )',
                $property,
                get_class($this)
            ),
            E_USER_DEPRECATED
        );
        $method = "set$property";
        if (method_exists($this, $method)) {
            return $this->$method($value);
        }

        throw new OutOfBoundsException("'$property' is not a valid property of '" . get_class($this). "'");
    }

    /**
     * Gets a property through the getter method.
     *
     * An exception is raised, when no getter method exists.
     *
     * @deprecated since 0.25 use getter method directly.
     * @param string $property
     * @return mixed
     * @throws OutOfBoundsException
     */
    public function __get($property)
    {
        $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
        trigger_error(
            sprintf(
                'Accessing entity properties is deprecated. Use getter method instead. ( Tried to access "%s" on %s in %s on line %s )',
                $property,
                get_class($this),
                $trace[0]['file'],
                $trace[0]['line']
            ),
            E_USER_DEPRECATED
        );
        $method = "get$property";
        if (method_exists($this, $method)) {
            return $this->$method();
        }
        throw new OutOfBoundsException("'$property' is not a valid property of '" . get_class($this) . "'");
    }

    /**
     * Checks if a property exists and has a non-empty value.
     *
     * If the property is an array, the check will return, if this
     * array has items or not.
     *
     * @deprecated since 0.25 Use {@link notEmpty()}
     * @param string $property
     * @return boolean
     */
    public function __isset($property)
    {
        trigger_error(
            sprintf(
                'Using isset() with entity properties is deprecated. Use %s::notEmpty("%s") instead.',
                get_class($this),
                $property
            ),
            E_USER_DEPRECATED
        );
        return $this->notEmpty($property);
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @license MIT
 * @copyright  2013 - 2016 Cross Solution <http://cross-solution.de>
 */

/** */
namespace Core\EventManager;

use Zend\EventManager\EventInterface;
use Zend\EventManager\EventManager as ZfEventManager;

/**
 * EventManager extension which allows creating event instances.
 *
 * Also allows calling of trigger() and triggerUntil() with event instances.
 *
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 * @since 0.25
 * @since 0.30 - ZF3 compatibility
 */
class EventManager extends ZfEventManager implements EventProviderInterface
{
    public function getEvent($name = null, $target = null, $params = null)
    {
        $event = clone $this->eventPrototype;

        if (is_array($name)) {
            $params = $name;
            $name = null;
        } elseif (is_array($target)) {
            $params = $target;
            $target = null;
        }

        if (!$name && isset($params['name'])) {
            $name = $params['name'];
            unset($params['name']);
        }

        if (!$target && isset($params['target'])) {
            $target = $params['target'];
            unset($params['target']);
        }

        $event->setName($name);
        if (null !== $target) {
            $event->setTarget($target);
        }
        if (null !== $params) {
            $event->setParams($params);
        }

        return $event;
    }

    /**
     * Trigger an event.
     *
     * If no event instance is passed, it creates one prior to triggering.
     *
     * @param EventInterface|string $eventName
     * @param object|string|null $target
     * @param array $argv
     *
     * @return \Zend\EventManager\ResponseCollection
     */
    public function trigger($eventName, $target = null, $argv = [])
    {
        $event = $eventName instanceof EventInterface
            ? $eventName
            : $this->getEvent($eventName, $target, $argv);

        return $this->triggerListeners($event);
    }

    /**
     * Trigger an event, applying a callback to each listener's result
     *
     * If no event instance is passed, it creates one prior to triggering.
     *
     * @param callable $callback
     * @param EventInterface|string   $eventName
     * @param object|string|null     $target
     * @param array    $argv
     *
     * @return \Zend\EventManager\ResponseCollection
     */
    public function triggerUntil(callable $callback, $eventName, $target = null, $argv = [])
    {
        $event = $eventName instanceof EventInterface
            ? $eventName
            : $this->getEvent($eventName, $target, $argv);

        return $this->triggerListeners($event, $callback);
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @license MIT
 * @copyright  2013 - 2017 Cross Solution <http://cross-solution.de>
 */

/** */
namespace Core\Listener\Events;

use Zend\EventManager\Event;
use Zend\Http\Request;
use Zend\Http\Response;

/**
 * Ajax route event
 *
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 * @since 0.29
 */
class AjaxEvent extends Event
{
    /**#@+
     * Response content types.
     * @var string
     */
    const TYPE_HTML = 'text/html';
    const TYPE_JSON = 'application/json';
    const TYPE_TEXT = 'text/plain';

    /**#@-*/

    /**
     * The mvc request object
     *
     * @var Request
     */
    private $request;

    /**
     * The mvc response object
     *
     * @var Response
     */
    private $response;

    /**
     * The result.
     *
     * @var mixed|array|\Traversable
     */
    private $result;

    /**
     * The response content type.
     *
     * @var string
     */
    private $contentType;

    /**
     * Set the content type used in the response header.
     *
     * @param string $contentType
     *
     * @return self
     */
    public function setContentType($contentType)
    {
        $this->setParam('contentType', $contentType);
        $this->contentType = $contentType;

        return $this;
    }

    /**
     * Get the content type.
     *
     * @return string
     */
    public function getContentType()
    {
        if (!$this->contentType) {
            $this->setContentType($this->getParam('contentType') ?: static::TYPE_JSON);
        }

        return $this->contentType;
    }

    /**
     * Set the mvc request.
     *
     * @param Request $request
     *
     * @return self
     */
    public function setRequest(Request $request)
    {
        $this->setParam('request', $request);
        $this->request = $request;

        return $this;
    }

    /**
     * Get the mvc request.
     *
     * @return Request
     */
    public function getRequest()
    {
        return $this->request ?: $this->getParam('request');
    }

    /**
     * Set the mvc response
     *
     * @param Response $response
     *
     * @return self
     */
    public function setResponse(Response $response)
    {
        $this->setParam('response', $response);
        $this->response = $response;

        return $this;
    }

    /**
     * Get the mvc response
     *
     * @return Response
     */
    public function getResponse()
    {
        return $this->response ?: $this->getParam('response');
    }

    /**
     * Set the result.
     *
     * @param mixed|array|\Traversable $result
     *
     * @return self
     */
    public function setResult($result)
    {
        $this->setParam('result', $result);
        $this->result = $result;

        return $this;
    }

    /**
     * Get the result.
     *
     * @return mixed|array|\Traversable
     */
    public function getResult()
    {
        return $this->result ?: $this->getParam('result');
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @copyright (c) 2013 - 2016 Cross Solution (http://cross-solution.de)
 * @license   MIT
 */

namespace Core\Form;

use Zend\Form\Fieldset;

/**
 * Class LocalizationSettingsFieldset
 *
 * @package Core\Form
 */
class LocalizationSettingsFieldset extends Fieldset
{
    /**
     * Initialize the Sele
     */
    public function init()
    {
        $this->setLabel('general settings');

        $this->add(
            array(
                'type' => 'Core\Form\Element\Select',
                'name' => 'language',
                'options' => array(
                        'label' => /* @translate */ 'choose your language',
                        'value_options' => array(
                                'en' => /* @translate */ 'English',
                                'fr' => /* @translate */ 'French',
                                'de' => /* @translate */ 'German',
                                'it' => /* @translate */ 'Italian',
                                'po' => /* @translate */ 'Polish',
                                'ru' => /* @translate */ 'Russian',
                                'tr' => /* @translate */ 'Turkish',
                                'es' => /* @translate */ 'Spanish',
                        ),
                        'description' => /* @translate */ 'defines the languages of this frontend.'
                ),
            )
        );

        $timezones=array_merge(
            \DateTimeZone::listIdentifiers(\DateTimeZone::AFRICA),
            \DateTimeZone::listIdentifiers(\DateTimeZone::AMERICA),
            \DateTimeZone::listIdentifiers(\DateTimeZone::ASIA),
            \DateTimeZone::listIdentifiers(\DateTimeZone::ATLANTIC),
            \DateTimeZone::listIdentifiers(\DateTimeZone::AUSTRALIA),
            \DateTimeZone::listIdentifiers(\DateTimeZone::EUROPE),
            \DateTimeZone::listIdentifiers(\DateTimeZone::INDIAN),
            \DateTimeZone::listIdentifiers(\DateTimeZone::PACIFIC)
        );

        $this->add(
            array(
                'type' => 'Core\Form\Element\Select',
                'name' => 'timezone',
                'options' => array(
                        'label' => /* @translate */ 'choose your timzone',
                        'value_options' => $timezones,
                        'description' => /* @translate */ 'defines your local timezone.'
                ),
            )
        );
    }
}


<?php
/**
 * YAWIK
 *
 * @filesource
 * @license MIT
 * @copyright  2013 - 2016 Cross Solution <http://cross-solution.de>
 */

/** */
namespace Core\Factory\Paginator;

use Core\Paginator\PaginatorService;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\AbstractFactoryInterface;
//use Zend\ServiceManager\MutableCreationOptionsInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

/**
 * Abstract factory to create paginators from an entity repository.
 *
 * The main purpose of this class is to be able to quickly create paginators over an entity set,
 * without having to create factories and paginator classes.
 *
 * To work out of the box, there are a few assumptions:
 *
 * * The name of the paginator service must be a name also recognized by the repository service manager.
 *   (e.g. Namespace/EntityName). It can be prefixed with 'Repository/'. (e.g. Repository/Namespace/EntityName)
 *
 * * If you want to filter the query, there must be a filter in the filter manager with the name of the
 *   requested paginator prepended with 'PaginationQuery/' (e.g. PaginationQuery/Namespace/EntityName)
 *
 * * The options given to this factory through the service manager are passed AS IS to the filters' filter
 *   method. The second parameter to the filter is the QueryBuilder object for the specified entity (repository)
 *
 * There is currently one minor issue:
 *
 * * If you want to use more than one paginator for the same repository (with different options), you have to
 *   set the particular name in the 'shared' section of the paginator manager config in your module config file
 *   and assign it the value false.
 *   Example:
 *
 *

 *      'paginator_manager' => [
 *          'shared' => [
 *              'Repository/Namespace/EntityName' => false,
 *          ],
 *      ],
 *

 *
 * @author Mathias Gelhausen <gelhausen@cross-solution.de>
 * @author Anthonius Munthi <me@itstoni.com>
 * @TODO    [ZF3] fix remove implementation of MutableCreationOptionsInterface
 * @since 0.24
 */
class RepositoryAbstractFactory implements AbstractFactoryInterface
{
    /**
     * Create a new Paginator instance
     *
     * @param   ContainerInterface  $container
     * @param   string              $requestedName
     * @param   array|null          $options
     * @return  \Zend\Paginator\Paginator
     */
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        /**
         * @var $repositories \Core\Repository\RepositoryService
         * @var $filter       \Zend\Filter\FilterInterface
         * @var $container PaginatorService
         */
        $repositories = $container->get('repositories');
        $queryBuilder = $repositories->createQueryBuilder();

        $queryBuilder->find($this->getEntityClassName($requestedName));

        $filterManager = $container->get('FilterManager');
        $filterName    = 'PaginationQuery/' . $requestedName;

        if ($filterManager->has($filterName)) {
            $filter       = $filterManager->get('PaginationQuery/' . $requestedName);
            $queryBuilder = $filter->filter($options, $queryBuilder);
        }

        $cursor    = $queryBuilder->getQuery()->execute();
        $adapter   = new \Core\Paginator\Adapter\DoctrineMongoCursor($cursor);
        $paginator = new \Zend\Paginator\Paginator($adapter);

        return $paginator;
    }

    /**
     * Can the factory create an instance for the given $requestedName service
     *
     * @param ContainerInterface    $container
     * @param string                $requestedName
     * @param array|null            $options
     * @return bool
     */
    public function canCreate(ContainerInterface $container, $requestedName, array $options=null)
    {
        $class = $this->getEntityClassName($requestedName);

        return class_exists($class, true);
    }

    /**
     * Gets an entity class name from the requested service name.
     *
     * @param string $name
     *
     * @return string
     */
    protected function getEntityClassName($name)
    {
        $repositoryName = str_replace('Repository/', '', $name);
        $nameParts      = explode('/', $repositoryName);

        $namespace = $nameParts[0];
        $entity    = isset($nameParts[1]) ? $nameParts[1] : substr($namespace, 0, -1);
        $class     = "\\$namespace\\Entity\\$entity";

        return $class;
    }
}