<?php

namespace ebussola\common\datatype;

/**
 * @method \ebussola\common\datatype\Number bcadd($number) make the calc and return itself
 * @method \ebussola\common\datatype\Number bcsub($number) make the calc and return itself
 * @method \ebussola\common\datatype\Number bcmul($number) make the calc and return itself
 * @method \ebussola\common\datatype\Number bcdiv($number) make the calc and return itself
 *
 * @version 1.0b
 */
class Number
{

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

    /**
     * @var int
     */
    protected $decimals = 2;

    /**
     * @var bool
     */
    protected $isNegative = false;

    /**
     * @var integer
     */
    protected $precision = 14;

    /**
     * @param string $value
     */
    public function __construct($value = 0)
    {
        if (!extension_loaded('bcmath')) {
            trigger_error('bcmath not loaded, please install the extension: http://php.net/manual/en/book.bc.php');
        }

        $this->setValue($value);
    }

    /**
     * @param string|\ebussola\common\datatype\Number $value
     * @return Number
     */
    public function setValue($value)
    {
        if ($value instanceof Number) {
            $value = $value->getValue();
        } elseif (is_null($value) || $value == '') {
            $value = 0;
        }

        $value = $this->normalize($value);

        $value = preg_replace('/([^-0-9]*)([-]?)([0-9.]*).*/is', '$2$3', $value); //Clean all invalid chars
        if ($value < 0) {
            $this->isNegative = true;
        } else {
            $this->isNegative = false;
        }
        $this->value = (string)$value;

        return $this;
    }

    /**
     * @return string
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * @param integer $decimals
     * @return Number
     */
    public function setDecimals($decimals)
    {
        $this->decimals = $decimals;

        return $this;
    }

    /**
     * @return int
     */
    public function getDecimals()
    {
        return $this->decimals;
    }

    public function __call($name, $args)
    {
        if (substr($name, 0, 2) === 'bc') {
            $this->value = $this->bcCalc($name, $args);
        } else {
            throw new \Exception('Method do not exists. ' . $name);
        }

        return $this;
    }

    /**
     * @param $name
     * @param $args
     * @return String
     */
    protected function bcCalc($name, $args)
    {
        $value = current($args);
        if ($value instanceof number\Percentage) {
            switch ($name) {
                case 'bcmul' :
                case 'bcdiv' :
                    $value->bcdiv(100)
                        ->bcmul($this->getValue());
                    break;

                default :
                    $value = $value->of($this);
                    break;
            }
        } elseif (!$value instanceof Number) {
            if (is_numeric($value)) {
                $value = new Number($value);
            } else {
                trigger_error('BC Functions must be compared with another Number or a valid number');
            }
        }

        if ($name == 'bcdiv' && $value->getValue() == 0) {
            $result = 0;
        } else {
            $result = $name($this->getValue(), $value->getValue(), $this->getPrecision());
        }

        return $result;
    }

    /**
     * @return string
     */
    public function __toString()
    {
        return $this->getNumberFormat();
    }

    /**
     * @return bool
     */
    public function isNegative()
    {
        return (!$this->isZero() && $this->isNegative);
    }

    /**
     * @return bool
     */
    public function isPositive()
    {
        return (!$this->isZero() && !$this->isNegative);
    }

    /**
     * @return bool
     */
    public function isZero()
    {
        return bccomp($this->getValue(), 0) === 0;
    }

    /**
     * @param \ebussola\common\datatype\Number|String $number
     * @return boolean
     */
    public function isGreater($number)
    {
        if ($number instanceof Number) {
            $number = $number->getValue();
        }

        return bccomp($this->getValue(), $number) === 1;
    }

    /**
     * @param \ebussola\common\datatype\Number|String $number
     * @return boolean
     */
    public function isLess($number)
    {
        if ($number instanceof Number) {
            $number = $number->getValue();
        }

        return bccomp($this->getValue(), $number) === -1;
    }

    /**
     * @param \ebussola\common\datatype\Number|String $number
     * @return bool
     */
    public function isEqual($number)
    {
        if ($number instanceof Number) {
            $number = $number->getValue();
        }

        return bccomp($this->getValue(), $number) === 0;
    }

    /**
     * Number OF $value is what percentage?
     *
     * @param \ebussola\common\datatype\Number | String $value
     * @return number\Percentage
     */
    public function of($value)
    {
        $number = clone $this;

        return new number\Percentage($number->bcdiv($value)->bcmul(100)->getValue());
    }

    /**
     * Number IS $percentage of what Number?
     *
     * @param Number | float $percentage
     * @return Number
     */
    public function is($percentage)
    {
        $number = clone $this;

        if ($percentage instanceof Number) {
            $percentage = $percentage->getValue();
        }

        return $number->bcmul(100)->bcdiv($percentage);
    }

    /**
     * @param int $precision
     */
    public function setPrecision($precision)
    {
        $this->precision = $precision;
    }

    /**
     * @return int
     */
    public function getPrecision()
    {
        return $this->precision;
    }

    /**
     * Used to make calculations without change the value
     * Instead of change the value of itself, preserve it and return the calculated value
     *
     * @return Number
     */
    public function preserve()
    {
        return clone $this;
    }

    /**
     * @return string
     */
    private function getNumberFormat()
    {
        $numberFormatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL);
        $decPoint = $numberFormatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);
        $thousandPoint = $numberFormatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL);

        return number_format((float)$this->getValue(), $this->getDecimals(), $decPoint, $thousandPoint);
    }

    /**
     * @param String $number
     * @return String
     */
    private function normalize($number)
    {
        $numberFormatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL);
        $decPoint = $numberFormatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);
        $thousandPoint = $numberFormatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL);
        if (strstr($number, $decPoint)) {
            $number = str_replace($thousandPoint, '', $number);
            $number = str_replace($decPoint, '.', $number);
        }
        return $number;
    }

    /**
     * @param boolean $bool
     */
    protected function setNegative($bool)
    {
        $this->isNegative = (bool)$bool;
    }

    /**
     * @param String $value
     */
    protected function setRawValue($value)
    {
        $this->value = $value;
    }

}


<?php
/**
 * This file is part of the RedKite CMS Application and it is distributed
 * under the GPL LICENSE Version 2.0. To use this application you must leave
 * intact this copyright notice.
 *
 * Copyright (c) RedKite Labs <info@redkite-labs.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * For extra documentation and help please visit http://www.redkite-labs.com
 *
 * @license    GPL LICENSE Version 2.0
 *
 */
namespace RedKiteCms\Block\IconStacked\Core;

use JMS\Serializer\Annotation\Type;
use JMS\Serializer\Annotation\Exclude;
use RedKiteCms\Block\Icon\Core\IconBlock;
use RedKiteCms\Content\Block\ExtendableCollectionBlock;

/**
 * Class IconStackedBlock is the object deputed to handle a FontAwesome stacked icon
 *
 * @author  RedKite Labs <webmaster@redkite-labs.com>
 * @package RedKiteCms\Block\IconStacked\Core
 */
class IconStackedBlock extends ExtendableCollectionBlock
{
    /**
     * @Type("string")
     */
    protected $value = "stacked_icon_default_value";
    /**
     * @Type("string")
     */
    protected $type = "IconStacked";
    /**
     * @Type("string")
     */
    protected $customTag = "rkcms-icon-stacked";
    /**
     * Contructor
     */
    public function __construct($children = null, $value = null, array $tags = array())
    {
        if (null === $children) {
            $children = array(
                new IconBlock("", array('class' => "fa fa-circle-o fa-stack-2x")),
                new IconBlock("", array('class' => "fa fa-cog fa-stack-1x")),
            );
        }

        if (null !== $value) {
            $this->value = $value;
        }

        $this->tags = array(
            'class' => 'fa-stack fa-lg',
        );
        if (!empty($tags)) {
            $this->tags = $tags;
        }

        parent::__construct($children, $tags);
    }

    /**
     * {@inheritdoc}
     */
    protected function generateSourceFromChildren()
    {
        $this->translate();
        $source = parent::generateSourceFromChildren();
        $source["value"] = $this->value;

        return $source;
    }

    /**
     * {@inheritdoc}
     */
    protected function getTranslatorOptions()
    {
        return array(
            "fields" => array('value'),
        );
    }
}


<?php

/*
 * Chill is a software for social workers
 *
 * Copyright (C) 2014-2015, Champs Libres Cooperative SCRLFS,
 * <http://www.champs-libres.coop>, <info@champs-libres.coop>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

namespace Chill\CustomFieldsBundle\Templating\Twig;

use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Chill\CustomFieldsBundle\Entity\CustomField;

/**
 * Add the following Twig Extension :
 * * chill_custom_field_widget : to render the value of the custom field,
 * * chill_custom_field_label : to render the label of the custom field,
 *
 * @author Julien Fastré <julien.fastre@champs-libres.coop>
 */
class CustomFieldRenderingTwig extends \Twig_Extension implements ContainerAwareInterface
{

    /** @var Container $container The container */
    private $container;

    /** @var array $defaultParams The default parameters */
    private $defaultParams = array(
        'label_layout' => 'ChillCustomFieldsBundle:CustomField:render_label.html.twig'
    );

    /*
     * (non-PHPdoc)
     * @see \Symfony\Component\DependencyInjection\ContainerAwareInterface::setContainer()
     */
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    /*
     * (non-PHPdoc)
     * @see Twig_Extension::getFunctions()
     */
    public function getFunctions()
    {
        return [
            new \Twig_SimpleFunction('chill_custom_field_widget', array(
                $this,
                'renderWidget'
            ), array(
                'is_safe' => array(
                    'html'
                )
            )),
            new \Twig_SimpleFunction('chill_custom_field_label', array(
                $this,
                'renderLabel'
            ), array(
                'is_safe' => array(
                    'html'
                )
            )),
            new \Twig_SimpleFunction('chill_custom_field_is_empty', array(
                $this,
                'isEmptyValue'
            ))
        ];
    }

    public function isEmptyValue($customFieldorClass, $fields, $slug = null)
    {
        return $this->container->get('chill.custom_field.helper')
            ->isEmptyValue($fields, $customFieldorClass);
    }

    /* (non-PHPdoc)
     * @see Twig_ExtensionInterface::getName()
     */
    public function getName()
    {
        return 'chill_custom_fields_rendering';
    }

