<?php

namespace Gdbots\Pbj\Serializer;

use Gdbots\Pbj\Exception\DeserializeMessageFailed;
use Gdbots\Pbj\Message;

class JsonSerializer extends PhpArraySerializer
{
    /**
     * {@inheritdoc}
     */
    public function serialize(Message $message, array $options = [])
    {
        if (isset($options['json_encode_options'])) {
            return json_encode(parent::serialize($message, $options), $options['json_encode_options']);
        }

        return json_encode(parent::serialize($message, $options));
    }

    /**
     * {@inheritdoc}
     *
     * @return Message
     */
    public function deserialize($data, array $options = [])
    {
        if (!is_array($data)) {
            $data = json_decode($data, true);
            if (JSON_ERROR_NONE !== json_last_error()) {
                throw new DeserializeMessageFailed($this->getLastErrorMessage());
            }
        }

        return parent::deserialize($data, $options);
    }

    /**
     * Resolves json_last_error message.
     *
     * @return string
     */
    private function getLastErrorMessage()
    {
        if (function_exists('json_last_error_msg')) {
            return json_last_error_msg();
        }

        switch (json_last_error()) {
            case JSON_ERROR_DEPTH:
                return 'Maximum stack depth exceeded';
            case JSON_ERROR_STATE_MISMATCH:
                return 'Underflow or the modes mismatch';
            case JSON_ERROR_CTRL_CHAR:
                return 'Unexpected control character found';
            case JSON_ERROR_SYNTAX:
                return 'Syntax error, malformed JSON';
            case JSON_ERROR_UTF8:
                return 'Malformed UTF-8 characters, possibly incorrectly encoded';
            default:
                return 'Unknown error';
        }
    }
}


<?php

namespace Gdbots\Pbj\Type;

use Gdbots\Common\Util\NumberUtils;
use Gdbots\Pbj\Assertion;
use Gdbots\Pbj\Codec;
use Gdbots\Pbj\Exception\DecodeValueFailed;
use Gdbots\Pbj\Field;

abstract class AbstractBinaryType extends AbstractType
{
    private $decodeFromBase64 = true;
    private $encodeToBase64 = true;

    /**
     * @param bool $useBase64
     */
    public function decodeFromBase64($useBase64)
    {
        $this->decodeFromBase64 = (bool) $useBase64;
    }

    /**
     * @param bool $useBase64
     */
    public function encodeToBase64($useBase64)
    {
        $this->encodeToBase64 = (bool) $useBase64;
    }

    /**
     * {@inheritdoc}
     */
    public function guard($value, Field $field)
    {
        Assertion::string($value, null, $field->getName());

        // intentionally using strlen to get byte length, not mb_strlen
        $length = $this->encodeToBase64 ? strlen($this->encode($value, $field)) : strlen($value);
        $minLength = $field->getMinLength();
        $maxLength = NumberUtils::bound($field->getMaxLength(), $minLength, $this->getMaxBytes());
        $okay = $length >= $minLength && $length <= $maxLength;

        Assertion::true(
            $okay,
            sprintf(
                'Field [%s] must be between [%d] and [%d] bytes, [%d] bytes given.',
                $field->getName(),
                $minLength,
                $maxLength,
                $length
            ),
            $field->getName()
        );
    }

    /**
     * {@inheritdoc}
     */
    public function encode($value, Field $field, Codec $codec = null)
    {
        $value = trim($value);
        if ($value === '') {
            return null;
        }

        return $this->encodeToBase64 ? base64_encode($value) : $value;
    }

    /**
     * {@inheritdoc}
     */
    public function decode($value, Field $field, Codec $codec = null)
    {
        $value = trim((string) $value);
        if ($value === '') {
            return null;
        }

        if (!$this->decodeFromBase64) {
            return $value;
        }

        $value = base64_decode($value, true);

        if (false === $value) {
            throw new DecodeValueFailed($value, $field, 'Strict base64_decode failed.');
        }

        return $value;
    }

    /**
     * {@inheritdoc}
     */
    public function isBinary()
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function isString()
    {
        return true;
    }
}


<?php

namespace Gdbots\Pbj\Serializer;

use Gdbots\Common\Util\ArrayUtils;
use Gdbots\Pbj\Assertion;
use Gdbots\Pbj\Codec;
use Gdbots\Pbj\Enum\FieldRule;
use Gdbots\Pbj\Exception\GdbotsPbjException;
use Gdbots\Pbj\Exception\InvalidResolvedSchema;
use Gdbots\Pbj\Field;
use Gdbots\Pbj\Message;
use Gdbots\Pbj\MessageRef;
use Gdbots\Pbj\MessageResolver;
use Gdbots\Pbj\Schema;
use Gdbots\Pbj\SchemaId;
use Gdbots\Pbj\WellKnown\DynamicField;
use Gdbots\Pbj\WellKnown\GeoPoint;

class PhpArraySerializer implements Serializer, Codec
{
    /**
     * Options for the serializer to use, e.g. json encoding options,
     * 'includeAllFields' which includes fields even if they're not set, etc.
     *
     * @var array
     */
    protected $options;

    /**
     * {@inheritdoc}
     */
    public function serialize(Message $message, array $options = [])
    {
        $this->options = $options;
        return $this->doSerialize($message);
    }

    /**
     * {@inheritdoc}
     * @return Message
     */
    public function deserialize($data, array $options = [])
    {
        $this->options = $options;

        Assertion::keyIsset(
            $data,
            Schema::PBJ_FIELD_NAME,
            sprintf(
                '[%s::%s] Array provided must contain the [%s] key.',
                get_called_class(),
                __FUNCTION__,
                Schema::PBJ_FIELD_NAME
            )
        );

        return $this->doDeserialize($data);
    }

    /**
     * @param Message $message
     * @param Field $field
     *
     * @return mixed
     */
    public function encodeMessage(Message $message, Field $field)
    {
        return $this->doSerialize($message);
    }

    /**
     * @param mixed $value
     * @param Field $field
     *
     * @return Message
     */
    public function decodeMessage($value, Field $field)
    {
        return $this->doDeserialize($value);
    }

    /**
     * @param MessageRef $messageRef
     * @param Field $field
     *
     * @return mixed
     */
    public function encodeMessageRef(MessageRef $messageRef, Field $field)
    {
        return $messageRef->toArray();
    }

    /**
     * @param mixed $value
     * @param Field $field
     *
     * @return MessageRef
     */
    public function decodeMessageRef($value, Field $field)
    {
        return MessageRef::fromArray($value);
    }

    /**
     * @param GeoPoint $geoPoint
     * @param Field $field
     *
     * @return mixed
     */
    public function encodeGeoPoint(GeoPoint $geoPoint, Field $field)
    {
        return $geoPoint->toArray();
    }

    /**
     * @param mixed $value
     * @param Field $field
     *
     * @return GeoPoint
     */
    public function decodeGeoPoint($value, Field $field)
    {
        return GeoPoint::fromArray($value);
    }

    /**
     * @param DynamicField $dynamicField
     * @param Field $field
     *
     * @return mixed
     */
    public function encodeDynamicField(DynamicField $dynamicField, Field $field)
    {
        return $dynamicField->toArray();
    }

    /**
     * @param mixed $value
     * @param Field $field
     *
     * @return DynamicField
     */
    public function decodeDynamicField($value, Field $field)
    {
        return DynamicField::fromArray($value);
    }

    /**
     * @param Message $message
     *
     * @return array
     */
    private function doSerialize(Message $message)
    {
        $schema = $message::schema();
        $message->validate();

        $payload = [];
        // $includeAllFields = isset($this->options['includeAllFields']) && true === $this->options['includeAllFields'];

        foreach ($schema->getFields() as $field) {
            $fieldName = $field->getName();

            if (!$message->has($fieldName)) {
                // suspect this may not be needed at all.
                /*
                if ($includeAllFields || $message->hasClearedField($fieldName)) {
                    $payload[$fieldName] = null;
                }
                */

                continue;
            }

            $value = $message->get($fieldName);
            $type = $field->getType();

            switch ($field->getRule()->getValue()) {
                case FieldRule::A_SINGLE_VALUE:
                    $payload[$fieldName] = $type->encode($value, $field, $this);
                    break;

                case FieldRule::A_SET:
                case FieldRule::A_LIST:
                    $payload[$fieldName] = [];
                    foreach ($value as $v) {
                        $payload[$fieldName][] = $type->encode($v, $field, $this);
                    }
                    break;

                case FieldRule::A_MAP:
                    $payload[$fieldName] = [];
                    foreach ($value as $k => $v) {
                        $payload[$fieldName][$k] = $type->encode($v, $field, $this);
                    }
                    break;

                default:
                    break;
            }
        }

        return $payload;
    }

    /**
     * @param array $data
     * @return Message
     *
     * @throws \Exception
     * @throws GdbotsPbjException
     */
    private function doDeserialize(array $data)
    {
        $schemaId = SchemaId::fromString((string) $data[Schema::PBJ_FIELD_NAME]);
        $className = MessageResolver::resolveId($schemaId);

        /** @var Message $message */
        $message = new $className();
        Assertion::isInstanceOf($message, Message::class);

        if ($message::schema()->getCurieMajor() !== $schemaId->getCurieMajor()) {
            throw new InvalidResolvedSchema($message::schema(), $schemaId, $className);
        }

        $schema = $message::schema();

        foreach ($data as $fieldName => $value) {
            if (!$schema->hasField($fieldName)) {
                continue;
            }

            if (null === $value) {
                $message->clear($fieldName);
                continue;
            }

            $field = $schema->getField($fieldName);
            $type = $field->getType();

            switch ($field->getRule()->getValue()) {
                case FieldRule::A_SINGLE_VALUE:
                    $message->set($fieldName, $type->decode($value, $field, $this));
                    break;

                case FieldRule::A_SET:
                case FieldRule::A_LIST:
                    Assertion::isArray($value, sprintf('Field [%s] must be an array.', $fieldName), $fieldName);
                    $values = [];
                    foreach ($value as $v) {
                        $values[] = $type->decode($v, $field, $this);
                    }

                    if ($field->isASet()) {
                        $message->addToSet($fieldName, $values);
                    } else {
                        $message->addToList($fieldName, $values);
                    }
                    break;

                case FieldRule::A_MAP:
                    Assertion::true(
                        ArrayUtils::isAssoc($value),
                        sprintf('Field [%s] must be an associative array.', $fieldName),
                        $fieldName
                    );
                    foreach ($value as $k => $v) {
                        $message->addToMap($fieldName, $k, $type->decode($v, $field, $this));
                    }
                    break;

                default:
                    break;
            }
        }

        return $message->set(Schema::PBJ_FIELD_NAME, $schema->getId()->toString())->populateDefaults();
    }
}