    /**
     * Twig Extension that is used to render the label of a custom field.
     *
     * @param CustomField|object|string $customFieldOrClass Either a customField OR a customizable_entity OR the FQDN of the entity
     * @param string $slug The slug ONLY necessary if the first argument is NOT a CustomField instance
     * @param array $params The parameters for rendering. Currently, 'label_layout' allow to choose a different label. Default is 'ChillCustomFieldsBundle:CustomField:render_label.html.twig'
     * @return string HTML representation of the custom field label.
     */
    public function renderLabel($customFieldOrClass, $slug = null, array $params = array())
    {
        $resolvedParams = array_merge($this->defaultParams, $params);

        $customField = ($customFieldOrClass instanceof CustomField)
            ? $customFieldOrClass : $this->container->get('chill.custom_field.provider')
                ->getCustomField($customFieldOrClass, $slug);

        return $this->container->get('templating')
            ->render($resolvedParams['label_layout'], array('customField' => $customField));
    }

    /**
     * Twig extension that is used to render the value of a custom field.
     *
     * The presentation of the value  is influenced by the document type.
     *
     * @param array $fields The array raw, as stored in the db
     * @param CustomField|object|string $customFieldOrClass Either a customField OR a customizable_entity OR the FQDN of the entity
     * @param string $documentType The type of the document (csv, html)
     * @param string $slug The slug of the custom field ONLY necessary if the first argument is NOT a CustomField instance
     * @return string HTML representation of the custom field value, as described in the CustomFieldInterface. Is HTML safe
     */
    public function renderWidget(array $fields, $customFieldOrClass, $documentType='html', $slug = null)
    {
        return $this->container->get('chill.custom_field.helper')
            ->renderCustomField($fields, $customFieldOrClass, $documentType, $slug);
    }
}


<?php

/*
 * This file is part of the Meta Reader package.
 *
 * (c) Stephan Wentz <stephan@wentz.it>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Temp\MetaReader;

use FFMpeg\FFProbe;
use FFMpeg\FFProbe\DataMapping\Stream;
use Temp\MetaReader\Value\MetaValue;
use Temp\MetaReader\Value\ValueBag;

/**
 * Ffprobe reader.
 *
 * @author Stephan Wentz <stephan@wentz.it>
 */
class FfprobeReader implements ReaderInterface
{
    /**
     * @var FFProbe
     */
    private $ffprobe;

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

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

    /**
     * {@inheritdoc}
     */
    public function supports($filename)
    {
        try {
            $streams = $this->ffprobe->streams($filename);
        } catch (\Exception $e) {
            return false;
        }

        foreach ($streams as $stream) {
            if (!$stream->has('codec_type') || !in_array($stream->get('codec_type'), ['audio', 'video'])) {
                return false;
            }
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function read($filename)
    {
        $meta = new ValueBag();

        try {
            $format = $this->ffprobe->format($filename);

            if ($format->has('format_name')) {
                $meta->set('media.format_name', new MetaValue($format->get('format_name')));
            }
            if ($format->has('format_long_name')) {
                $meta->set('media.format_long_name', new MetaValue($format->get('format_long_name')));
            }
            if ($format->has('duration')) {
                $meta->set('media.duration', new MetaValue($format->get('duration')));
            }
            if ($format->has('bit_rate')) {
                $meta->set('media.bit_rate', new MetaValue($format->get('bit_rate')));
            }
            if ($format->has('width')) {
                $meta->set('media.width', new MetaValue($format->get('width')));
            }
            if ($format->has('height')) {
                $meta->set('media.height', new MetaValue($format->get('height')));
            }
            if ($format->has('nb_streams')) {
                $meta->set('media.number_of_streams', new MetaValue($format->get('nb_streams')));
            }

            $streams = $this->ffprobe->streams($filename);

            foreach ($streams as $stream) {
                $index = $stream->get('index');
                $prefix = 'stream_'.$index;

                $type = 'media';
                if ($stream->isVideo()) {
                    $type = 'video';
                } elseif ($stream->isAudio()) {
                    $type = 'audio';
                }

                if ($stream->has('codec_type')) {
                    $meta->set("$type.$prefix.codec_type", new MetaValue($stream->get('codec_type')));
                }
                if ($stream->has('codec_name')) {
                    $meta->set("$type.$prefix.codec_name", new MetaValue($stream->get('codec_name')));
                }
                if ($stream->has('codec_long_name')) {
                    $meta->set("$type.$prefix.codec_long_name", new MetaValue($stream->get('codec_long_name')));
                }
                if ($stream->has('codec_time_base')) {
                    $meta->set("$type.$prefix.codec_time_base", new MetaValue($stream->get('codec_time_base')));
                }
                if ($stream->has('codec_tag_string')) {
                    $meta->set("$type.$prefix.codec_tag", new MetaValue($stream->get('codec_tag_string')));
                }
                if ($stream->has('bit_rate')) {
                    $meta->set("$type.$prefix.bit_rate", new MetaValue($stream->get('bit_rate')));
                }
                if ($stream->has('display_aspect_ration')) {
                    $meta->set("$type.$prefix.aspect_ratio", new MetaValue($stream->get('display_aspect_ratio')));
                }
                if ($stream->has('avg_frame_rate')) {
                    $meta->set("$type.$prefix.frame_rate", new MetaValue($stream->get('avg_frame_rate')));
                }
                if ($stream->has('bits_per_sample')) {
                    $meta->set("$type.$prefix.bits_per_sample", new MetaValue($stream->get('bits_per_sample')));
                }
                if ($stream->has('channels')) {
                    $meta->set("$type.$prefix.channels", new MetaValue($stream->get('channels')));
                }
            }
        } catch (\Exception $e) {
        }

        return $meta;
    }
}


<?php

namespace Senhung\CLI;

require_once 'Service.php';

/**
 * Class Command
 * @package Senhung\CLI
 */
class Command
{
    /** @var string $command */
    private $command;
    /** @var array $arguments */
    private $arguments;
    /** @var array $options */
    private $options;
    /** @var string $signature */
    protected $signature;
    /** @var string $description */
    protected $description;

    /**
     * Command constructor.
     */
    public function __construct()
    {
        $parsedSignature = Service::parseSignature($this->signature);
        $this->command = $parsedSignature[0];
        $this->arguments = $parsedSignature[1];
        $this->options = $parsedSignature[2];
    }

    /**
     * Update Arguments and Options
     *
     * @param array|null $arguments
     * @param array|null $options
     * @return void
     */
    public function update(array $arguments = null, array $options = null): void
    {
        /* Update Arguments */
        if ($arguments) {
            $keys = array_keys($this->arguments);
            for ($index = 0; $index < count($keys); $index++) {
                $this->arguments[$keys[$index]] = $arguments[$index];
            }
        }

        /* Update Options */
        if ($options) {
            foreach ($options as $option => $value) {
                $this->options[$option] = $value;
            }
        }
    }

    /**
     * Handle function when calling command
     *
     * @return void
     */
    public function handle()
    {
        return;
    }

    /**
     * Get command of current class
     *
     * @return string
     */
    public function getCommand(): string
    {
        return $this->command;
    }

    /**
     * Get description of command
     *
     * @return string
     */
    public function getDescription(): string
    {
        return $this->description;
    }

    /**
     * Get specific argument
     *
     * @param string $argument
     * @return mixed|null
     */
    protected function getArgument(string $argument)
    {
        if (isset($this->arguments[':' . $argument])) {
            return $this->arguments[':' . $argument];
        }

        return null;
    }

    /**
     * Get specific argument
     *
     * @param string $option
     * @return mixed|null
     */
    protected function getOption(string $option)
    {
        if (isset($this->options['--' . $option])) {
            return $this->options['--' . $option];
        }

        return null;
    }
}


<?php
/**
 * This file is part of the RedKite CMS Application and it is distributed
 * under the GPL LICENSE Version 2.0. To use this application you must leave
 * intact this copyright notice.
 *
 * Copyright (c) RedKite Labs <info@redkite-labs.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * For extra documentation and help please visit http://www.redkite-labs.com
 *
 * @license    GPL LICENSE Version 2.0
 *
 */

namespace RedKiteCms\Rendering\Controller\Deploy;

use RedKiteCms\Content\BlockManager\BlockManagerApprover;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
 * Class SavePageController is the object assigned to save a page in production
 *
 * @author  RedKite Labs <webmaster@redkite-labs.com>
 * @package RedKiteCms\Rendering\Controller\Page
 */
abstract class SavePageController extends BaseSavePageController
{
    /**
     * Implements the action to save the page
     * @param array $options
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function save(array $options)
    {
        $request = $options["request"];
        $serializer = $options["serializer"];
        $deployer = $options["deployer"];
        $saveOptions = array(
            'page' => $request->get('page'),
            'language' => $request->get('language'),
            'country' => $request->get('country'),
        );

        $blockManager = new BlockManagerApprover($serializer, new OptionsResolver());
        $deployer
            ->contributor($options["username"])
            ->save($blockManager, $saveOptions)
        ;

        $this->buldSitemap($options);
        $this->removeCache($options);

        return $this->buildJSonResponse(array());
    }
}


<?php
/**
 * com.xcitestudios.Generic
 *
 * @copyright Wade Womersley (xcitestudios)
 * @license http://www.opensource.org/licenses/mit-license.php MIT
 * @link https://xcitestudios.com/
 */

namespace com\xcitestudios\Generic\Text;

use com\xcitestudios\Generic\Text\Interfaces\TemplatedSerializableInterface;
use JsonSerializable;
use Mustache_Engine;
use stdClass;

/**
 * Simple serializable template using mustache
 *
 * @package com.xcitestudios.Generic
 * @subpackage Text
 */
class Template implements TemplatedSerializableInterface, JsonSerializable
{
    /**
     * Template content.
     *
     * @var string
     */
    protected $content;

    /**
     * Template context.
     *
     * @var stdClass
     */
    protected $context;

    /**
     * Sets the template version of the content to be used during rendering.
     *
     * @param string $content Template content.
     *
     * @return void
     */
    public function setContent($content)
    {
        $this->content = $content;
    }

    /**
     * Gets the template version of the content being used during rendering.
     *
     * @return string
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * Sets the object passed in to replace items in the content.
     *
     * @param stdClass $context Ibject passed in to replace items in the content.
     *
     * @return void
     */
    public function setContext(stdClass $context)
    {
        $this->context = $context;
    }

    /**
     * Gets the object passed in to replace items in the content.
     *
     * @return stdClass
     */
    public function getContext()
    {
        return $this->context;
    }

    /**
     * Renders content given the context object.
     *
     * @return string content rendered using the values in $context
     */
    public function render()
    {
        $engine = new Mustache_Engine();

        return $engine->render($this->content, $this->context);
    }

    /**
     * Updates the element implementing this interface using a JSON representation.
     *
     * This means updating the state of this object with that defined in the JSON
     * as opposed to returning a new instance of this object.
     *
     * @param string $jsonString Representation of the object.
     *
     * @return void
     */
    public function deserializeJSON($jsonString)
    {
        $data = json_decode($jsonString);

        $this->setContent($data->content);
        $this->setContext($data->context);
    }

    /**
     * Convert this object into JSON so it can be handled by anything that supports JSON.
     *
     * @return string A JSON representation of this object.
     */
    public function serializeJSON()
    {
        return json_encode($this->jsonSerialize());
    }

    /**
     * Specify data which should be serialized to JSON (PHP 5.4.0+ only).
     *
     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
     *
     * @return mixed data which can be serialized by <b>json_encode</b>,
     *                    which is a value of any type other than a resource.
     */
    public function jsonSerialize()
    {
        $ret = new stdClass();

        $ret->content = $this->content;
        $ret->context = $this->context;

        return $ret;
    }
}


<?php
/**
 * Implement a read-write-lock system, so that tasks can be executed without stepping on each other toes
 * (see http://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock)
 *
 * We avoid usage of php flock() call, as when on nfs it becomes unreliable.
 *
 * Known limitations:
 * - very simple algorithm - does not prevent writer starvation
 * - acquire() is all but atomic; we should do some stress testing to see how we fare...
 *   for discussions see: http://php.net/manual/en/function.getmypid.php, http://stackoverflow.com/questions/218451/locking-nfs-files-in-php
 * - killing processes or bad coding will leave lock files on disk. This is why we have a cleanup() function
 * - not really thread safe (esp. if user code tries to acquire 2 R locks on same token at same time in different threads)
 *
 * @author    G. Giunta
 * @copyright (C) G. Giunta 2013-2014
 * @license   code licensed under the GNU GPL 2.0: see README file
 */

namespace eZExtBuilder;

class SharedLock
{

    static $cleanedUp = false;

    /**
     * Returns true if the lock is acquired for the given token (no waiting here).
     * A Write lock can only be acquired as long as there are no W or R locks.
     * A Read lock can be acquired as long as there are no W locks.
     * Does not not complain if 2 Read locks are taken on the same token by the same php script.
     *
     * @param string $token
     * @param int $mode LOCK_SH (reader) or LOCK_EX (writer)
     * @param array $opts
     * @param bool $autoCleanup when true, on first lock acquired we remove any stale locks found
     * @return bool
     */
    static public function acquire( $token, $mode, $opts=array(), $autoCleanup=true /*, $task=''*/ )
    {
        // just in case (is_file results might be cached!)...
        clearstatcache();

        if ( $autoCleanup && !self::$cleanedUp )
        {
            self::cleanup( $opts );
            self::$cleanedUp = true;
        }

        $lockDir = self::lockDir( $opts );
        $wLockFile = "$lockDir/{$token}_W.lock";

        if ( file_exists( $wLockFile ) )
        {
            return false;
        }

        if ( $mode == LOCK_EX && count( glob( $lockDir . "/{$token}_R/*.lock" ) ) )
        {
            return false;
        }

        if ( $mode == LOCK_EX )
        {
            pake_mkdirs( $lockDir );
            if ( !file_put_contents( $wLockFile, getmypid() /*. ' ' . $task*/, LOCK_EX ) )
            {
                pake_echo_error( "Could not create W lock file '$wLockFile'" );
                return false;
            }
            return true;
        }

        // assume a read lock
        $rLockFile = "$lockDir/{$token}_R/" . getmypid() . ".lock";
        pake_mkdirs( "$lockDir/{$token}_R/" );
        // we assume to be running in single-thread mode: do not lock the file for writing
        if ( !file_put_contents( $rLockFile, getmypid() /*. ' ' . $task*/ ) )
        {
            // log some error?
            pake_echo_error( "Could not create R lock file '$wLockFile'" );
            return false;
        }
        return true;
    }

    /**
     * Releases the token. Does not warn if lock has disappeared before the release.
     * @param string $token
     * @param int $mode
     * @param array $opts
     */
    static function release( $token, $mode, $opts=array() )
    {
        // just in case (is_file results might be cached!)...
        clearstatcache();

        $lockDir = self::lockDir( $opts );
        if ( $mode == LOCK_EX )
        {
            $wLockFile = "$lockDir/{$token}_W.lock";
            if ( is_file(  $wLockFile ) && !unlink( $wLockFile ) )
            {
                // what to do here? we echo an error msg but do not throw an exception
                pake_echo_error( "Could not remove W lock file '$wLockFile'" );
            }
            return;
        }
        // assume a read lock
        $rLockFile = "$lockDir/{$token}_R/" . getmypid() . ".lock";
        if ( is_file(  $rLockFile ) && !unlink( $rLockFile ) )
        {
            // what to do here? we echo an error msg but do not throw an exception
            pake_echo_error( "Could not remove R lock file '$rLockFile'" );
        }
    }

    /**
     * Removes orphaned lock files - by checking their PIDs against running processes
     * @param array $opts
     */
    static public function cleanup( $opts=array() )
    {
        if ( strtoupper( substr( PHP_OS, 0, 3 ) ) == 'WIN' )
        {
            exec( 'tasklist /FO CSV', $runningProcesses, $return_var );
            $runningProcesses = array_map(
                function( $line ){ $cols = explode( ',', $line ); return trim( $cols[1], '"' ); },
                $runningProcesses );
            unset( $runningProcesses[0] ); // 'PID'
            sort( $runningProcesses );
            unset( $runningProcesses[0] ); // 0
        }
        else
        {
            exec( 'ps -e -o pid', $runningProcesses, $return_var );
        }

        if ( $return_var != 0 )
        {
            pake_echo_error( "Could not get list of processes to remove stale lock files" );
            return;
        }

        $lockDir = self::lockDir( $opts );
        foreach( glob( $lockDir . "/*_W.lock" ) as $writeLock )
        {
            $pid = file_get_contents( $writeLock ); //strstr( file_get_contents( $writeLock ), ' ', true );
            if ( !in_array( $pid, $runningProcesses ) )
            {
                pake_unlink( $writeLock );
            }
        }
        foreach( glob( $lockDir . "/*_R/*.lock" ) as $readLock )
        {
            $pid = file_get_contents( $readLock ); // strstr( file_get_contents( $readLock ), ' ', true );
            if ( !in_array( $pid, $runningProcesses ) )
            {
                pake_unlink( $readLock );
            }
        }
    }

    static protected function lockDir( $opts=array() )
    {
        $build = Builder::getBuildDir( $opts );
        return $build == '' ? './locks' : "$build/locks";
    }

}


<?php
/**
 * @link http://psesd.org/
 *
 * @copyright Copyright (c) 2015 Puget Sound ESD
 * @license http://psesd.org/license/
 */

namespace cascade\components\dataInterface\connectors\generic;

use cascade\components\dataInterface\Action;
use cascade\components\dataInterface\Module as BaseModule;
use canis\action\Action as BaseAction;
use Yii;

/**
 * Module [[@doctodo class_description:cascade\components\dataInterface\connectors\generic\Module]].
 *
 * @author Jacob Morrison <email@ofjacob.com>
 */
abstract class Module extends BaseModule
{
    /**
     * @var [[@doctodo var_type:dataSourceClass]] [[@doctodo var_description:dataSourceClass]]
     */
    public $dataSourceClass = 'cascade\components\dataInterface\connectors\generic\DataSource';

    /**
     * @var [[@doctodo var_type:_models]] [[@doctodo var_description:_models]]
     */
    protected $_models;

    /**
     * @var [[@doctodo var_type:_dataSources]] [[@doctodo var_description:_dataSources]]
     */
    protected $_dataSources;
    /**
     * @var [[@doctodo var_type:_action]] [[@doctodo var_description:_action]]
     */
    protected $_action;

    /**
     * Get foreign object.
     *
     * @param [[@doctodo param_type:foreignModelClass]] $foreignModelClass [[@doctodo param_description:foreignModelClass]]
     * @param [[@doctodo param_type:foreignPrimaryKey]] $foreignPrimaryKey [[@doctodo param_description:foreignPrimaryKey]]
     */
    abstract public function getForeignObject($foreignModelClass, $foreignPrimaryKey);
    /**
     * Get foreign model.
     *
     * @param [[@doctodo param_type:model]] $model [[@doctodo param_description:model]]
     */
    abstract public function getForeignModel($model);

    /**
     * @inheritdoc
     */
    public function run(BaseAction $action)
    {
        $this->_action = $action;
        if (!$this->beforeRun()) {
            // @todo add something to action log
            return false;
        }
        $total = 0;
        $taskSets = [];
        foreach ($this->dataSources as $source) {
            $id = md5(uniqid(rand(), true));
            if ($source->settings['direction'] === 'to_local') {
                $prefix = 'Importing';
            } elseif ($source->settings['direction'] === 'to_foreign') {
                $prefix = 'Exporting';
            } else {
                $prefix = 'Syncing';
            }

            $task = $action->status->addTask($id, $prefix . ' ' . $source->descriptor);
            $source->task = $task;
            $source->prepareTask();
            $taskSets[] = [
                'task' => $task,
                'dataSource' => $source,
            ];
        }

        foreach ($taskSets as $taskSet) {
            $task = $taskSet['task'];
            $dataSource = $taskSet['dataSource'];
            $dataSource->run();
        }
        if (!$this->afterRun()) {
            // @todo add action log
            return false;
        }

        return true;
    }

    /**
     * [[@doctodo method_description:beforeRun]].
     *
     * @return [[@doctodo return_type:beforeRun]] [[@doctodo return_description:beforeRun]]
     */
    public function beforeRun()
    {
        return true;
    }

    /**
     * [[@doctodo method_description:afterRun]].
     *
     * @return [[@doctodo return_type:afterRun]] [[@doctodo return_description:afterRun]]
     */
    public function afterRun()
    {
        return true;
    }

    /**
     * Get local object.
     *
     * @param [[@doctodo param_type:localModelClass]]   $localModelClass   [[@doctodo param_description:localModelClass]]
     * @param [[@doctodo param_type:foreignPrimaryKey]] $foreignPrimaryKey [[@doctodo param_description:foreignPrimaryKey]]
     *
     * @return [[@doctodo return_type:getLocalObject]] [[@doctodo return_description:getLocalObject]]
     */
    public function getLocalObject($localModelClass, $foreignPrimaryKey)
    {
        $dataSource = $this->getLocalDataSource($localModelClass);
        if (is_array($foreignPrimaryKey) && isset($foreignPrimaryKey['localId'])) {
            $registryClass = Yii::$app->classes['Registry'];

            return $registryClass::getObject($foreignPrimaryKey['localId'], false);
        }
        if ($dataSource && ($foreignDataItem = $dataSource->getForeignDataItem($foreignPrimaryKey))) {
            return $foreignDataItem->handle(true);
        }

        return false;
    }

    /**
     * Get data source.
     *
     * @param [[@doctodo param_type:dataSourceName]] $dataSourceName [[@doctodo param_description:dataSourceName]]
     *
     * @return [[@doctodo return_type:getDataSource]] [[@doctodo return_description:getDataSource]]
     */
    public function getDataSource($dataSourceName)
    {
        if (isset($this->dataSources[$dataSourceName])) {
            return $this->dataSources[$dataSourceName];
        }

        return false;
    }

    /**
     * Get data sources.
     *
     * @return [[@doctodo return_type:getDataSources]] [[@doctodo return_description:getDataSources]]
     */
    public function getDataSources()
    {
        if (is_null($this->_dataSources)) {
            $this->_dataSources = [];
            foreach ($this->dataSources() as $foreignModel => $dataSource) {
                if (is_numeric($foreignModel) || isset($dataSources['foreignModel'])) {
                    if (!isset($dataSources['foreignModel'])) {
                        continue;
                    }
                    $foreignModel = $dataSources['foreignModel'];
                    unset($dataSources['foreignModel']);
                }
                if (!isset($dataSource['class'])) {
                    $dataSource['class'] = $this->dataSourceClass;
                }
                $dataSource['name'] = $foreignModel;
                $dataSource['foreignModel'] = $this->getForeignModel($foreignModel);
                if (empty($dataSource['foreignModel'])) {
                    continue;
                }
                $this->_dataSources[$foreignModel] = Yii::createObject(array_merge(['module' => $this], $dataSource));
            }
        }

        return $this->_dataSources;
    }

    /**
     * Get local data source.
     *
     * @param [[@doctodo param_type:localModelClass]] $localModelClass [[@doctodo param_description:localModelClass]]
     *
     * @return [[@doctodo return_type:getLocalDataSource]] [[@doctodo return_description:getLocalDataSource]]
     */
    public function getLocalDataSource($localModelClass)
    {
        foreach ($this->dataSources as $dataSource) {
            if ($dataSource->localModel === $localModelClass) {
                return $dataSource;
            }
        }

        return false;
    }

    /**
     * Get foreign data source.
     *
     * @param [[@doctodo param_type:foreignModelClass]] $foreignModelClass [[@doctodo param_description:foreignModelClass]]
     *
     * @return [[@doctodo return_type:getForeignDataSource]] [[@doctodo return_description:getForeignDataSource]]
     */
    public function getForeignDataSource($foreignModelClass)
    {
        foreach ($this->dataSources as $dataSource) {
            if ($dataSource->foreignModel->modelName === $foreignModelClass) {
                return $dataSource;
            }
        }

        return false;
    }

    /**
     * Get action.
     *
     * @return [[@doctodo return_type:getAction]] [[@doctodo return_description:getAction]]
     */
    public function getAction()
    {
        if (is_null($this->_action)) {
            $this->_action = new Action();
        }

        return $this->_action;
    }
}


<?php

/*
 * This file is part of the overtrue/wechat.
 *
 * (c) overtrue <i@overtrue.me>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

/**
 * Device.php.
 *
 * @author    allen05ren <allen05ren@outlook.com>
 * @copyright 2016 overtrue <i@overtrue.me>
 *
 * @see       https://github.com/overtrue
 * @see       http://overtrue.me
 */

namespace EasyWeChat\ShakeAround;

use EasyWeChat\Core\AbstractAPI;
use EasyWeChat\Core\Exceptions\InvalidArgumentException;

/**
 * Class Device.
 */
class Device extends AbstractAPI
{
    const API_DEVICE_APPLYID = 'https://api.weixin.qq.com/shakearound/device/applyid';
    const API_DEVICE_APPLYSTATUS = 'https://api.weixin.qq.com/shakearound/device/applystatus';
    const API_DEVICE_UPDATE = 'https://api.weixin.qq.com/shakearound/device/update';
    const API_DEVICE_BINDLOCATION = 'https://api.weixin.qq.com/shakearound/device/bindlocation';
    const API_DEVICE_SEARCH = 'https://api.weixin.qq.com/shakearound/device/search';

    /**
     * Apply device ids.
     *
     * @param int    $quantity
     * @param string $reason
     * @param string $comment
     * @param int    $poiId
     *
     * @return \EasyWeChat\Support\Collection
     */
    public function apply($quantity, $reason, $comment = '', $poiId = null)
    {
        $params = [
            'quantity' => intval($quantity),
            'apply_reason' => $reason,
        ];

        if (!empty($comment)) {
            $params['comment'] = $comment;
        }

        if (!is_null($poiId)) {
            $params['poi_id'] = intval($poiId);
        }

        return $this->parseJSON('json', [self::API_DEVICE_APPLYID, $params]);
    }

    /**
     * Get audit status.
     *
     * @param int $applyId
     *
     * @return \EasyWeChat\Support\Collection
     */
    public function getStatus($applyId)
    {
        $params = [
            'apply_id' => intval($applyId),
        ];

        return $this->parseJSON('json', [self::API_DEVICE_APPLYSTATUS, $params]);
    }

    /**
     * Update a device comment.
     *
     * @param array  $deviceIdentifier
     * @param string $comment
     *
     * @return \EasyWeChat\Support\Collection
     */
    public function update(array $deviceIdentifier, $comment)
    {
        $params = [
            'device_identifier' => $deviceIdentifier,
            'comment' => $comment,
        ];

        return $this->parseJSON('json', [self::API_DEVICE_UPDATE, $params]);
    }

    /**
     * Bind location for device.
     *
     * @param array  $deviceIdentifier
     * @param int    $poiId
     * @param int    $type
     * @param string $poiAppid
     *
     * @return \EasyWeChat\Support\Collection
     *
     * @throws InvalidArgumentException
     */
    public function bindLocation(array $deviceIdentifier, $poiId, $type = 1, $poiAppid = null)
    {
        $params = [
            'device_identifier' => $deviceIdentifier,
            'poi_id' => intval($poiId),
        ];

        if ($type === 2) {
            if (is_null($poiAppid)) {
                throw new InvalidArgumentException('If value of argument #3 is 2, argument #4 is required.');
            }
            $params['type'] = 2;
            $params['poi_appid'] = $poiAppid;
        }

        return $this->parseJSON('json', [self::API_DEVICE_BINDLOCATION, $params]);
    }

    /**
     * Fetch batch of devices by deviceIds.
     *
     * @param array $deviceIdentifiers
     *
     * @return \EasyWeChat\Support\Collection
     */
    public function fetchByIds(array $deviceIdentifiers)
    {
        $params = [
            'type' => 1,
            'device_identifiers' => $deviceIdentifiers,
        ];

        return $this->fetch($params);
    }

    /**
     * Pagination to fetch batch of devices.
     *
     * @param int $lastSeen
     * @param int $count
     *
     * @return \EasyWeChat\Support\Collection
     */
    public function pagination($lastSeen, $count)
    {
        $params = [
            'type' => 2,
            'last_seen' => intval($lastSeen),
            'count' => intval($count),
        ];

        return $this->fetch($params);
    }

    /**
     * Fetch batch of devices by applyId.
     *
     * @param int $applyId
     * @param int $lastSeen
     * @param int $count
     *
     * @return \EasyWeChat\Support\Collection
     */
    public function fetchByApplyId($applyId, $lastSeen, $count)
    {
        $params = [
            'type' => 3,
            'apply_id' => intval($applyId),
            'last_seen' => intval($lastSeen),
            'count' => intval($count),
        ];

        return $this->fetch($params);
    }

    /**
     * Fetch batch of devices.
     *
     * @param array $params
     *
     * @return \EasyWeChat\Support\Collection
     */
    private function fetch($params)
    {
        return $this->parseJSON('json', [self::API_DEVICE_SEARCH, $params]);
    }
}


<?php

declare(strict_types=1);

namespace GBProd\ElasticaSpecification\QueryFactory;

use Elastica\QueryBuilder;
use GBProd\ElasticaSpecification\Registry;
use GBProd\Specification\AndX;
use GBProd\Specification\Specification;

/**
 * Factory for AndX specification
 *
 * @author gbprod <contact@gb-prod.fr>
 */
class AndXFactory implements Factory
{
    /**
     * @var Registry
     */
    private $registry;

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

    /**
     * {inheritdoc}
     */
    public function create(Specification $spec, QueryBuilder $qb)
    {
        if (!$spec instanceof AndX) {
            throw new \InvalidArgumentException();
        }

        $firstPartFactory  = $this->registry->getFactory($spec->getFirstPart());
        $secondPartFactory = $this->registry->getFactory($spec->getSecondPart());

        return $qb->query()->bool()
            ->addMust($firstPartFactory->create($spec->getFirstPart(), $qb))
            ->addMust($secondPartFactory->create($spec->getSecondPart(), $qb))
        ;
    }
}


<?php

/*
 * This file is part of the Dektrium project.
 *
 * (c) Dektrium project <http://github.com/dektrium/>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace dektrium\user\controllers;

use dektrium\user\Finder;
use dektrium\user\models\Account;
use dektrium\user\models\LoginForm;
use yii\base\Model;
use yii\helpers\Url;
use yii\web\Controller;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use yii\authclient\ClientInterface;
use yii\web\Response;
use yii\widgets\ActiveForm;

/**
 * Controller that manages user authentication process.
 *
 * @property \dektrium\user\Module $module
 *
 * @author Dmitry Erofeev <dmeroff@gmail.com>
 */
class SecurityController extends Controller
{
    /** @var Finder */
    protected $finder;

    /**
     * @param string $id
     * @param \yii\base\Module $module
     * @param Finder $finder
     * @param array $config
     */
    public function __construct($id, $module, Finder $finder, $config = [])
    {
        $this->finder = $finder;
        parent::__construct($id, $module, $config);
    }

    /** @inheritdoc */
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'rules' => [
                    ['allow' => true, 'actions' => ['login', 'auth'], 'roles' => ['?']],
                    ['allow' => true, 'actions' => ['logout'], 'roles' => ['@']],
                ]
            ],
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'logout' => ['post']
                ]
            ]
        ];
    }

    /** @inheritdoc */
    public function actions()
    {
        return [
            'auth' => [
                'class' => 'yii\authclient\AuthAction',
                'successCallback' => [$this, 'authenticate'],
            ]
        ];
    }

    /**
     * Displays the login page.
     * @return string|\yii\web\Response
     */
    public function actionLogin()
    {
        $model = \Yii::createObject(LoginForm::className());

        $this->performAjaxValidation($model);

        if ($model->load(\Yii::$app->getRequest()->post()) && $model->login()) {
            return $this->goBack();
        }

        return $this->render('login', [
            'model'  => $model,
            'module' => $this->module,
        ]);
    }

    /**
     * Logs the user out and then redirects to the homepage.
     * @return \yii\web\Response
     */
    public function actionLogout()
    {
        \Yii::$app->getUser()->logout();
        return $this->goHome();
    }

    /**
     * Logs the user in if this social account has been already used. Otherwise shows registration form.
     * @param  ClientInterface $client
     * @return \yii\web\Response
     */
    public function authenticate(ClientInterface $client)
    {
        $attributes = $client->getUserAttributes();
        $provider   = $client->getId();
        $clientId   = $attributes['id'];

        $account = $this->finder->findAccountByProviderAndClientId($provider, $clientId);

        if ($account === null) {
            $account = \Yii::createObject([
                'class'      => Account::className(),
                'provider'   => $provider,
                'client_id'  => $clientId,
                'data'       => json_encode($attributes),
            ]);
            $account->save(false);
        }

        if (null === ($user = $account->user)) {
            $this->action->successUrl = Url::to(['/user/registration/connect', 'account_id' => $account->id]);
        } else {
            \Yii::$app->user->login($user, $this->module->rememberFor);
        }
    }

    /**
     * Performs ajax validation.
     * @param Model $model
     * @throws \yii\base\ExitException
     */
    protected function performAjaxValidation(Model $model)
    {
        if (\Yii::$app->request->isAjax && $model->load(\Yii::$app->request->post())) {
            \Yii::$app->response->format = Response::FORMAT_JSON;
            echo json_encode(ActiveForm::validate($model));
            \Yii::$app->end();
        }
    }
}