<?php

namespace Nerdify\SmsGateway;

use Illuminate\Notifications\Notification;

class SmsGatewayChannel
{
    /**
     * The client instance.
     *
     * @var SmsGatewayClient
     */
    protected $client;

    /**
     * Create a new SMS Gateway channel instance.
     *
     * @param SmsGatewayClient $client
     */
    public function __construct(SmsGatewayClient $client)
    {
        $this->client = $client;
    }

    /**
     * Send the given notification.
     *
     * @param mixed        $notifiable
     * @param Notification $notification
     *
     * @return array|void
     */
    public function send($notifiable, Notification $notification)
    {
        $to = $this->getTo($notifiable);

        $message = $notification->toSmsGateway($notifiable);

        if (is_string($message)) {
            $message = new SmsGatewayMessage($message);
        }

        return $this->client->send($this->buildParams($message, $to));
    }

    /**
     * Get phone number.
     *
     * @param $notifiable
     *
     * @return mixed
     */
    protected function getTo($notifiable)
    {
        if ($to = $notifiable->routeNotificationFor('smsGateway')) {
            return $to;
        }

        return $notifiable->phone_number;
    }

    /**
     * Build up params.
     *
     * @param SmsGatewayMessage $message
     * @param string            $to
     *
     * @return array
     */
    protected function buildParams(SmsGatewayMessage $message, $to)
    {
        $optionalFields = array_filter([
            'expires_at' => data_get($message, 'expiresAt'),
            'send_at'    => data_get($message, 'sendAt'),
        ]);

        return array_merge([
            'number'     => $to,
            'message'    => trim($message->content),
        ], $optionalFields);
    }
}


<?php

namespace Gdbots\Pbj\Type;

use Gdbots\Pbj\Assertion;
use Gdbots\Pbj\Codec;
use Gdbots\Pbj\Field;
use Gdbots\Pbj\WellKnown\BigNumber;

final class BigIntType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function guard($value, Field $field)
    {
        /** @var BigNumber $value */
        Assertion::isInstanceOf($value, BigNumber::class, null, $field->getName());
        Assertion::true(
            !$value->isNegative(),
            sprintf('Field [%s] cannot be negative.', $field->getName()),
            $field->getName()
        );
        Assertion::true(
            $value->isLessThanOrEqualTo('18446744073709551615'),
            sprintf('Field [%s] cannot be greater than [18446744073709551615].', $field->getName()),
            $field->getName()
        );
    }

    /**
     * {@inheritdoc}
     */
    public function encode($value, Field $field, Codec $codec = null)
    {
        if ($value instanceof BigNumber) {
            return $value->getValue();
        }

        return '0';
    }

    /**
     * {@inheritdoc}
     */
    public function decode($value, Field $field, Codec $codec = null)
    {
        if (null === $value || $value instanceof BigNumber) {
            return $value;
        }

        return new BigNumber((string) $value);
    }

    /**
     * {@inheritdoc}
     */
    public function isScalar()
    {
        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function getDefault()
    {
        return new BigNumber(0);
    }

    /**
     * {@inheritdoc}
     */
    public function isNumeric()
    {
        return true;
    }
}


<?php

namespace Gdbots\Pbj\Type;

use Gdbots\Common\Enum;
use Gdbots\Pbj\Assertion;
use Gdbots\Pbj\Codec;
use Gdbots\Pbj\Exception\DecodeValueFailed;
use Gdbots\Pbj\Field;