<?php

/*
 * This file is part of the Common API Interface package.
 *
 * (c) Pavel Logachev <alhames@mail.ru>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Alhames\Api;

use Alhames\Api\Exception\ParseContentException;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\RequestOptions;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;

/**
 * Class HttpClient.
 */
class HttpClient implements \Serializable, LoggerAwareInterface
{
    use LoggerAwareTrait;

    const USER_AGENT = 'alhames-api/'.ApiClientInterface::VERSION;

    /** @var float Query per second */
    private $qps;
    /** @var array */
    private $config;
    /** @var Client */
    private $client;
    /** @var float */
    private $lastRequestTime;

    /**
     * InternalApiClient constructor.
     *
     * @param int|float|null $qps
     * @param array          $config
     */
    public function __construct($qps = null, array $config = [])
    {
        $this->qps = $qps ? (float) $qps : null;
        $this->config = array_merge([
            RequestOptions::HTTP_ERRORS => true,
            RequestOptions::ALLOW_REDIRECTS => false,
            RequestOptions::HEADERS => [HttpInterface::HEADER_USER_AGENT => self::USER_AGENT],
        ], $config);
        $this->client = new Client($this->config);
    }

    /**
     * @param ResponseInterface $response
     *
     * @return null|string
     */
    public static function getContentType(ResponseInterface $response): ?string
    {
        $contentTypes = $response->getHeader(HttpInterface::HEADER_CONTENT_TYPE);
        if (empty($contentTypes[0])) {
            return null;
        }

        if (false === strpos($contentTypes[0], ';')) {
            return $contentTypes[0];
        }

        return substr($contentTypes[0], 0, strpos($contentTypes[0], ';'));
    }

    /**
     * @param string     $method
     * @param string     $uri
     * @param array|null $get
     * @param array|null $post
     * @param array|null $files
     * @param array|null $headers
     *
     * @throws GuzzleException
     *
     * @return string
     */
    public function requestContent(string $method, string $uri, ?array $get = null, ?array $post = null, ?array $files = null, ?array $headers = null)
    {
        $options = $this->prepareOptions($get, $post, $files, $headers);

        return (string) $this->request($method, $uri, $options)->getBody();
    }

    /**
     * @param string $method
     * @param string $uri
     * @param array  $options
     *
     * @throws GuzzleException
     *
     * @return ResponseInterface
     */
    public function request(string $method, string $uri, array $options = []): ResponseInterface
    {
        if (null !== $this->qps && null !== $this->lastRequestTime) {
            $lastInterval = floor((microtime(true) - $this->lastRequestTime) * 1000000);
            $timeout = ceil(1000000 / $this->qps);
            if ($lastInterval < $timeout) {
                usleep($timeout - $lastInterval);
            }
        }

        try {
            $response = $this->client->request($method, $uri, $options);
        } catch (RequestException $e) {
            $response = $e->getResponse();
            throw $e;
        } finally {
            $this->lastRequestTime = microtime(true);
            if (null !== $this->logger) {
                $statusCode = !empty($response) ? $response->getStatusCode() : 0;
                $this->logger->debug(sprintf('"%s %s" %d', $method, $uri, $statusCode), [
                    'method' => $method,
                    'uri' => $uri,
                    'options' => $options,
                    'time' => $this->lastRequestTime,
                    'response' => $response ?? null,
                ]);
            }
        }

        return $response;
    }

    /**
     * @param string     $method
     * @param string     $uri
     * @param array|null $get
     * @param array|null $post
     * @param array|null $files
     * @param array|null $headers
     *
     * @throws GuzzleException
     * @throws ParseContentException
     *
     * @return mixed
     */
    public function requestJson(string $method, string $uri, ?array $get = null, ?array $post = null, ?array $files = null, ?array $headers = null)
    {
        $headers = array_merge([HttpInterface::HEADER_ACCEPT => 'application/json'], $headers ?: []);
        $options = $this->prepareOptions($get, $post, $files, $headers);
        $response = $this->request($method, $uri, $options);

        return $this->parseJsonResponse($response);
    }

    /**
     * @param string     $method
     * @param string     $uri
     * @param mixed      $data
     * @param array|null $headers
     *
     * @throws GuzzleException
     * @throws ParseContentException
     *
     * @return mixed
     */
    public function sendJson(string $method, string $uri, $data, ?array $headers = null)
    {
        $headers = array_merge([HttpInterface::HEADER_ACCEPT => 'application/json'], $headers ?: []);
        $options = $this->prepareOptions(null, null, null, $headers);
        $options[RequestOptions::JSON] = $data;
        $response = $this->request($method, $uri, $options);

        return $this->parseJsonResponse($response);
    }

    /**
     * @see http://openid.net/specs/openid-authentication-2_0.html#anchor4
     *
     * @param string     $method
     * @param string     $uri
     * @param array|null $get
     * @param array|null $post
     * @param array|null $files
     * @param array|null $headers
     *
     * @throws GuzzleException
     * @throws ParseContentException
     *
     * @return array
     */
    public function requestKeyValueForm(string $method, string $uri, ?array $get = null, ?array $post = null, ?array $files = null, ?array $headers = null): array
    {
        $options = $this->prepareOptions($get, $post, $files, $headers);
        $response = $this->request($method, $uri, $options);
        if (!preg_match_all("#(?<key>.+?)\:(?<value>.+)#", (string) $response->getBody(), $matches)) {
            throw new ParseContentException($response, 'key-value');
        }

        return array_combine($matches['key'], $matches['value']);
    }