final class IntEnumType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function guard($value, Field $field)
    {
        /** @var Enum $value */
        Assertion::isInstanceOf($value, Enum::class, null, $field->getName());
        Assertion::isInstanceOf($value, $field->getClassName(), null, $field->getName());
        Assertion::integer($value->getValue(), null, $field->getName());
        Assertion::range($value->getValue(), $this->getMin(), $this->getMax(), null, $field->getName());
    }

    /**
     * {@inheritdoc}
     */
    public function encode($value, Field $field, Codec $codec = null)
    {
        if ($value instanceof Enum) {
            return (int) $value->getValue();
        }

        return 0;
    }

    /**
     * {@inheritdoc}
     */
    public function decode($value, Field $field, Codec $codec = null)
    {
        if (null === $value) {
            return null;
        }

        /** @var Enum $className */
        $className = $field->getClassName();

        try {
            return $className::create((int) $value);
        } catch (\Exception $e) {
            throw new DecodeValueFailed($value, $field, $e->getMessage());
        }
    }

    /**
     * {@inheritdoc}
     */
    public function isScalar()
    {
        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function isNumeric()
    {
        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function getMin()
    {
        return 0;
    }

    /**
     * {@inheritdoc}
     */
    public function getMax()
    {
        return 65535;
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Component\Selector\Source;

use Elastica\Query;
use Yucca\Component\ConnectionManager;

/**
 * Class ElasticSearch
 * @package Yucca\Component\Selector\Source
 */
class ElasticSearch implements SelectorSourceInterface
{

    /**
     * @var \Yucca\Component\ConnectionManager
     */
    protected $connectionManager;

    /**
     * @param ConnectionManager $connectionManager
     */
    public function setConnectionManager(ConnectionManager $connectionManager)
    {
        $this->connectionManager = $connectionManager;
    }

    /**
     * @param array $criterias
     * @param array $options
     * @throws \Exception
     * @throws \Yucca\Component\Selector\Exception\NoDataException
     * @return string
     */
    public function loadIds(array $criterias, array $options = array())
    {
        //Merge options
        $defaultOptions = array(
            SelectorSourceInterface::ID_FIELD => array('id'),
            SelectorSourceInterface::FORCE_FROM_MASTER => false,
            SelectorSourceInterface::SHARDING_KEY_FIELD => '',
            SelectorSourceInterface::TABLE => '',
            SelectorSourceInterface::CONNECTION_NAME => '',
            SelectorSourceInterface::LIMIT => 10,
            SelectorSourceInterface::OFFSET => 0,
            SelectorSourceInterface::ORDERBY => null,
            SelectorSourceInterface::FACETS => array(),
            SelectorSourceInterface::RESULT => SelectorSourceInterface::RESULT_IDENTIFIERS,
        );
        $options = array_merge($defaultOptions, $options);

        $resultSetKey = $this->getResultSetKey(
            $options[SelectorSourceInterface::ELASTIC_QUERY],
            $options[SelectorSourceInterface::LIMIT],
            $options[SelectorSourceInterface::OFFSET],
            $options[SelectorSourceInterface::ORDERBY],
            $options[SelectorSourceInterface::FACETS]
        );

        //Check options
        if (empty($options[SelectorSourceInterface::ELASTIC_SEARCHABLE])) {
            throw new \Exception('Elastic searchable index or type must be set for selector source');
        }
        if (false === $options[SelectorSourceInterface::ELASTIC_SEARCHABLE] instanceof \Elastica\SearchableInterface) {
            throw new \Exception('Elastic searchable must be an instance of \Elastica\SearchableInterface');
        }
        if (empty($options[SelectorSourceInterface::ID_FIELD])) {
            throw new \Exception('Id Field must be set for selector source');
        }

        /**
         * @var $index \Elastica\SearchableInterface
         */
        $index = $options[SelectorSourceInterface::ELASTIC_SEARCHABLE];
        $query = $options[SelectorSourceInterface::ELASTIC_QUERY];
        if (false === ($query instanceof Query)) {
            $query = Query::create($query);
        }

        if (self::RESULT_COUNT !== $options[SelectorSourceInterface::RESULT]) {
            if (is_numeric($options[SelectorSourceInterface::LIMIT])) {
                $query->setSize(
                    (int) $options[SelectorSourceInterface::LIMIT]
                );
            }
            if (is_numeric($options[SelectorSourceInterface::OFFSET])) {
                $query->setFrom(
                    (int) $options[SelectorSourceInterface::OFFSET]
                );
            }

            $orders = $options[SelectorSourceInterface::ORDERBY];
            if (false === empty($orders) && is_array($orders)) {
                foreach ($orders as $order) {
                    $query->addSort($order);
                }
            }
        }

        if (false === empty($options[self::GROUPBY])) {
            throw new \Exception('Not implemented yet');
        }

        if (false === empty($options[self::FACETS])) {
            foreach ($options[self::FACETS] as $facet) {
                $query->addAggregation($facet);
            }
        }

        $resultSet = $index->search($query);

        //fields
        if (self::RESULT_COUNT === $options[SelectorSourceInterface::RESULT]) {
            return $resultSet->getTotalHits();
        } elseif (self::RESULT_IDENTIFIERS === $options[SelectorSourceInterface::RESULT]) {
            return $resultSet;
        } else {
            throw new \Exception('Unknown result type');
        }
    }

    /**
     * @param array $ids
     * @param array $criterias
     * @param array $options
     *
     * @throws \Exception
     */
    public function saveIds($ids, array $criterias, array $options = array())
    {
        throw new \Exception("ElasticSearch selector source can't save result");
    }

    /**
     * @param array $options
     */
    public function invalidateGlobal(array $options = array())
    {
    }

    /**
     * @param $query
     * @param $limit
     * @param $offset
     * @param $orderBy
     * @param $facets
     *
     * @return string
     */
    protected function getResultSetKey($query, $limit, $offset, $orderBy, $facets)
    {
        $facetsParams = array();
        foreach ($facets as $facet) {
            $facetsParams[] = $facet->getParams();
        }

        return md5(
            var_export($query->toArray(), true).$limit.$offset.var_export($orderBy, true).var_export($facetsParams, true)
        );
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Component\SourceFactory;

use \Yucca\Component\Source\Chain;
use Yucca\Component\Source\DataParser\DataParser;

/**
 * Class ChainFactory
 * @package Yucca\Component\SourceFactory
 */
class ChainFactory implements SourceFactoryInterface
{
    /**
     * @var \Yucca\Component\Source\DataParser\DataParser
     */
    protected $dataParser;

    /**
     * @param \Yucca\Component\Source\DataParser\DataParser $dataParser
     */
    public function __construct(DataParser $dataParser)
    {
        $this->dataParser = $dataParser;
    }
    /**
     * Build source
     * @param string $sourceName
     * @param array  $params
     * @param array  $sources
     * @return \Yucca\Component\Source\Chain
     */
    public function getSource($sourceName, array $params = array(), array $sources = array())
    {
        $toReturn = new Chain($sourceName, $params, $sources);
        $toReturn->setDataParser($this->dataParser);

        return $toReturn;
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Form\Type;

use Symfony\Component\Form\ChoiceList\Factory\DefaultChoiceListFactory;
use Symfony\Component\Form\ChoiceList\Factory\PropertyAccessDecorator;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Yucca\Component\EntityManager;
use Yucca\Form\ChoiceList\ChoiceLoader;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Yucca\Form\DataTransformer\IteratorToArrayTransformer;

/**
 * Unique Entity Validator checks if one or a set of fields contain unique values.
 * Inspired by Doctrine Bridge bundle
 */
class YuccaEntityType extends AbstractType
{
    /**
     * @var EntityManager
     */
    protected $entityManager;

    /**
     * @var array
     */
    private $choiceListCache = array();

    /**
     * @var PropertyAccessDecorator
     */
    private $choiceListFactory;

    /**
     * @param EntityManager             $entityManager
     * @param PropertyAccessorInterface $propertyAccessor
     */
    public function __construct(EntityManager $entityManager, PropertyAccessorInterface $propertyAccessor = null)
    {
        $this->entityManager = $entityManager;
        $this->choiceListFactory = $propertyAccessor ?: new PropertyAccessDecorator(new DefaultChoiceListFactory(), $propertyAccessor);
    }

    /**
     * @param FormBuilderInterface $builder
     * @param array                $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if ($options['multiple']) {
            $builder->addModelTransformer(new IteratorToArrayTransformer(), true);
        }
    }

    /**
     * @param OptionsResolver $resolver
     *
     * @return mixed
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $choiceListCache =& $this->choiceListCache;
        $choiceListFactory = $this->choiceListFactory;
        $entityManager = $this->entityManager;

        $choiceLoader = function (Options $options) use (&$choiceListCache, $choiceListFactory, $entityManager) {
            // Support for closures
            $propertyHash = is_object($options['choice_label'])
                ? spl_object_hash($options['choice_label'])
                : $options['choice_label'];
            $iteratorHash = is_object($options['iterator'])
                ? spl_object_hash($options['iterator'])
                : $options['iterator'];

            $preferredChoiceHashes = $options['preferred_choices'];

            if (is_array($preferredChoiceHashes)) {
                array_walk_recursive($preferredChoiceHashes, function (&$value) {
                    $value = spl_object_hash($value);
                });
            }

            // Support for closures
            $groupByHash = is_object($options['group_by'])
                ? spl_object_hash($options['group_by'])
                : $options['group_by'];

            $hash = md5(json_encode(array(
                spl_object_hash($entityManager),
                $options['model_class_name'],
                $options['selector_class_name'],
                $propertyHash,
                $preferredChoiceHashes,
                $groupByHash,
                $iteratorHash,
            )));

            if (!isset($choiceListCache[$hash])) {
                $choiceListCache[$hash] = new ChoiceLoader(
                    $entityManager,
                    $options['model_class_name'],
                    $options['selector_class_name'],
                    $options['choice_label'],
                    $options['iterator'],
                    $options['preferred_choices'],
                    $options['group_by'],
                    $choiceListFactory
                );
            }

            return $choiceListCache[$hash];
        };

        $resolver->setDefaults(array(
            'em'                => null,
            'query_builder'     => null,
            'choices'           => array(),
            'choice_loader'     => $choiceLoader,
            'group_by'          => null,
            'iterator'          => null,
            'model_class_name'  => null,
            'selector_class_name' => null,
            //'choices_as_values' => true,
        ));

        $resolver->setRequired(array('model_class_name'));

        $resolver->setAllowedTypes('iterator', array('null', 'Yucca\Component\Iterator\Iterator', 'array'));
    }

    /**
     * @return string
     */
    public function getBlockPrefix()
    {
        return 'yucca_entity';
    }

    /**
     * @return null|string|\Symfony\Component\Form\FormTypeInterface
     */
    public function getParent()
    {
        return ChoiceType::class;
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Component\SourceFactory;

use \Yucca\Component\Source\Memcached;
use \Yucca\Component\ConnectionManager;
use \Yucca\Component\Source\DataParser\DataParser;

/**
 * Class MemcachedFactory
 * @package Yucca\Component\SourceFactory
 */
class MemcachedFactory implements SourceFactoryInterface
{
    /**
     * @var \Yucca\Component\ConnectionManager
     */
    protected $connectionManager;

    /**
     * @var \Yucca\Component\Source\DataParser\DataParser
     */
    protected $dataParser;

    /**
     * @param \Yucca\Component\ConnectionManager            $connectionManager
     * @param \Yucca\Component\Source\DataParser\DataParser $dataParser
     */
    public function __construct(ConnectionManager $connectionManager, DataParser $dataParser)
    {
        $this->connectionManager = $connectionManager;
        $this->dataParser = $dataParser;
    }

    /**
     * Build source
     * @param string $sourceName
     * @param array  $params
     * @return \Yucca\Component\Source\Memcache
     */
    public function getSource($sourceName, array $params = array())
    {
        if (false === isset($params['connection_name'])) {
            throw new \InvalidArgumentException("Configuration array must contain a 'connection_name' key");
        }
        $connectionConfig = $this->connectionManager->getConnectionConfig($params['connection_name']);
        $toReturn = new Memcached($sourceName, $params, isset($connectionConfig['options']['prefix']) ? $connectionConfig['options']['prefix'] : '');
        $toReturn->setConnectionManager($this->connectionManager);
        $toReturn->setDataParser($this->dataParser);

        return $toReturn;
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Component\Profiler;

use Symfony\Component\Stopwatch\Stopwatch;
use Yucca\Bundle\YuccaBundle\DataCollector\Logger;
use Yucca\Component\Selector\Source\LogWrapper;
use Yucca\Component\SelectorManager as BaseSelectorManager;

/**
 * Class SelectorManager
 * @package Yucca\Component\Profiler
 */
class SelectorManager extends BaseSelectorManager
{
    protected $stopWatch;

    protected $datacollectorLogger;

    /**
     * SelectorManager constructor.
     *
     * @param array     $selectorSourceConfig
     * @param Stopwatch $stopWatch
     * @param Logger    $datacollectorLogger
     */
    public function __construct(array $selectorSourceConfig, Stopwatch $stopWatch = null, Logger $datacollectorLogger)
    {
        parent::__construct($selectorSourceConfig);
        $this->stopWatch = $stopWatch;
        $this->datacollectorLogger = $datacollectorLogger;
    }

    /**
     * Get a source by it's name
     * @param $selectorSourceName
     * @return \Yucca\Component\Selector\Source\SelectorSourceInterface
     * @throws \InvalidArgumentException
     */
    protected function getSource($selectorSourceName)
    {
        if (false === isset($this->sources[$selectorSourceName])) {
            $this->sources[$selectorSourceName] = new LogWrapper(
                $this->getFactory($selectorSourceName)->getSource(),
                $this->stopWatch,
                $this->datacollectorLogger
            );
        }

        return $this->sources[$selectorSourceName];
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Component\Source;

use Yucca\Component\Source\Exception\NoDataException;
use Yucca\Component\Source\DataParser\DataParser;

/**
 * Class PhpArray
 * @package Yucca\Component\Source
 */
class PhpArray extends SourceAbstract
{
    static protected $datas;
    static protected $enabled = true;

    /**
     * @var \Yucca\Component\Source\DataParser\DataParser
     */
    protected $dataParser;

    /**
     * Constructor
     * @param string $sourceName
     * @param array  $configuration
     * @param string $prefix
     * @throws \InvalidArgumentException
     */
    public function __construct($sourceName, array $configuration = array(), $prefix = '')
    {
        parent::__construct($sourceName, $configuration);
    }

    /**
     *
     */
    public static function enablePhpArrayCache()
    {
        self::$enabled = true;
    }

    /**
     *
     */
    public static function disablePhpArrayCache()
    {
        self::$enabled = false;
    }

    /**
     * @param DataParser $dataParser
     *
     * @return $this
     */
    public function setDataParser(DataParser $dataParser)
    {
        $this->dataParser = $dataParser;

        return $this;
    }

    /**
     * @param array $identifier
     * @param bool  $rawData
     * @param mixed $shardingKey
     *
     * @return array
     * @throws NoDataException
     * @throws \Exception
     */
    public function load(array $identifier, $rawData, $shardingKey)
    {
        if (!self::$enabled) {
            throw new NoDataException(__CLASS__." is disabled");
        }
        $cacheKey = $this->getCacheKey($identifier);
        if (isset(static::$datas[$cacheKey])) {
            $datas = static::$datas[$cacheKey];

            if ($rawData) {
                return $datas;
            } else {
                return $this->dataParser->decode($datas, $this->configuration['fields']);
            }
        }

        throw new NoDataException("No datas found in cache for \"{$this->sourceName}\" with identifiers ".var_export($identifier, true));
    }

    /**
     * @param array $identifier
     * @param null  $shardingKey
     *
     * @return $this
     */
    public function remove(array $identifier, $shardingKey = null)
    {
        if (!self::$enabled) {
            return $this;
        }

        unset(static::$datas[$this->getCacheKey($identifier)]);

        return $this;
    }

    /**
     * @param mixed $serializedCriterias
     * @param array $options
     * @return array|string
     * @throws Exception\NoDataException
     */
    public function loadIds($serializedCriterias, array $options = array())
    {
        if (!self::$enabled) {
            throw new NoDataException(__CLASS__." is disabled");
        }

        if (isset(static::$datas[$serializedCriterias])) {
            return static::$datas[$serializedCriterias];
        }

        throw new NoDataException("No datas found in cache for \"{$this->sourceName}\" with criterias ".var_export($serializedCriterias, true));
    }

    /**
     * @param mixed $datas
     * @param array $identifier
     * @param null  $shardingKey
     * @param null  $affectedRows
     *
     * @return mixed|void
     */
    public function save($datas, array $identifier = array(), $shardingKey = null, &$affectedRows = null)
    {
        if (!self::$enabled) {
            return;
        }

        unset(static::$datas[$this->getCacheKey($identifier)]);
    }

    /**
     * @param mixed $datas
     * @param array $identifier
     * @param null  $shardingKey
     * @param null  $affectedRows
     */
    public function saveAfterLoading($datas, array $identifier = array(), $shardingKey = null, &$affectedRows = null)
    {
        if (!self::$enabled) {
            return;
        }

        static::$datas[$this->getCacheKey($identifier)] = $datas;
    }

    /**
     * @param $identifier
     * @return string
     */
    protected function getCacheKey($identifier)
    {
        $toReturn = $this->sourceName.'_'.(isset($this->configuration['version']) ? $this->configuration['version'] : 1);
        foreach ($identifier as $k => $v) {
            if ($v instanceof \Yucca\Model\ModelInterface) {
                $v = $v->getId();
            }
            $toReturn .= ':'.$k.'='.$v;
        }

        return $toReturn;
    }
}


<?php
namespace Yucca\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Yucca\Component\EntityManager;
use Yucca\Model\ModelInterface;

/**
 * Class ModelToNumberTransformer
 *
 * @package Yucca\Form\DataTransformer
 */
class ModelToNumberTransformer implements DataTransformerInterface
{
    /**
     * @var EntityManager
     */
    private $yuccaEntityManager;

    /**
     * @param EntityManager $yuccaEntityManager
     * @param string        $modelClassName
     */
    public function __construct(EntityManager $yuccaEntityManager, $modelClassName)
    {
        $this->yuccaEntityManager = $yuccaEntityManager;
        $this->modelClassName = $modelClassName;
    }

    /**
     * Transforms an object to a string (number).
     *
     * @param ModelInterface|null $shareType
     *
     * @return string
     */
    public function transform($shareType)
    {
        if (empty($shareType)) {
            return "";
        }

        return $shareType->getId();
    }

    /**
     * Transforms a string (number) to an object.
     *
     * @param string $number
     *
     * @return ModelInterface |null
     *
     * @throws TransformationFailedException if object (issue) is not found.
     */
    public function reverseTransform($number)
    {
        if (!$number) {
            return null;
        }

        try {
            $shareType = $this->yuccaEntityManager->load($this->modelClassName, $number);
        } catch (\Exception $e) {
            throw new TransformationFailedException(sprintf(
                'The object can\'t be found',
                $number
            ));
        }

        return $shareType;
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Component;

use Yucca\Component\SourceFactory\SourceFactoryInterface;

/**
 * Class SourceManager
 * @package Yucca\Component
 */
class SourceManager
{
    /**
     * @var array
     */
    protected $sourceConfig;

    /**
     * @var SourceFactoryInterface[]
     */
    protected $sourceFactories;

    /**
     * @var \Yucca\Component\SchemaManager
     */
    protected $schemaManager;

    /**
     * @var \Yucca\Component\Source\SourceInterface[]
     */
    protected $sources;

    /**
     * @param array $sourceConfig
     */
    public function __construct(array $sourceConfig)
    {
        $this->sourceConfig = $sourceConfig;
    }

    /**
     * Add a source factory to the pool
     * @param string                                                $sourceFactoryName
     * @param \Yucca\Component\SourceFactory\SourceFactoryInterface $sourceFactory
     * @return \Yucca\Component\SourceManager
     */
    public function addSourceFactory($sourceFactoryName, SourceFactoryInterface $sourceFactory)
    {
        $this->sourceFactories[$sourceFactoryName] = $sourceFactory;

        return $this;
    }

    /**
     * Get a source by it's name
     * @param string $sourceName
     * @return \Yucca\Component\Source\SourceInterface
     * @throws \InvalidArgumentException
     */
    public function getSource($sourceName)
    {
        if (false === isset($this->sources[$sourceName])) {
            if (false === isset($this->sourceConfig[$sourceName]['handlers'])) {
                throw new \InvalidArgumentException("\"$sourceName\" name has not been configured");
            }

            $sources = array();
            foreach ($this->sourceConfig[$sourceName]['handlers'] as $sourceConfig) {
                $params = array_merge($this->sourceConfig[$sourceName]['default_params'], $sourceConfig);
                $sources[] = $this->getFactory($sourceConfig['type'])->getSource($sourceName, $params);
            }

            if (1 === count($sources)) {
                $this->sources[$sourceName] = current($sources);
            } else {
                $this->sources[$sourceName] = $this->getFactory('chain')->getSource($sourceName, $this->sourceConfig[$sourceName]['default_params'], $sources);
            }
        }

        return $this->sources[$sourceName];
    }

    /**
     * get factory by its type
     * @param $type
     * @return SourceFactory\SourceFactoryInterface
     * @throws \Exception
     */
    protected function getFactory($type)
    {
        if (isset($this->sourceFactories[$type])) {
            return $this->sourceFactories[$type];
        } else {
            throw new \Exception("Factory \"$type\" not foud");
        }
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Yucca\Component\Selector;

/**
 * Class Expression
 * @package Yucca\Component\Selector
 */
class Expression
{
    /**
     * @var array
     */
    protected $texts;

    /**
     * @var array
     */
    protected $params;

    /**
     * @param array $text
     * @param array $params
     */
    public function __construct(array $text, array $params = array())
    {
        $this->text = $text;
        $this->params = $params;
    }

    /**
     * @param string $handler
     *
     * @return mixed
     * @throws \Exception
     */
    public function toString($handler)
    {
        if (false === isset($this->text[$handler])) {
            throw new \Exception('Missing handler '.$handler.' for expression : '.var_export($handler, true));
        }

        return $this->text[$handler];
    }

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


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Component\Source;

use Yucca\Component\Source\Exception\NoDataException;
use Yucca\Component\ConnectionManager;
use Yucca\Component\Source\DataParser\DataParser;

/**
 * Class Memcached
 * @package Yucca\Component\Source
 */
class Memcached extends SourceAbstract
{
    protected $connectionName;

    /**
     * @var \Yucca\Component\ConnectionManager
     */
    protected $connectionManager;

    /**
     * @var \Yucca\Component\Source\DataParser\DataParser
     */
    protected $dataParser;

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

    /**
     * Constructor
     * @param string $sourceName
     * @param array  $configuration
     * @param string $prefix
     * @throws \InvalidArgumentException
     */
    public function __construct($sourceName, array $configuration = array(), $prefix = '')
    {
        parent::__construct($sourceName, $configuration);

        if (false === isset($this->configuration['connection_name'])) {
            throw new \InvalidArgumentException("Configuration array must contain a 'connection_name' key");
        }
        $this->connectionName = $this->configuration['connection_name'];
        $this->prefix = $prefix;
    }

    /**
     * @param \Yucca\Component\ConnectionManager $connectionManager
     * @return \Yucca\Component\Source\Memcached
     */
    public function setConnectionManager(ConnectionManager $connectionManager)
    {
        $this->connectionManager = $connectionManager;

        return $this;
    }

    /**
     * @param DataParser $dataParser
     * @return DatabaseSingleRow
     */
    public function setDataParser(DataParser $dataParser)
    {
        $this->dataParser = $dataParser;

        return $this;
    }

    /**
     * @param array $identifier
     * @param bool  $rawData
     * @param mixed $shardingKey
     *
     * @return array|mixed
     * @throws NoDataException
     * @throws \Exception
     */
    public function load(array $identifier, $rawData, $shardingKey)
    {
        $datas = $this->getConnection()->get($this->getCacheKey($identifier));

        if (false === $datas) {
            throw new NoDataException("No datas found in cache for \"{$this->sourceName}\" with identifiers ".var_export($identifier, true));
        }

        if ($rawData) {
            return $datas;
        } else {
            return $this->dataParser->decode($datas, $this->configuration['fields']);
        }
    }

    /**
     * @param array $identifier
     * @param null  $shardingKey
     *
     * @return $this
     * @throws \Exception
     */
    public function remove(array $identifier, $shardingKey = null)
    {
        $this->getConnection()->delete($this->getCacheKey($identifier));

        return $this;
    }

    /**
     * @param mixed $serializedCriterias
     * @param array $options
     * @return array|string
     * @throws Exception\NoDataException
     */
    public function loadIds($serializedCriterias, array $options = array())
    {
        $datas = $this->getConnection()->get($serializedCriterias);

        if (false === $datas) {
            throw new NoDataException("No datas found in cache for \"{$this->sourceName}\" with criterias ".var_export($serializedCriterias, true));
        }

        return $datas;
    }

    /**
     * @param array $datas
     * @param array $identifier
     * @param null  $shardingKey
     * @param null  $affectedRows
     *
     * @throws \Exception
     */
    public function save($datas, array $identifier = array(), $shardingKey = null, &$affectedRows = null)
    {
        $this->getConnection()->delete($this->getCacheKey($identifier));
    }

    /**
     * @param array $datas
     * @param array $identifier
     * @param null  $shardingKey
     * @param null  $affectedRows
     *
     * @throws \Exception
     */
    public function saveAfterLoading($datas, array $identifier = array(), $shardingKey = null, &$affectedRows = null)
    {
        $this->getConnection()->set($this->getCacheKey($identifier), $datas, 0);
    }

    /**
     * @throws \Exception
     * @return \Memcached
     */
    protected function getConnection()
    {
        $toReturn = $this->connectionManager->getConnection($this->connectionName);
        if ($toReturn instanceof \Memcached) {
            return $toReturn;
        }

        throw new \Exception("Connection binded to \"{$this->sourceName}\" must be a \"Memcached\" connection");
    }

    /**
     * @param $identifier
     * @return string
     */
    protected function getCacheKey($identifier)
    {
        $toReturn = $this->prefix.'_'.$this->sourceName.'_'.(isset($this->configuration['version']) ? $this->configuration['version'] : 1);
        foreach ($identifier as $k => $v) {
            if ($v instanceof \Yucca\Model\ModelInterface) {
                $v = $v->getId();
            }
            $toReturn .= ':'.$k.'='.$v;
        }

        return $toReturn;
    }
}


<?php
/**
 * @author Semenov Alexander <semenov@skeeks.com>
 * @link https://skeeks.com/
 * @copyright (c) 2010 SkeekS
 * @date 11.03.2017
 */

namespace skeeks\cms\admin;

use skeeks\cms\admin\assets\AdminAsset;
use skeeks\cms\admin\form\fields\AdminSelectField;
use skeeks\cms\backend\BackendComponent;
use skeeks\cms\backend\BackendMenu;
use skeeks\cms\IHasPermissions;
use skeeks\cms\modules\admin\filters\AdminLastActivityAccessControl;
use skeeks\cms\rbac\CmsManager;
use skeeks\yii2\form\fields\SelectField;
use yii\base\Application;
use yii\base\Theme;
use yii\helpers\ArrayHelper;
use yii\web\View;

/**
 * Class AdminComponent
 * @package skeeks\cms\admin
 */
class AdminComponent extends BackendComponent
{
    /**
     * @var string
     */
    public $controllerPrefix = "admin";

    /**
     * @var array
     */
    public $urlRule = [
        'urlPrefix' => '~sx',
    ];

    /**
     * Default pjax options
     *
     * @var array
     */
    public $pjax =
        [
            'timeout' => 30000,
        ];

    protected function _run()
    {
        \Yii::$app->errorHandler->errorAction = 'admin/error/error';

        /*$theme = new \skeeks\cms\themes\unify\admin\UnifyThemeAdmin();
        $theme->pathMap = [
            '@app/views' => [
                '@common/themes/backend/views',
                '@skeeks/cms/themes/unify/admin/views',
            ],
        ];
        $theme->favicon = "";
        \skeeks\cms\themes\unify\admin\UnifyThemeAdmin::initBeforeRender();
        \Yii::$app->view->theme = $theme;*/

        \Yii::$app->view->theme = new Theme([
            'pathMap' => [
                '@app/views' => [
                    //'@skeeks/crm/themes/unifyAdmin/views',
                    '@skeeks/cms/admin/views',
                ],
            ],
        ]);

        if ($this->pjax) {
            \Yii::$container->set('yii\widgets\Pjax', $this->pjax);
        }

        \Yii::$app->language = \Yii::$app->admin->languageCode;

        /*\Yii::$container->setDefinitions([
            BackendController::class => \skeeks\modules\cms\form2\controllers\BackendController::class
        ]);*/

        \Yii::$app->on(Application::EVENT_BEFORE_ACTION, function () {
            if (in_array(\Yii::$app->controller->uniqueId, [
                'admin/admin-auth',
            ])) {
                return true;
            }

            if ($behaviorAccess = ArrayHelper::getValue(\Yii::$app->controller->behaviors(), 'access')) {
                $behaviorAccess['class'] = \skeeks\cms\admin\AdminAccessControl::class;
                \Yii::$app->controller->detachBehavior('access');
                \Yii::$app->controller->attachBehavior('access', $behaviorAccess);
            }

            \Yii::$app->controller->attachBehavior('adminLastActivityAccess', [
                'class' => AdminLastActivityAccessControl::className(),
                'rules' =>
                    [
                        [
                            'allow'         => true,
                            'matchCallback' => function ($rule, $action) {
                                if (\Yii::$app->user->identity->lastAdminActivityAgo > \Yii::$app->admin->blockedTime) {
                                    return false;
                                }

                                if (\Yii::$app->user->identity) {
                                    \Yii::$app->user->identity->updateLastAdminActivity();
                                }

                                return true;
                            },
                        ],
                    ],
            ]);

            if (\Yii::$app->controller instanceof IHasPermissions && \Yii::$app->controller->permissionNames) {
                $result = ArrayHelper::merge([
                    CmsManager::PERMISSION_ADMIN_ACCESS => \Yii::t('skeeks/cms', 'Access to the administration system'),
                ], \Yii::$app->controller->permissionNames);

                \Yii::$app->controller->setPermissionNames($result);
            }
        });

        \Yii::$container->setDefinitions(ArrayHelper::merge(
            \Yii::$container->definitions,
            [
                SelectField::class => [
                    'class' => AdminSelectField::class,
                ],
            ]
        ));
        parent::_run();
    }

    /**
     * @return BackendMenu
     */
    public function getMenu()
    {
        if (is_array($this->_menu) || $this->_menu === null) {
            $data = (array)$this->_menu;

            if (!ArrayHelper::getValue($data, 'class')) {
                $data['class'] = BackendMenu::class;
            }

            if ($dataFromFiles = (array)$this->getMenuFilesData()) {
                $dataFromFiles = static::_filesConfigNormalize($dataFromFiles);
            }

            if (ArrayHelper::getValue($data, 'data')) {
                $data['data'] = ArrayHelper::merge($dataFromFiles, $data['data']);
            } else {
                $data['data'] = $dataFromFiles;
            }

            if ($this->isMergeControllerMenu) {
                $data['data'] = ArrayHelper::merge((array)$this->getMenuDataFromControllers(), (array)$data['data']);
            }

            $this->_menu = \Yii::createObject($data);
        }

        return $this->_menu;
    }

    static protected function _filesConfigNormalize($config = [])
    {
        if ($config) {
            foreach ($config as $key => $itemData) {
                if ($label = ArrayHelper::getValue($itemData, 'label')) {
                    ArrayHelper::remove($itemData, 'label');
                    $itemData['name'] = $label;
                }

                if ($image = ArrayHelper::getValue($itemData, 'img')) {
                    ArrayHelper::remove($itemData, 'img');
                    $itemData['image'] = $image;
                }

                if ($code = ArrayHelper::getValue($itemData, 'code')) {
                    ArrayHelper::remove($itemData, 'code');
                    //$itemData['id'] = $code;
                }

                ArrayHelper::remove($itemData, 'enabled');

                if ($items = ArrayHelper::getValue($itemData, 'items')) {
                    if (is_array($items)) {
                        $itemData['items'] = self::_filesConfigNormalize($items);
                    }
                }

                $config[$key] = $itemData;
            }
        }

        return $config;
    }

    protected $_menuFilesData = null;

    /**
     * Scan admin config files
     * @return array
     */
    public function getMenuFilesData()
    {
        \Yii::beginProfile('admin-menu');

        if ($this->_menuFilesData !== null && is_array($this->_menuFilesData)) {
            return (array)$this->_menuFilesData;
        }

        $paths[] = \Yii::getAlias('@common/config/admin/menu.php');
        $paths[] = \Yii::getAlias('@app/config/admin/menu.php');

        foreach (\Yii::$app->extensions as $code => $data) {
            if ($data['alias']) {
                foreach ($data['alias'] as $code => $path) {
                    $adminMenuFile = $path.'/config/admin/menu.php';
                    if (file_exists($adminMenuFile)) {
                        $menuGroups = (array)include_once $adminMenuFile;
                        $this->_menuFilesData = ArrayHelper::merge($this->_menuFilesData, $menuGroups);
                    }
                }
            }
        }

        foreach ($paths as $path) {
            if (file_exists($path)) {
                $menuGroups = (array)include_once $path;
                $this->_menuFilesData = ArrayHelper::merge($this->_menuFilesData, $menuGroups);
            }
        }

        ArrayHelper::multisort($this->_menuFilesData, 'priority');

        if (!$this->_menuFilesData) {
            $this->_menuFilesData = false;
        }

        \Yii::endProfile('admin-menu');

        return (array)$this->_menuFilesData;
    }

    /**
     * @param View|null $view
     */
    public function initJs(View $view = null)
    {
        $options =
            [
                'BlockerImageLoader' => AdminAsset::getAssetUrl('images/loaders/circulare-blue-24_24.GIF'),
                'disableCetainLink'  => false,
                'globalAjaxLoader'   => true,
                'menu'               => [],
            ];

        $options = \yii\helpers\Json::encode($options);

        \Yii::$app->view->registerJs(<<<JS
        (function(sx, $, _)
        {
            /**
            * @type {Admin}
            */
            sx.App = new sx.classes.Admin($options);

        })(sx, sx.$, sx._);
JS
        );
    }

}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Component;

use Yucca\Component\ConnectionFactory\ConnectionFactoryInterface;

/**
 * Class ConnectionManager
 * @package Yucca\Component
 */
class ConnectionManager
{
    protected $connectionsConfig;
    protected $connectionFactories = array();

    protected $connections = array();

    /**
     *
     * @param array $connectionsConfig
     */
    public function __construct(array $connectionsConfig)
    {
        $this->connectionsConfig = $connectionsConfig;
    }

    /**
     * Add a connection factory to the pool
     * @param string                                                        $connectionFactoryName
     * @param \Yucca\Component\ConnectionFactory\ConnectionFactoryInterface $connectionFactory
     * @return \Yucca\Component\ConnectionManager
     */
    public function addConnectionFactory($connectionFactoryName, ConnectionFactoryInterface $connectionFactory)
    {
        $this->connectionFactories[$connectionFactoryName] = $connectionFactory;

        return $this;
    }

    /**
     * Get connection
     * @param string $connectionName
     * @param bool   $forceFromMaster
     * @return \Doctrine\DBAL\Connection
     */
    public function getConnection($connectionName, $forceFromMaster = true)
    {
        /*if($forceFromMaster) {
            return $this->buildConnection($this->connectionsConfig[$connectionName]);
        }*/
        //FIXME : check forceFromMaster parameter
        if (false === isset($this->connections[$connectionName])) {
            if (false === isset($this->connectionsConfig[$connectionName])) {
                throw new \InvalidArgumentException("Connection \"$connectionName\" is not configured");
            }
            $this->connections[$connectionName] = $this->buildConnection($this->connectionsConfig[$connectionName]);
        }

        return $this->connections[$connectionName];
    }

    /**
     * @param string $connectionName
     *
     * @return mixed
     */
    public function getConnectionConfig($connectionName)
    {
        return $this->connectionsConfig[$connectionName];
    }

    /**
     * Build connection
     * @param array $connectionConfig
     * @throws \InvalidArgumentException
     * @return mixed
     */
    protected function buildConnection(array $connectionConfig)
    {
        if (false === isset($connectionConfig['type'])) {
            throw new \InvalidArgumentException("Connection is not well formed : missing key \"type\"");
        }

        return $this->getConnectionFactory($connectionConfig['type'])->getConnection($connectionConfig);
    }

    /**
     * Get connection factory
     * @param string $type
     * @throws \Exception
     * @return \Yucca\Component\ConnectionFactory\ConnectionFactoryInterface
     */
    protected function getConnectionFactory($type)
    {
        if (false === isset($this->connectionFactories[$type])) {
            throw new \InvalidArgumentException("Missing connection factory \"$type\"");
        }

        return $this->connectionFactories[$type];
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Component\Source;

use Yucca\Component\Source\Exception\NoDataException;
use Yucca\Component\ConnectionManager;
use Yucca\Component\Source\DataParser\DataParser;

/**
 * Class Memcache
 * @package Yucca\Component\Source
 */
class Memcache extends SourceAbstract
{
    protected $connectionName;

    /**
     * @var \Yucca\Component\ConnectionManager
     */
    protected $connectionManager;

    /**
     * @var \Yucca\Component\Source\DataParser\DataParser
     */
    protected $dataParser;

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

    /**
     * Constructor
     * @param string $sourceName
     * @param array  $configuration
     * @param string $prefix
     * @throws \InvalidArgumentException
     */
    public function __construct($sourceName, array $configuration = array(), $prefix = '')
    {
        parent::__construct($sourceName, $configuration);

        if (false === isset($this->configuration['connection_name'])) {
            throw new \InvalidArgumentException("Configuration array must contain a 'connection_name' key");
        }
        $this->connectionName = $this->configuration['connection_name'];
        $this->prefix = $prefix;
    }

    /**
     * @param \Yucca\Component\ConnectionManager $connectionManager
     * @return \Yucca\Component\Source\Memcache
     */
    public function setConnectionManager(ConnectionManager $connectionManager)
    {
        $this->connectionManager = $connectionManager;

        return $this;
    }

    /**
     * @param DataParser $dataParser
     * @return DatabaseSingleRow
     */
    public function setDataParser(DataParser $dataParser)
    {
        $this->dataParser = $dataParser;

        return $this;
    }

    /**
     * @param array $identifier
     * @param bool  $rawData
     * @param mixed $shardingKey
     *
     * @return array|string
     * @throws NoDataException
     * @throws \Exception
     */
    public function load(array $identifier, $rawData, $shardingKey)
    {
        $datas = $this->getConnection()->get($this->getCacheKey($identifier));

        if (false === $datas) {
            throw new NoDataException("No datas found in cache for \"{$this->sourceName}\" with identifiers ".var_export($identifier, true));
        }

        if ($rawData) {
            return $datas;
        } else {
            return $this->dataParser->decode($datas, $this->configuration['fields']);
        }
    }

    /**
     * @param array $identifier
     * @param null  $shardingKey
     *
     * @return $this
     * @throws \Exception
     */
    public function remove(array $identifier, $shardingKey = null)
    {
        $this->getConnection()->delete($this->getCacheKey($identifier));

        return $this;
    }

    /**
     * @param mixed $serializedCriterias
     * @param array $options
     *
     * @return array|string
     * @throws NoDataException
     * @throws \Exception
     */
    public function loadIds($serializedCriterias, array $options = array())
    {
        $datas = $this->getConnection()->get($serializedCriterias);

        if (false === $datas) {
            throw new NoDataException("No datas found in cache for \"{$this->sourceName}\" with criterias ".var_export($serializedCriterias, true));
        }

        return $datas;
    }

    /**
     * @param array $datas
     * @param array $identifier
     * @param null  $shardingKey
     * @param null  $affectedRows
     *
     * @throws \Exception
     */
    public function save($datas, array $identifier = array(), $shardingKey = null, &$affectedRows = null)
    {
        $this->getConnection()->delete($this->getCacheKey($identifier));
    }

    /**
     * @param array $datas
     * @param array $identifier
     * @param null  $shardingKey
     * @param null  $affectedRows
     *
     * @throws \Exception
     */
    public function saveAfterLoading($datas, array $identifier = array(), $shardingKey = null, &$affectedRows = null)
    {
        $this->getConnection()->set($this->getCacheKey($identifier), $datas, 0, 0);
    }

    /**
     * @throws \Exception
     * @return \Memcache
     */
    protected function getConnection()
    {
        $toReturn = $this->connectionManager->getConnection($this->connectionName);
        if ($toReturn instanceof \Memcache) {
            return $toReturn;
        }

        throw new \Exception("Connection binded to \"{$this->sourceName}\" must be a \"memcache\" connection");
    }

    /**
     * @param $identifier
     * @return string
     */
    protected function getCacheKey($identifier)
    {
        $toReturn = $this->prefix.'_'.$this->sourceName.'_'.(isset($this->configuration['version']) ? $this->configuration['version'] : 1);
        foreach ($identifier as $k => $v) {
            if ($v instanceof \Yucca\Model\ModelInterface) {
                $v = $v->getId();
            }
            $toReturn .= ':'.$k.'='.$v;
        }

        return $toReturn;
    }
}


<?php
/**
 * @author Semenov Alexander <semenov@skeeks.com>
 * @link https://skeeks.com/
 * @copyright (c) 2010 SkeekS
 * @date 12.03.2017
 */

namespace skeeks\cms\admin\actions;

use skeeks\cms\helpers\RequestResponse;
use skeeks\cms\rbac\CmsManager;
use Yii;
use yii\base\Exception;
use yii\base\UserException;
use yii\helpers\Html;

/**
 * Class ErrorAction
 * @package skeeks\cms\actions
 */
class ErrorAction extends \yii\web\ErrorAction
{
    /**
     * Runs the action
     *
     * @return string result content
     */
    public function run()
    {
        if (($exception = Yii::$app->getErrorHandler()->exception) === null) {
            return '';
        }

        if ($exception instanceof \HttpException) {
            $code = $exception->statusCode;
        } else {
            $code = $exception->getCode();
        }

        if ($exception instanceof Exception) {
            $name = $exception->getName();
        } else {
            $name = $this->defaultName ?: Yii::t('yii', 'Error');
        }

        if ($code) {
            $name .= " (#$code)";
        }

        if ($exception instanceof UserException) {
            $message = $exception->getMessage();
        } else {
            $message = $this->defaultMessage ?: Yii::t('yii', 'An internal server error occurred.');
        }

        if (Yii::$app->getRequest()->getIsAjax()) {
            $rr = new RequestResponse();

            $rr->success = false;
            $rr->message = "$name: $message";

            return (array)$rr;
        } else {
            if (\Yii::$app->user->can(CmsManager::PERMISSION_ADMIN_ACCESS)) {
                $this->controller->layout = \Yii::$app->cms->moduleAdmin->layout;
                return $this->controller->render('@app/views/error/error', [
                    'message' => nl2br(Html::encode($message))
                ]);
            } else {
                $this->controller->layout = '@app/views/layouts/unauthorized';

                return $this->controller->render('@app/views/error/unauthorized-403', [
                    'message' => nl2br(Html::encode($message))
                ]);
            }
        }
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Model;

use Wheeliz\Domain\Car\Entity\RentEntity;
use Yucca\Component\EntityManager;
use Yucca\Component\MappingManager;
use Yucca\Component\SelectorManager;

/**
 * Class ModelAbstract
 * @package Yucca\Model
 */
abstract class ModelAbstract implements ModelInterface
{
    protected $yuccaInitialized = array();
    protected $yuccaProperties = array();

    /**
     * @var \Yucca\Component\MappingManager
     */
    protected $yuccaMappingManager;
    /**
     * @var \Yucca\Component\SelectorManager
     */
    protected $yuccaSelectorManager;
    /**
     * @var \Yucca\Component\EntityManager
     */
    protected $yuccaEntityManager;

    protected $yuccaIdentifier;
    protected $yuccaShardingKey;

    // For old PHP 5.3 (like 5.3.3) compatibility
    //abstract public function getId();

    /**
     * EntityManager
     * @param \Yucca\Component\MappingManager $mappingManager
     * @return ModelAbstract
     */
    public function setYuccaMappingManager(MappingManager $mappingManager)
    {
        $this->yuccaMappingManager = $mappingManager;

        return $this;
    }

    /**
     * @param \Yucca\Component\EntityManager $entityManager
     * @return ModelAbstract
     */
    public function setYuccaEntityManager(EntityManager $entityManager)
    {
        $this->yuccaEntityManager = $entityManager;

        return $this;
    }

    /**
     * @param \Yucca\Component\SelectorManager $selectorManager
     * @return ModelAbstract
     */
    public function setYuccaSelectorManager(SelectorManager $selectorManager)
    {
        $this->yuccaSelectorManager = $selectorManager;

        return $this;
    }

    /**
     * @param MappingManager  $mappingManager
     * @param SelectorManager $selectorManager
     * @param EntityManager   $entityManager
     *
     * @return mixed
     */
    public function refresh(MappingManager $mappingManager, SelectorManager $selectorManager, EntityManager $entityManager)
    {
        $this->yuccaMappingManager = $mappingManager;
        $this->yuccaSelectorManager = $selectorManager;
        $this->yuccaEntityManager = $entityManager;

        foreach (array_keys($this->yuccaInitialized) as $propertyName) {
            if ($this->$propertyName instanceof ModelInterface) {
                $this->yuccaEntityManager->refresh($this->$propertyName);
            }
        }

        return $this;
    }

    /**
     * @param mixed $identifier
     * @param null  $shardingKey
     *
     * @return $this
     */
    public function setYuccaIdentifier($identifier, $shardingKey = null)
    {
        $this->yuccaIdentifier = $identifier;
        $this->yuccaShardingKey = $shardingKey;

        return $this;
    }

    /**
     * @param mixed $identifier
     *
     * @return $this
     */
    public function reset($identifier)
    {
        $this->yuccaIdentifier = $identifier;
        foreach ($this->yuccaProperties as $propertyName) {
            $this->$propertyName = null;
        }
        $this->yuccaInitialized = array();

        return $this;
    }

    /**
     * @return $this
     * @throws \Yucca\Component\Source\Exception\NoDataException
     */
    public function ensureExist()
    {
        if (empty($this->yuccaIdentifier)) {
            throw new \Yucca\Component\Source\Exception\NoDataException(get_class($this).' doesn\'t seems to be saved in database');
        }
        try {
            foreach ($this->yuccaProperties as $propertyName) {
                if (false === isset($this->yuccaInitialized[$propertyName])) {
                    $this->hydrate($propertyName);
                }
            }
        } catch (\Yucca\Component\Source\Exception\NoDataException $exception) {
            throw new \Yucca\Component\Source\Exception\NoDataException(get_class($this).' doesn\'t seems to exist with identifiers : '.var_export($this->yuccaIdentifier, true));
        }

        return $this;
    }

    /**
     * @return ModelAbstract
     * @throws \Exception
     */
    public function save()
    {
        // Check that we have a mapping
        if (false === isset($this->yuccaMappingManager)) {
            throw new \Exception("Mapping manager isn't set");
        }

        //load values
        foreach ($this->yuccaProperties as $propertyName) {
            if (false === isset($this->yuccaInitialized[$propertyName])) {
                $this->hydrate($propertyName);
            }
        }

        //Create value list to save
        $toSave = array();
        foreach ($this->yuccaProperties as $propertyName) {
            $toSave[$propertyName] = $this->$propertyName;
        }
        //Save
        $mapper = $this->yuccaMappingManager->getMapper(get_class($this));
        $this->yuccaIdentifier = $mapper->save($this->yuccaIdentifier, $toSave, $this->yuccaShardingKey);

        //Set identifier to properties
        foreach ($this->yuccaIdentifier as $property => $value) {
            $this->$property = $value;
            $this->yuccaInitialized[$property] = true;
        }

        //Unset some properties dynamically set by DB
        foreach ($mapper->getPropertiesToRefreshAfterSave() as $property) {
            $this->$property = null;
            unset($this->yuccaInitialized[$property]);
        }

        return $this;
    }

    /**
     * @return $this
     * @throws \Exception
     */
    public function remove()
    {
        // Check that we have a mapping
        if (false === isset($this->yuccaMappingManager)) {
            throw new \Exception("Mapping manager isn't set");
        }

        //Remove
        $this->yuccaMappingManager->getMapper(get_class($this))->remove($this->yuccaIdentifier, $this->yuccaShardingKey);

        $this->reset(array());

        return $this;
    }

    /**
     * @return array
     */
    public function __sleep()
    {
        return array_merge(
            array('yuccaInitialized', 'yuccaProperties', 'yuccaIdentifier', 'yuccaShardingKey'),
            $this->yuccaProperties
        );
    }

    /**
     * @param $properties
     * @return ModelAbstract
     */
    protected function setYuccaProperties(array $properties)
    {
        $this->yuccaProperties = $properties;

        return $this;
    }

    /**
     * Hydrate this model with information coming from the mapping manager
     * @param $propertyName
     * @return ModelAbstract
     */
    protected function hydrate($propertyName)
    {

        if (isset($this->yuccaMappingManager) && (false === isset($this->yuccaInitialized[$propertyName])) && (false === empty($this->yuccaIdentifier))) {
            $values = $this->yuccaMappingManager->getMapper(get_class($this))->load($this->yuccaIdentifier, $propertyName, $this->yuccaShardingKey);
            foreach ($values as $property => $value) {
                if (false === isset($this->yuccaInitialized[$property])) {
                    $this->$property = $value;
                    $this->yuccaInitialized[$property] = true;
                }
            }
        }
        $this->yuccaInitialized[$propertyName] = true;

        return $this;
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Component\Iterator;

use Yucca\Component\Selector\SelectorInterface;
use Yucca\Component\EntityManager;

/**
 * Class Iterator
 * @package Yucca\Component\Iterator
 */
class EditableIterator extends Iterator implements \ArrayAccess
{
    protected $updatedDatas = array();
    protected $deletedDatas = array();

    protected $retrieved = false;

    /**
     * @param \Yucca\Component\Selector\SelectorInterface $selector
     * @param \Yucca\Component\EntityManager              $entityManager
     * @param string                                      $modelClassName
     */
    public function __construct(SelectorInterface $selector, EntityManager $entityManager = null, $modelClassName)
    {
        parent::__construct($selector, $entityManager, $modelClassName);
        $this->wantNewModel();
    }

    /**
     * give model count
     * @return int
     */
    public function count()
    {
        if ($this->retrieved) {
            return count($this->updatedDatas);
        } else {
            return parent::count();
        }
    }

    /**
     * retrieve the current Model
     * @return \Yucca\Model\ModelInterface
     */
    public function current()
    {
        if ($this->retrieved) {
            return current($this->updatedDatas);
        } else {
            return parent::current();
        }
    }

    /**
     * retrieve the current key
     * @return mixed
     */
    public function key()
    {
        if ($this->retrieved) {
            return key($this->updatedDatas);
        } else {
            return parent::key();
        }
    }

    /**
     * @return $this|void
     */
    public function next()
    {
        if ($this->retrieved) {
            next($this->updatedDatas);

            return $this;
        } else {
            return parent::next();
        }
    }

    /**
     * First
     * @return \Yucca\Component\Iterator\Iterator
     */
    public function rewind()
    {
        if ($this->retrieved) {
            reset($this->updatedDatas);

            return $this;
        } else {
            return parent::rewind();
        }
    }

    /**
     * Is there any model to fetch ?
     * @return boolean
     */
    public function valid()
    {
        if ($this->retrieved) {
            return false !== current($this->updatedDatas);
        } else {
            return parent::valid();
        }
    }

    /**
     * @return \Yucca\Component\Selector\SelectorInterface
     */
    public function getSelector()
    {
        if ($this->retrieved) {
            error_log('Try to '.__METHOD__.' on a retrieved iterator. The selector is no more in sync with the iterator');
        }

        return parent::getSelector();
    }

    /**
     * @return array
     */
    public function getArray()
    {
        if ($this->retrieved) {
            return $this->updatedDatas;
        } else {
            return parent::getArray();
        }
    }

    /**
     * @param mixed $offset
     *
     * @return $this
     */
    public function offsetUnset($offset)
    {
        $this->retrieve();
        $this->deletedDatas[] = $this->updatedDatas[$offset];
        if (isset($this->updatedDatas[$offset])) {
            unset($this->updatedDatas[$offset]);
        }

        return $this;
    }

    /**
     * @param mixed $offset
     * @return bool
     */
    public function offsetExists($offset)
    {
        $this->retrieve();

        return isset($this->updatedDatas[$offset]);
    }

    /**
     * @param mixed $offset
     * @return \Yucca\Model\ModelInterface
     * @throws \Exception
     */
    public function offsetGet($offset)
    {
        $this->retrieve();

        if (isset($this->updatedDatas[$offset])) {
            return $this->updatedDatas[$offset];
        } else {
            throw new \RuntimeException('Offset does not exists : '.$offset.'. Available offsets:'.implode(',', array_keys($this->updatedDatas)));
        }
    }

    /**
     * @param mixed $offset
     * @param mixed $value
     * @return $this
     */
    public function offsetSet($offset, $value)
    {
        $this->retrieve();
        $this->updatedDatas[$offset] = $value;

        return $this;
    }

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

    /**
     * When an update come to the iterator, retrieve the original dataset, only once
     */
    protected function retrieve()
    {
        if (false === $this->retrieved) {
            $this->updatedDatas = $this->getArray();
            $this->retrieved = true;
        }
    }
}


<?php
/**
 * @author Semenov Alexander <semenov@skeeks.com>
 * @link https://skeeks.com/
 * @copyright (c) 2010 SkeekS
 * @date 12.03.2017
 */

namespace skeeks\cms\admin\assets;

use skeeks\cms\base\AssetBundle;

/**
 * Class AdminAsset
 * @package skeeks\cms\admin\assets
 */
class AdminAsset extends AssetBundle
{
    public $sourcePath = '@skeeks/cms/admin/assets/src';

    public $css = [
        'https://use.fontawesome.com/releases/v5.0.7/css/all.css',

        'css/panel.css',
        'css/sidebar.css',
        'css/app.css',

        /*'css/grid.css',
        'css/table.css'*/
    ];
    public $js = [
        'js/classes/Blocker.js',
        'js/classes/OldNav.js',
        'js/classes/Menu.js',
        'js/classes/Iframe.js',
        'js/classes/Window.js',
        'js/classes/modal/Dialog.js',
        'js/classes/Fullscreen.js',
        'js/classes/UserLastActivity.js',
        'js/classes/modal/Promt.js',
        'js/classes/modal/Confirm.js',
        //'js/App.js',
        'js/Admin.js',
    ];
    public $depends = [

        'yii\web\YiiAsset',
        'yii\bootstrap\BootstrapPluginAsset',

        'skeeks\sx\assets\Custom',
        'skeeks\sx\assets\ComponentAjaxLoader',
        'skeeks\cms\admin\assets\JqueryScrollbarAsset',
        'skeeks\cms\admin\assets\ThemeRealAdminAsset',
        'skeeks\cms\assets\FancyboxAssets',
    ];

    /**
     * Registers this asset bundle with a view.
     * @param View $view the view to be registered with
     * @return static the registered asset bundle instance
     */
    public function registerAssetFiles($view)
    {
        if (\Yii::$app->request->isPjax) {
            return parent::registerAssetFiles($view);
        }

        parent::registerAssetFiles($view);
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Validator\Constraints;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\ConstraintValidator;
use Yucca\Component\EntityManager;
use Yucca\Component\SelectorManager;
use Yucca\Model\ModelAbstract;

/**
 * Unique Entity Validator checks if one or a set of fields contain unique values.
 * Inspired by Doctrine UniqueEntityValidator by Benjamin Eberlei <kontakt@beberlei.de>
 */
class UniqueEntityValidator extends ConstraintValidator
{
    /**
     * @var SelectorManager
     */
    private $selectorManager;

    /**
     * @var EntityManager
     */
    private $entityManager;

    /**
     * @param SelectorManager                $selectorManager
     * @param \Yucca\Component\EntityManager $entityManager
     */
    public function __construct(SelectorManager $selectorManager, EntityManager $entityManager)
    {
        $this->selectorManager = $selectorManager;
        $this->entityManager = $entityManager;
    }

    /**
     * @param ModelAbstract $entity
     * @param Constraint    $constraint
     *
     * @throws UnexpectedTypeException
     * @throws ConstraintDefinitionException
     */
    public function validate($entity, Constraint $constraint)
    {
        if (false === ($entity instanceof ModelAbstract )) {
            throw new UnexpectedTypeException($entity, 'ModelAbstract');
        }
        /**
         * @var ModelAbstract $entity
         */

        if (!is_array($constraint->fields) && !is_string($constraint->fields)) {
            throw new UnexpectedTypeException($constraint->fields, 'array');
        }

        if (null !== $constraint->errorPath && !is_string($constraint->errorPath)) {
            throw new UnexpectedTypeException($constraint->errorPath, 'string or null');
        }

        $fields = (array) $constraint->fields;

        if (0 === count($fields)) {
            throw new ConstraintDefinitionException('At least one field has to be specified.');
        }

        if (!$constraint->selector) {
            $selectorName = str_replace('Model', 'Selector', get_class($entity));
        } else {
            $selectorName = $constraint->selector;
        }

        $selector = $this->selectorManager->getSelector($selectorName);
        $selectorMethods = get_class_methods($selectorName);

        $criteria = array();
        foreach ($fields as $fieldName) {
            $camelFieldName = str_replace(' ', '', ucwords(str_replace('_', ' ', $fieldName)));
            $selectorMethod = 'add'.$camelFieldName.'Criteria';
            if (false === in_array($selectorMethod, $selectorMethods)) {
                throw new ConstraintDefinitionException(sprintf("The field '%s' is not mapped", $fieldName));
            }

            $getterMethod = 'get'.$camelFieldName;
            $value = $entity->$getterMethod();

            if ($constraint->ignoreNull && null === $value) {
                return;
            }

            $selector->$selectorMethod($value);
        }

        $iterator = new \Yucca\Component\Iterator\Iterator(
            $selector,
            $this->entityManager,
            get_class($entity)
        );

        /* If no entity matched the query criteria or a single entity matched,
         * which is the same as the entity being validated, the criteria is
         * unique.
         */
        if (0 == $iterator->count() || (1 == $iterator->count() && $entity->getId() == ($iterator->current()->getId()))) {
            return;
        }

        $errorPath = null !== $constraint->errorPath ? $constraint->errorPath : $fields[0];

        //$this->context->addViolationAt($errorPath, $constraint->message, array(), $value);
        $this->context->buildViolation($constraint->message)
            ->atPath($errorPath)
            ->addViolation();
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Yucca\Bundle\YuccaBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;

/**
 * This is the class that validates and merges configuration from your app/config files
 *
 * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
 */
class Configuration implements ConfigurationInterface
{
    /**
     * {@inheritDoc}
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('yucca');

        // Here you should define the parameters that are allowed to
        // configure your bundle. See the documentation linked above for
        // more information on that topic.
        $this->addConnections($rootNode);
        $this->addSchema($rootNode);
        $this->addSources($rootNode);
        $this->addMapping($rootNode);
        $this->addSelectors($rootNode);

        return $treeBuilder;
    }

    protected function addSchema(ArrayNodeDefinition $rootNode)
    {
        $rootNode
            ->children()
                ->arrayNode('schema')
                    ->useAttributeAsKey('alias')
                    ->prototype('array')
                        ->children()
                            ->scalarNode('sharding_strategy')->end()
                            ->arrayNode('sharding_strategy_options')
                                ->prototype('scalar')
                                ->end()
                            ->end()
                            ->arrayNode('shards')
                                ->prototype('scalar')
                                ->end()
                            ->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
        ;
    }

    protected function addConnections(ArrayNodeDefinition $rootNode)
    {
        $rootNode
            ->children()
                ->arrayNode('connections')
                    ->useAttributeAsKey('alias')
                    ->prototype('array')
                        ->children()
                            ->scalarNode('type')
                            ->end()
                            ->arrayNode('options')
                                ->useAttributeAsKey('alias')
                                ->prototype('variable')
                                ->end()
                            ->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
        ;
    }

    protected function addSources(ArrayNodeDefinition $rootNode)
    {
        $rootNode
            ->children()
                ->arrayNode('sources')
                    ->useAttributeAsKey('alias')
                    ->prototype('variable')
                    ->end()
                ->end()
            ->end()
        ;
    }

    protected function addSelectors(ArrayNodeDefinition $rootNode)
    {
        $rootNode
            ->children()
                ->arrayNode('selectors')
                    ->useAttributeAsKey('alias')
                    ->prototype('variable')
                    ->end()
                ->end()
            ->end()
        ;
    }

    protected function addMapping(ArrayNodeDefinition $rootNode)
    {
        $rootNode
            ->children()
                ->arrayNode('mapping')
                    ->useAttributeAsKey('alias')
                    ->prototype('array')
                        ->children()
                            ->arrayNode('timestampable')
                                ->useAttributeAsKey('alias')
                                ->prototype('variable')
                                ->end()
                            ->end()
                            ->scalarNode('mapper_class_name')
                            ->end()
                            ->arrayNode('properties')
                                ->useAttributeAsKey('alias')
                                ->prototype('variable')
                                ->end()
                            ->end()
                            ->arrayNode('sources')
                                ->useAttributeAsKey('alias')
                                ->prototype('variable')
                                ->end()
                            ->end()
                            ->arrayNode('selectors')
                                ->useAttributeAsKey('alias')
                                ->prototype('variable')
                                ->end()
                            ->end()
                            ->arrayNode('options')
                                ->useAttributeAsKey('alias')
                                ->prototype('variable')
                                ->end()
                            ->end()
                        ->end()
                    ->end()
                ->end()
            ->end()
        ;
    }
}


<?php

namespace Oh\ColorPickerTypeBundle\Form\Type;

use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;

class ColorPickerType extends ChoiceType {

    /**
     * {@inheritdoc}
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {

        $choiceList = function (Options $options) use (&$choiceListCache) {
            // Harden against NULL values (like in EntityType and ModelType)
            $choices = null !== $options['choices'] ? $options['choices'] : array();

            // Reuse existing choice lists in order to increase performance
            $hash = md5(json_encode(array($choices, $options['preferred_choices'])));

            if (!isset($choiceListCache[$hash])) {
                $choiceListCache[$hash] = new SimpleChoiceList($choices, $options['preferred_choices']);
            }

            return $choiceListCache[$hash];
        };

        $resolver->setDefaults(array(
            'multiple'          => false,
            'expanded'          => false,
            'choice_list'       => $choiceList,
            'choices'           =>
               array(
                    '#ffffff' =>'White',
                    '#cccccc' =>'Light Grey',
                    '#777777' =>'Grey',
                    '#333333' =>'Dark Grey',
                    '#000000' =>'Black',
                    '#2f4096' =>'Dark Blue',
                    '#0082be' =>'Light Blue',
                    '#32c4ec' =>'Aqua',
                    '#00944f' =>'Dark Green',
                    '#39af4c' =>'Light Green',
                    '#b2ce40' =>'Greenish',
                    '#6c2c8e' =>'Dark Purple',
                    '#913990' =>'Purple',
                    '#b989ba' =>'Lilac',
                    '#F934C5' =>'Dark Pink',
                    '#f3aebc' =>'Light Pink',
                    '#e81e25' =>'Red',
                    '#ed7043' =>'Peach',
                    '#f39f2b' =>'Orange',
                    '#ecba4b' =>'Light Orange',
                    '#fce92d' =>'Yellow',
                    '#f9eea9' =>'Cream',

//                  Alternative Color Palette
//                    "#ffffff"=>'White',
//                    "#000000"=>'Black',
//                    "#333333"=>'Dary Gray',
//                    "#7bd148"=>'Green',
//                    "#5484ed"=>'Bold blue',
//                    "#a4bdfc"=>'Blue',
//                    "#46d6db"=>'Turquoise',
//                    "#7ae7bf"=>'Light green',
//                    "#51b749"=>'Bold green',
//                    "#fbd75b"=>'Yellow',
//                    "#ffb878"=>'Orange',
//                    "#ff887c"=>'Red',
//                    "#F934C5"=>'Pink',
//                    "#dc2127"=>'Bold red',
//                    "#dbadff"=>'Purple',
//                    "#e1e1e1"=>'Gray'
                        ),
            'preferred_choices' => array(),
            'empty_data'        => null,
            'empty_value'       => null,
            'error_bubbling'    => false,
            'compound'          => false,
            'include_jquery'    => false,
            'include_js'        => false,
            'include_js_constructor'=>true,
            'include_css'       => false,
            'picker'            => false,
            'placeholder'       => false
        ));

    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        parent::buildView($view, $form, $options);

        $view->vars['include_jquery'] = $options['include_jquery'];
        $view->vars['include_js'] = $options['include_js'];
        $view->vars['include_js_constructor'] = $options['include_js_constructor'];
        $view->vars['include_css'] = $options['include_css'];
        $view->vars['picker'] = $options['picker'];

    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'oh_colorpicker';
    }
}


<?php
/*
 * This file was delivered to you as part of the Yucca package.
 *
 * (c) Rémi JANOT <r.janot@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Yucca\Component\SourceFactory;

use \Yucca\Component\Source\DatabaseMultipleRow;
use \Yucca\Component\SchemaManager;
use \Yucca\Component\ConnectionManager;
use \Yucca\Component\Source\DataParser\DataParser;

/**
 * Class DatabaseMultipleRowFactory
 * @package Yucca\Component\SourceFactory
 */
class DatabaseMultipleRowFactory implements SourceFactoryInterface
{
    /**
     * @var \Yucca\Component\SchemaManager
     */
    protected $schemaManager;

    /**
     * @var \Yucca\Component\ConnectionManager
     */
    protected $connectionManager;

    /**
     * @var \Yucca\Component\Source\DataParser\DataParser
     */
    protected $dataParser;

    /**
     * @param \Yucca\Component\SchemaManager                $schemaManager
     * @param \Yucca\Component\ConnectionManager            $connectionManager
     * @param \Yucca\Component\Source\DataParser\DataParser $dataParser
     */
    public function __construct(SchemaManager $schemaManager, ConnectionManager $connectionManager, DataParser $dataParser)
    {
        ;
        $this->schemaManager = $schemaManager;
        $this->connectionManager = $connectionManager;
        $this->dataParser = $dataParser;
    }

    /**
     * build source
     * @param string $sourceName
     * @param array  $params
     * @return \Yucca\Component\Source\DatabaseSingleRow
     */
    public function getSource($sourceName, array $params = array())
    {
        $toReturn = new DatabaseMultipleRow($sourceName, $params);
        $toReturn->setSchemaManager($this->schemaManager);
        $toReturn->setConnectionManager($this->connectionManager);
        $toReturn->setDataParser($this->dataParser);

        return $toReturn;
    }
}