    /**
     * @param ResponseInterface $response
     *
     * @throws ParseContentException
     *
     * @return mixed
     */
    public function parseJsonResponse(ResponseInterface $response)
    {
        if (!in_array(static::getContentType($response), ['application/json', 'application/javascript', 'text/javascript'], true)) {
            throw new ParseContentException($response, 'json');
        }

        $content = (string) $response->getBody();
        try {
            return \GuzzleHttp\json_decode($content);
        } catch (\InvalidArgumentException $e) {
            throw new ParseContentException($response, 'json', $e);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function serialize()
    {
        return serialize([$this->qps, $this->config, $this->lastRequestTime, $this->logger]);
    }

    /**
     * {@inheritdoc}
     */
    public function unserialize($serialized)
    {
        list($this->qps, $this->config, $this->lastRequestTime, $this->logger) = unserialize($serialized);
        $this->client = new Client($this->config);
    }

    /**
     * @param null|string $option
     *
     * @return array|mixed|null
     */
    public function getConfig(?string $option = null)
    {
        return null === $option
            ? $this->config
            : (isset($this->config[$option]) ? $this->config[$option] : null);
    }

    /**
     * @todo Fix load from uri
     * @todo Fix load from string
     *
     * @param array|null $get
     * @param array|null $post
     * @param array|null $files
     * @param array|null $headers
     *
     * @return array
     */
    private function prepareOptions(?array $get = null, ?array $post = null, ?array $files = null, ?array $headers = null): array
    {
        $options = [
            RequestOptions::QUERY => $get ?: [],
            RequestOptions::HEADERS => $headers ?: [],
        ];
        if (!empty($files)) {
            $elements = [];
            foreach ($post ?: [] as $key => $value) {
                $elements[] = ['name' => $key, 'contents' => (string) $value];
            }
            foreach ($files as $key => $file) {
                if ($file instanceof \SplFileInfo) {
                    $fileName = $file->getFilename();
                    $contents = $file->isFile() ? fopen($file->getRealPath(), 'r') : file_get_contents($file->getPathname());
                } else {
                    $fileName = $key;
                    $contents = $file;
                }
                $elements[] = ['name' => $key, 'contents' => $contents, 'filename' => $fileName];
            }
            $options[RequestOptions::MULTIPART] = $elements;
        } elseif (!empty($post)) {
            $options[RequestOptions::FORM_PARAMS] = $post;
        }

        return $options;
    }
}


<?php

/*
 * This file is part of the Predis package.
 *
 * (c) Daniele Alessandri <suppakilla@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Predis\Connection\Replication;

use Predis\ClientException;
use Predis\Command\CommandInterface;
use Predis\Command\RawCommand;
use Predis\Connection\ConnectionException;
use Predis\Connection\FactoryInterface;
use Predis\Connection\NodeConnectionInterface;
use Predis\Replication\MissingMasterException;
use Predis\Replication\ReplicationStrategy;
use Predis\Response\ErrorInterface as ResponseErrorInterface;

/**
 * Aggregate connection handling replication of Redis nodes configured in a
 * single master / multiple slaves setup.
 *
 * @author Daniele Alessandri <suppakilla@gmail.com>
 */
class MasterSlaveReplication implements ReplicationInterface
{
    /**
     * @var ReplicationStrategy
     */
    protected $strategy;

    /**
     * @var NodeConnectionInterface
     */
    protected $master;

    /**
     * @var NodeConnectionInterface[]
     */
    protected $slaves = array();

    /**
     * @var NodeConnectionInterface[]
     */
    protected $pool = array();

    /**
     * @var NodeConnectionInterface[]
     */
    protected $aliases = array();

    /**
     * @var NodeConnectionInterface
     */
    protected $current;

    /**
     * @var bool
     */
    protected $autoDiscovery = false;

    /**
     * @var FactoryInterface
     */
    protected $connectionFactory;

    /**
     * {@inheritdoc}
     */
    public function __construct(ReplicationStrategy $strategy = null)
    {
        $this->strategy = $strategy ?: new ReplicationStrategy();
    }

    /**
     * Configures the automatic discovery of the replication configuration on failure.
     *
     * @param bool $value Enable or disable auto discovery.
     */
    public function setAutoDiscovery($value)
    {
        if (!$this->connectionFactory) {
            throw new ClientException('Automatic discovery requires a connection factory');
        }

        $this->autoDiscovery = (bool) $value;
    }

    /**
     * Sets the connection factory used to create the connections by the auto
     * discovery procedure.
     *
     * @param FactoryInterface $connectionFactory Connection factory instance.
     */
    public function setConnectionFactory(FactoryInterface $connectionFactory)
    {
        $this->connectionFactory = $connectionFactory;
    }

    /**
     * Resets the connection state.
     */
    protected function reset()
    {
        $this->current = null;
    }

    /**
     * {@inheritdoc}
     */
    public function add(NodeConnectionInterface $connection)
    {
        $parameters = $connection->getParameters();

        if ('master' === $parameters->role) {
            $this->master = $connection;
        } else {
            // everything else is considered a slvave.
            $this->slaves[] = $connection;
        }

        if (isset($parameters->alias)) {
            $this->aliases[$parameters->alias] = $connection;
        }

        $this->pool[(string) $connection] = $connection;

        $this->reset();
    }

    /**
     * {@inheritdoc}
     */
    public function remove(NodeConnectionInterface $connection)
    {
        if ($connection === $this->master) {
            $this->master = null;
        } elseif (false !== $id = array_search($connection, $this->slaves, true)) {
            unset($this->slaves[$id]);
        } else {
            return false;
        }

        unset($this->pool[(string) $connection]);

        if ($this->aliases && $alias = $connection->getParameters()->alias) {
            unset($this->aliases[$alias]);
        }

        $this->reset();

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function getConnectionByCommand(CommandInterface $command)
    {
        if (!$this->current) {
            if ($this->strategy->isReadOperation($command) && $slave = $this->pickSlave()) {
                $this->current = $slave;
            } else {
                $this->current = $this->getMasterOrDie();
            }

            return $this->current;
        }

        if ($this->current === $master = $this->getMasterOrDie()) {
            return $master;
        }

        if (!$this->strategy->isReadOperation($command) || !$this->slaves) {
            $this->current = $master;
        }

        return $this->current;
    }

    /**
     * {@inheritdoc}
     */
    public function getConnectionById($id)
    {
        if (isset($this->pool[$id])) {
            return $this->pool[$id];
        }
    }

    /**
     * Returns a connection instance by its alias.
     *
     * @param string $alias Connection alias.
     *
     * @return NodeConnectionInterface|null
     */
    public function getConnectionByAlias($alias)
    {
        if (isset($this->aliases[$alias])) {
            return $this->aliases[$alias];
        }
    }

    /**
     * Returns a connection by its role.
     *
     * @param string $role Connection role (`master` or `slave`)
     *
     * @return NodeConnectionInterface|null
     */
    public function getConnectionByRole($role)
    {
        if ($role === 'master') {
            return $this->getMaster();
        } elseif ($role === 'slave') {
            return $this->pickSlave();
        }
    }

    /**
     * Switches the internal connection in use by the backend.
     *
     * @param NodeConnectionInterface $connection Connection instance in the pool.
     */
    public function switchTo(NodeConnectionInterface $connection)
    {
        if ($connection && $connection === $this->current) {
            return;
        }

        if ($connection !== $this->master && !in_array($connection, $this->slaves, true)) {
            throw new \InvalidArgumentException('Invalid connection or connection not found.');
        }

        $this->current = $connection;
    }

    /**
     * {@inheritdoc}
     */
    public function switchToMaster()
    {
        if (!$connection = $this->getConnectionByRole('master')) {
            throw new \InvalidArgumentException('Invalid connection or connection not found.');
        }

        $this->switchTo($connection);
    }

    /**
     * {@inheritdoc}
     */
    public function switchToSlave()
    {
        if (!$connection = $this->getConnectionByRole('slave')) {
            throw new \InvalidArgumentException('Invalid connection or connection not found.');
        }

        $this->switchTo($connection);
    }

    /**
     * {@inheritdoc}
     */
    public function getCurrent()
    {
        return $this->current;
    }

    /**
     * {@inheritdoc}
     */
    public function getMaster()
    {
        return $this->master;
    }

    /**
     * Returns the connection associated to the master server.
     *
     * @return NodeConnectionInterface
     */
    private function getMasterOrDie()
    {
        if (!$connection = $this->getMaster()) {
            throw new MissingMasterException('No master server available for replication');
        }

        return $connection;
    }

    /**
     * {@inheritdoc}
     */
    public function getSlaves()
    {
        return $this->slaves;
    }

    /**
     * Returns the underlying replication strategy.
     *
     * @return ReplicationStrategy
     */
    public function getReplicationStrategy()
    {
        return $this->strategy;
    }

    /**
     * Returns a random slave.
     *
     * @return NodeConnectionInterface
     */
    protected function pickSlave()
    {
        if ($this->slaves) {
            return $this->slaves[array_rand($this->slaves)];
        }
    }

    /**
     * {@inheritdoc}
     */
    public function isConnected()
    {
        return $this->current ? $this->current->isConnected() : false;
    }

    /**
     * {@inheritdoc}
     */
    public function connect()
    {
        if (!$this->current) {
            if (!$this->current = $this->pickSlave()) {
                if (!$this->current = $this->getMaster()) {
                    throw new ClientException('No available connection for replication');
                }
            }
        }

        $this->current->connect();
    }

    /**
     * {@inheritdoc}
     */
    public function disconnect()
    {
        foreach ($this->pool as $connection) {
            $connection->disconnect();
        }
    }

    /**
     * Handles response from INFO.
     *
     * @param string $response
     *
     * @return array
     */
    private function handleInfoResponse($response)
    {
        $info = array();

        foreach (preg_split('/\r?\n/', $response) as $row) {
            if (strpos($row, ':') === false) {
                continue;
            }

            list($k, $v) = explode(':', $row, 2);
            $info[$k] = $v;
        }

        return $info;
    }

    /**
     * Fetches the replication configuration from one of the servers.
     */
    public function discover()
    {
        if (!$this->connectionFactory) {
            throw new ClientException('Discovery requires a connection factory');
        }

        RETRY_FETCH: {
            try {
                if ($connection = $this->getMaster()) {
                    $this->discoverFromMaster($connection, $this->connectionFactory);
                } elseif ($connection = $this->pickSlave()) {
                    $this->discoverFromSlave($connection, $this->connectionFactory);
                } else {
                    throw new ClientException('No connection available for discovery');
                }
            } catch (ConnectionException $exception) {
                $this->remove($connection);
                goto RETRY_FETCH;
            }
        }
    }

    /**
     * Discovers the replication configuration by contacting the master node.
     *
     * @param NodeConnectionInterface $connection        Connection to the master node.
     * @param FactoryInterface        $connectionFactory Connection factory instance.
     */
    protected function discoverFromMaster(NodeConnectionInterface $connection, FactoryInterface $connectionFactory)
    {
        $response = $connection->executeCommand(RawCommand::create('INFO', 'REPLICATION'));
        $replication = $this->handleInfoResponse($response);

        if ($replication['role'] !== 'master') {
            throw new ClientException("Role mismatch (expected master, got slave) [$connection]");
        }

        $this->slaves = array();

        foreach ($replication as $k => $v) {
            $parameters = null;

            if (strpos($k, 'slave') === 0 && preg_match('/ip=(?P<host>.*),port=(?P<port>\d+)/', $v, $parameters)) {
                $slaveConnection = $connectionFactory->create(array(
                    'host' => $parameters['host'],
                    'port' => $parameters['port'],
                    'role' => 'slave',
                ));

                $this->add($slaveConnection);
            }
        }
    }

    /**
     * Discovers the replication configuration by contacting one of the slaves.
     *
     * @param NodeConnectionInterface $connection        Connection to one of the slaves.
     * @param FactoryInterface        $connectionFactory Connection factory instance.
     */
    protected function discoverFromSlave(NodeConnectionInterface $connection, FactoryInterface $connectionFactory)
    {
        $response = $connection->executeCommand(RawCommand::create('INFO', 'REPLICATION'));
        $replication = $this->handleInfoResponse($response);

        if ($replication['role'] !== 'slave') {
            throw new ClientException("Role mismatch (expected slave, got master) [$connection]");
        }

        $masterConnection = $connectionFactory->create(array(
            'host' => $replication['master_host'],
            'port' => $replication['master_port'],
            'role' => 'master',
        ));

        $this->add($masterConnection);

        $this->discoverFromMaster($masterConnection, $connectionFactory);
    }

    /**
     * Retries the execution of a command upon slave failure.
     *
     * @param CommandInterface $command Command instance.
     * @param string           $method  Actual method.
     *
     * @return mixed
     */
    private function retryCommandOnFailure(CommandInterface $command, $method)
    {
        RETRY_COMMAND: {
            try {
                $connection = $this->getConnectionByCommand($command);
                $response = $connection->$method($command);

                if ($response instanceof ResponseErrorInterface && $response->getErrorType() === 'LOADING') {
                    throw new ConnectionException($connection, "Redis is loading the dataset in memory [$connection]");
                }
            } catch (ConnectionException $exception) {
                $connection = $exception->getConnection();
                $connection->disconnect();

                if ($connection === $this->master && !$this->autoDiscovery) {
                    // Throw immediately when master connection is failing, even
                    // when the command represents a read-only operation, unless
                    // automatic discovery has been enabled.
                    throw $exception;
                } else {
                    // Otherwise remove the failing slave and attempt to execute
                    // the command again on one of the remaining slaves...
                    $this->remove($connection);
                }

                // ... that is, unless we have no more connections to use.
                if (!$this->slaves && !$this->master) {
                    throw $exception;
                } elseif ($this->autoDiscovery) {
                    $this->discover();
                }

                goto RETRY_COMMAND;
            } catch (MissingMasterException $exception) {
                if ($this->autoDiscovery) {
                    $this->discover();
                } else {
                    throw $exception;
                }

                goto RETRY_COMMAND;
            }
        }

        return $response;
    }

    /**
     * {@inheritdoc}
     */
    public function writeRequest(CommandInterface $command)
    {
        $this->retryCommandOnFailure($command, __FUNCTION__);
    }

    /**
     * {@inheritdoc}
     */
    public function readResponse(CommandInterface $command)
    {
        return $this->retryCommandOnFailure($command, __FUNCTION__);
    }

    /**
     * {@inheritdoc}
     */
    public function executeCommand(CommandInterface $command)
    {
        return $this->retryCommandOnFailure($command, __FUNCTION__);
    }

    /**
     * {@inheritdoc}
     */
    public function __sleep()
    {
        return array('master', 'slaves', 'pool', 'aliases', 'strategy');
    }
}


<?php

namespace Bavix\SDK\FileLoader;

use Bavix\Helpers\File;

class IniWriter
{

    /**
     * @param string $filename
     * @param array  $config
     * @param string $header
     *
     * @return int
     */
    public function toFile($filename, array $config, $header = null)
    {
        $ini = $this->toString($config, $header);
        return File::put($filename, $ini);
    }

    /**
     * @param array $config
     * @param string|null  $header
     *
     * @return string
     */
    public function toString(array $config, $header = null)
    {
        $ini = !empty($header) ? $header . PHP_EOL : '';

        uasort($config, function ($first, $second) {
            if (is_array($first)) {
                return 1;
            }

            if (is_array($second))
            {
                return -1;
            }

            return 0;
        });

        $names = array_keys($config);

        foreach ($names as $name)
        {
            $section = $config[$name];

            if (!is_array($section))
            {
                $ini .= $name . ' = ' . $this->encodeValue($section) . PHP_EOL;
                continue;
            }

            if (empty($section))
            {
                continue;
            }

            if (!empty($ini))
            {
                $ini .= PHP_EOL;
            }

            $ini .= "[$name]" . PHP_EOL;

            foreach ($section as $option => $value)
            {
                if (is_numeric($option))
                {
                    $option = $name;
                    $value  = (array)$value;
                }

                if (is_array($value))
                {
                    foreach ($value as $key => $currentValue)
                    {
                        $ini .= $option . '[' . $key . '] = ' . $this->encodeValue($currentValue) . PHP_EOL;
                    }
                }
                else
                {
                    $ini .= $option . ' = ' . $this->encodeValue($value) . PHP_EOL;
                }
            }

            $ini .= "\n";
        }

        return $ini;
    }

    /**
     * @param $value
     *
     * @return int|string
     */
    protected function encodeValue($value)
    {
        if (is_bool($value))
        {
            return (int)$value;
        }

        if (is_string($value))
        {
            return '"' . $value . '"';
        }

        return $value;
    }

}


<?php
/**
 * @link http://psesd.org/
 *
 * @copyright Copyright (c) 2015 Puget Sound ESD
 * @license http://psesd.org/license/
 */

namespace cascade\components\db\behaviors;

use Yii;

/**
 * RelatedObjects [[@doctodo class_description:cascade\components\db\behaviors\RelatedObjects]].
 *
 * @author Jacob Morrison <email@ofjacob.com>
 */
class RelatedObjects extends \canis\db\behaviors\ActiveRecord
{
    /**
     * @var [[@doctodo var_type:companionObject]] [[@doctodo var_description:companionObject]]
     */
    public $companionObject = false;
    /**
     * @var [[@doctodo var_type:companionRelationship]] [[@doctodo var_description:companionRelationship]]
     */
    public $companionRelationship = false;
    /**
     * @var [[@doctodo var_type:companionRole]] [[@doctodo var_description:companionRole]]
     */
    public $companionRole = false;
    /**
     * @var [[@doctodo var_type:relation]] [[@doctodo var_description:relation]]
     */
    public $relation;
    /**
     * @var [[@doctodo var_type:_relatedObjects]] [[@doctodo var_description:_relatedObjects]]
     */
    protected $_relatedObjects = [];
    /**
     * @var [[@doctodo var_type:_relatedObjectsFlat]] [[@doctodo var_description:_relatedObjectsFlat]]
     */
    protected $_relatedObjectsFlat = [];
    /**
     * @var [[@doctodo var_type:_relations]] [[@doctodo var_description:_relations]]
     */
    protected $_relations = [];

    /**
     * @inheritdoc
     */
    public function events()
    {
        return [
            \canis\db\ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
            \canis\db\ActiveRecord::EVENT_AFTER_UPDATE => 'afterSave',
            \canis\db\ActiveRecord::EVENT_AFTER_INSERT => 'afterSave',
            \canis\db\ActiveRecord::EVENT_BEFORE_UPDATE => 'beforeSave',
            \canis\db\ActiveRecord::EVENT_BEFORE_INSERT => 'beforeSave',
        ];
    }
    /**
     * [[@doctodo method_description:collectModels]].
     *
     * @param array $models [[@doctodo param_description:models]] [optional]
     *
     * @return [[@doctodo return_type:collectModels]] [[@doctodo return_description:collectModels]]
     */
    public function collectModels($models = [])
    {
        if (!isset($models['relations'])) {
            $models['relations'] = [];
        }
        if ($this->owner->tabularId) {
            $models[$this->owner->tabularId] = $this->owner;
        } else {
            $models['primary'] = $this->owner;
        }
        foreach ($this->_relatedObjectsFlat as $related) {
            $models = $related->collectModels($models);
        }
        foreach ($this->_relations as $key => $relation) {
            if (!is_object($relation)) {
                if (!isset($relation['class'])) {
                    $relation['class'] = Yii::$app->classes['Relation'];
                }
                $relation = Yii::createObject($relation);
            }
            $models['relations'][$key] = $relation;
        }

        return $models;
    }

    /**
     * [[@doctodo method_description:beforeSave]].
     *
     * @param [[@doctodo param_type:event]] $event [[@doctodo param_description:event]]
     *
     * @return [[@doctodo return_type:beforeSave]] [[@doctodo return_description:beforeSave]]
     */
    public function beforeSave($event)
    {
        foreach ($this->_relations as $key => $relation) {
            unset($relation['_moduleHandler']);
            if (!empty($this->companionObject)) {
                if ($this->companionRole === 'child') {
                    $relation['parent_object_id'] = $this->companionObject->primaryKey;
                } else {
                    $relation['child_object_id'] = $this->companionObject->primaryKey;
                }
            }
            if (empty($relation['child_object_id']) && empty($relation['parent_object_id'])) {
                if (!empty($this->_relations) && (!$this->companionObject || empty($this->companionObject->primaryKey))) {
                    $event->isValid = false;
                    $this->owner->addError('_', 'Saving relations with no companion object! ' . get_class($this->owner));

                    return false;
                }
            }
            $this->owner->registerRelationModel($relation, $key);
        }
    }

    /**
     * [[@doctodo method_description:afterSave]].
     *
     * @param [[@doctodo param_type:event]] $event [[@doctodo param_description:event]]
     *
     * @return [[@doctodo return_type:afterSave]] [[@doctodo return_description:afterSave]]
     */
    public function afterSave($event)
    {
        foreach ($this->_relatedObjectsFlat as $relatedObject) {
            if (!$relatedObject->save()) {
                $event->handled = false;
                $this->owner->addError('_', $relatedObject->objectType->title->upperSingular . ' could not be saved!');
            }
        }

        return $event->handled;
    }

    /**
     * [[@doctodo method_description:beforeValidate]].
     *
     * @param [[@doctodo param_type:event]] $event [[@doctodo param_description:event]]
     *
     * @return [[@doctodo return_type:beforeValidate]] [[@doctodo return_description:beforeValidate]]
     */
    public function beforeValidate($event)
    {
        foreach ($this->_relatedObjectsFlat as $relatedObject) {
            if (!$relatedObject->validate()) {
                $this->owner->addError('_', $relatedObject->objectType->title->upperSingular . ' did not validate.');
                $event->isValid = false;

                return false;
            }
        }

        return true;
    }

    /**
     * Set related objects.
     *
     * @param [[@doctodo param_type:relatedObjects]] $relatedObjects [[@doctodo param_description:relatedObjects]]
     */
    public function setRelatedObjects($relatedObjects)
    {
        foreach ($relatedObjects as $modelName => $objects) {
            if (!isset($this->_relatedObjects[$modelName])) {
                $this->_relatedObjects[$modelName] = [];
            }
            foreach ($objects as $tabId => $objectAttributes) {
                if (!isset($objectAttributes['_moduleHandler'])) {
                    continue;
                }
                list($relationship, $role) = $this->owner->objectType->getRelationship($objectAttributes['_moduleHandler']);
                $relatedHandler = $this->owner->objectType->getRelatedType($objectAttributes['_moduleHandler']);
                if (!$relatedHandler) {
                    continue;
                }
                $objectAttributes = array_merge([
                    'companionObject' => $this->owner,
                    'companionRelationship' => $relationship,
                    'companionRole' => $role,
                    ], $objectAttributes);
                $object = $relatedHandler->getModel(null, $objectAttributes);
                $object->tabularId = $objectAttributes['_moduleHandler'];
                if ((!$object
                    || $object->isEmptyObject())
                    && !($relationship->required)
                ) {
                    continue;
                }

                $object->companionObject = $object->indirectObject = $this->owner;
                $object->companionRelationship = $relationship;
                $object->companionRole = $role;
                $this->_relatedObjects[$modelName][$tabId] = $object;
                $this->_relatedObjectsFlat[] = $object;
            }
        }
    }

    /**
     * Get related objects.
     *
     * @return [[@doctodo return_type:getRelatedObjects]] [[@doctodo return_description:getRelatedObjects]]
     */
    public function getRelatedObjects()
    {
        return $this->_relatedObjects;
    }

    /**
     * Set relations.
     *
     * @param [[@doctodo param_type:value]] $value [[@doctodo param_description:value]]
     */
    public function setRelations($value)
    {
        if ($this->companionObject) {
            $baseObject = $this->companionObject;
        } else {
            $baseObject = $this->owner;
        }
        $fields = $baseObject->getFields();
        foreach ($value as $tabId => $relation) {
            if (!isset($relation['_moduleHandler'])) {
                \d("boom");
                exit;
                continue;
            }
            if (!isset($fields[$relation['_moduleHandler']])) {
                \d($relation['_moduleHandler']);
                \d(array_keys($fields));
                exit;
                continue;
            }
            $baseAttributes = [];
            $model = $fields[$relation['_moduleHandler']]->model;
            if (empty($model)) {
                $model = $fields[$relation['_moduleHandler']]->resetModel();
            }
            $model->attributes = $relation;
            $model->_moduleHandler = $relation['_moduleHandler'];
            $model->tabularId = $relation['_moduleHandler'];
            list($relationship, $role) = $baseObject->objectType->getRelationship($model->_moduleHandler);
            $relatedHandler = $baseObject->objectType->getRelatedType($model->_moduleHandler);
            if (!$relatedHandler) {
                continue;
            }
            if (!$this->owner->tabularId  // primary object
                && !$this->owner->isNewRecord
                && empty($model->parent_object_id)
                && empty($model->child_object_id)) {
                continue;
            }
            $this->_relations[$tabId] = $model;
        }
    }

    /**
     * Get relations.
     *
     * @return [[@doctodo return_type:getRelations]] [[@doctodo return_description:getRelations]]
     */
    public function getRelations()
    {
        return $this->_relations;
    }

    /**
     * @inheritdoc
     */
    public function safeAttributes()
    {
        return ['relatedObjects', 'relations', 'companionObject', 'companionRole', 'companionRelationship'];
    }
}


<?php

/*
 * This file is part of the Сáша framework.
 *
 * (c) tchiotludo <http://github.com/tchiotludo>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

declare(strict_types = 1);

namespace Cawa\Renderer;

use Cawa\Controller\ViewController;

trait ContainerTrait
{
    /**
     * @var ViewController[]
     */
    protected $elements = [];

    /**
     * @param ViewController|ViewController[] ...$elements
     *
     * @return $this|self
     */
    public function add(ViewController ...$elements)
    {
        foreach ($elements as $element) {
            $this->elements[] = $element;
        }

        return $this;
    }

    /**
     * @param ViewController|ViewController[] ...$elements
     *
     * @return $this|self
     */
    public function addFirst(ViewController ...$elements)
    {
        foreach ($elements as $element) {
            array_unshift($this->elements, $element);
        }

        return $this;
    }

    /**
     * @return $this|self
     */
    public function clear()
    {
        $this->elements = [];

        return $this;
    }

    /**
     * @return ViewController
     */
    public function first()
    {
        return $this->elements[0] ?? null;
    }

    /**
     * @return int
     */
    public function count() : int
    {
        return sizeof($this->elements);
    }

    /**
     * @param ViewController $compare
     *
     * @return int|null
     */
    protected function getIndex(ViewController $compare = null)
    {
        if (is_null($compare)) {
            return null;
        }

        $index = null;
        foreach ($this->elements as $i => $element) {
            if ($element === $compare) {
                $index = $i;
            }
        }

        return $index;
    }

    /**
     * @return ViewController[]
     */
    public function getElements() : array
    {
        return $this->elements;
    }

    /**
     * @return string
     */
    public function render()
    {
        $content = '';
        foreach ($this->elements as $element) {
            $content .= $element->render() . "\n";
        }

        return $content;
    }
}


<?php

namespace Versatile\Search;

use XType\Casting\Contracts\InputCaster;
use XType\StringType;
use XType\AbstractType;
use Versatile\Search\Contracts\CriteriaBuilder;
use Illuminate\Http\Request;
use Versatile\Search\Contracts\Filter as FilterContract;
use Versatile\Search\Contracts\Criteria as CriteriaContract;
use Versatile\Search\Criteria;
use Versatile\Introspection\Contracts\TypeIntrospector;
use Versatile\View\Contracts\ModelPresenter;

/**
 * The FlatCriteriaBuilder builds criterias out of flat get arrays which doesnt
 * need to be encoded. This leads to readable get parameters but is not as
 * flexible as working with complete arrays.
 *
 * The main features are:
 *
 * Operators by $key-$operator. This class assumes you have no minus signs in
 * your model properties/columns.
 *
 * Supported operators:
 * greater:      >
 * less:         <
 * greaterEqual: >=
 * lessEqual:    <=
 * in:           IN (', ' separated value)
 * not:          <>
 * equals:       =
 * like:         like
 * between:      BETWEEN (' - ' separated value)
 *
 * So a query could look like this:
 * /users/?name-like=John&last_login-between=2015/21/05 - 2015/28/05
 *
 **/
class FlatCriteriaBuilder implements CriteriaBuilder
{

    public $operatorSeparator = '-';

    public $sortParam = 'sort';

    public $directionParam = 'order';

    public $fullTextParam = 'q';

    public $pageParam = 'page';

    /**
     * @var array
     **/
    protected $handlers = [];

    protected $caster;

    protected $types;

    protected $scaffold;

    /**
     * @var \Versatile\Search\Contracts\Criteria
     **/
    protected $criteriaPrototype;

    public function __construct(InputCaster $caster, TypeIntrospector $types,
                                ModelPresenter $scaffold, CriteriaContract $criteria=null)
    {
        $this->caster = $caster;
        $this->types = $types;
        $this->scaffold = $scaffold;
        $this->criteriaPrototype = $criteria ?: new Criteria;
    }

    /**
     * {@inheritdoc}
     *
     * @param string $modelClass
     * @param array $parameters
     * @param string $contentType (optional)
     * @return \Versatile\Search\Contracts\Criteria
     **/
    public function criteria($modelClass, array $parameters, $contentType='text/html')
    {

        if ($this->hasHandler($contentType)) {
            return $this->callHandler($modelClass, $parameters, $contentType);
        }

        return $this->buildCriteria($modelClass, $parameters);

    }

    public function handleContentType($contentType, callable $handler)
    {
        $this->handlers[$contentType] = $handler;
        return $this;
    }

    public function hasHandler($contentType)
    {
        return isset($this->handlers[$contentType]);
    }

    public function setCriteriaPrototype(CriteriaContract $criteria)
    {
        $this->criteriaPrototype = $criteria;
        return $this;
    }

    protected function buildCriteria($modelClass, array $params)
    {

        $criteria = $this->newCriteria();

        $criteria->setModelClass($modelClass);

        $casted = $this->castInput($params);

        $this->addExpressions($modelClass, $criteria->filter(), $casted);

        $this->addSortIfPassed($criteria, $params);

        return $criteria;

    }

    protected function castInput($input)
    {
        return $this->caster->with('!nested','!type')->castInput($input);
    }

    protected function addExpressions($modelClass, FilterContract $filter, $casted)
    {
        foreach ($casted as $key=>$value) {
            if ($key == $this->sortParam || $key == $this->directionParam) {
                continue;
            }
            if ($key == $this->pageParam) {
                continue;
            }
            if ($key == $this->fullTextParam) {
                $this->addFullTextCriteria($modelClass, $filter, $value);
                continue;
            }
            if ($value === '') {
                continue;
            }
            $filter->add($this->toExpression($modelClass, $filter, $key, $value));
        }
    }

    protected function addFullTextCriteria($modelClass, $filter, $value)
    {

        $searchableKeys = $this->scaffold->searchableKeys($modelClass, ModelPresenter::VIEW_FULLTEXT);

        if (!$searchableKeys) {
            return;
        }

        foreach ($searchableKeys as $key) {
            $filter->where($key, 'like', "%$value%", 'or');
        }

    }

    protected function toExpression($modelClass, FilterContract $filter, $key, $value)
    {

        if (!$type = $this->types->keyType($modelClass, $key)) {
            $type = new StringType;
        }

        list($key, $operator) = $this->splitOperator($key);

        if (!$operator) {
            $operator = $this->getDefaultOperator($type, $value);
        }

        $castedValue = $type->castToModel($value);

        return new Expression($key, $operator, $this->formatForOperator($castedValue, $operator));

    }

    protected function splitOperator($key)
    {
        if (str_contains($key, $this->operatorSeparator)) {
            return explode($this->operatorSeparator, $key);
        }
        return [$key, ''];
    }

    protected function getDefaultOperator($type, $value)
    {
        switch ($type->getGroup()) {
            case AbstractType::STRING:
                return 'like';
            default:
                return '=';

        }
    }

    protected function formatForOperator($value, $operator)
    {
        if ($operator == 'like' && is_string($value)) {
            return str_replace('*','%', $value);
        }
        return $value;
    }

    protected function addSortIfPassed(CriteriaContract $criteria, array $params)
    {

        if (!isset($params[$this->sortParam])) {
            return;
        }

        $direction = isset($params[$this->directionParam]) ? $params[$this->directionParam] : 'asc';

        $direction = in_array($direction, ['asc','desc']) ? $direction : 'asc';

        $criteria->sort($params[$this->sortParam], $direction);

    }

    protected function callHandler($modelClass, $parameters, $contentType)
    {
        return call_user_func($this->handlers[$contentType], $modelClass, $parameters, $contentType);
    }

    protected function newCriteria()
    {
        return clone $this->criteriaPrototype;
    }

}