<?php

namespace Relaxed\Merge;

use Relaxed\Merge\ConflictException;

class ThreeWayMerge
{
    /**
     * Perform merge on associative array
     *
     * @param array $ancestor
     * @param array $local
     * @param array $remote
     *
     * @return array
     */
    public function performMerge(array $ancestor, array $local, array $remote)
    {
        // Returning a new Array for now. Can return the modified ancestor as well.
        $merged = [];
        foreach ($ancestor as $key => $value) {
            // Checks if the value contains an array itself.
            if (is_array($value) && array_key_exists($key, $local) && array_key_exists($key, $remote)) {
                $merged[$key] = $this->performMerge(
                    $value,
                    $local[$key],
                    $remote[$key]
                );
            } else {
                if (array_key_exists($key, $local) && array_key_exists($key, $remote)) {
                    $merged[$key] = $this->merge(
                        $ancestor[$key],
                        $local[$key],
                        $remote[$key],
                        $key
                    );
                } elseif (array_key_exists($key, $local)) {
                    if ($ancestor[$key] != $local[$key]) {
                        throw new ConflictException("A conflict has occured");
                    }
                } elseif (array_key_exists($key, $remote)) {
                    if ($ancestor[$key] != $remote[$key]) {
                        throw new ConflictException("A conflict has occured");
                    }
                } else {
                    unset($merged[$key]);
                }
            }
        }
        return $merged;
    }

    /**
     * Function to perform merge. Do not call it directly.
     *
     * @param string $x
     * @param string $y
     * @param string $z
     * @param mixed $key
     *
     * @return mixed
     * @throws Exception
     */
    protected function merge($x, $y, $z, $key)
    {
        // Convert the value into array.
        $ancestor = (strpos($x, PHP_EOL) !== false ? explode(PHP_EOL, $x) : array($x));
        $local = (strpos($y, PHP_EOL) !== false ? explode(PHP_EOL, $y) : array($y));
        $remote = (strpos($z, PHP_EOL) !== false ? explode(PHP_EOL, $z) : array($z));

        // Count number of lines in value or elements in new formed array.
        $count_ancestor = count($ancestor);
        $count_remote = count($remote);
        $count_local = count($local);

        // If number of lines is different in all 3 values.
        // For example : addition in remote and removal in local node.
        //
        // Else get the value of number of lines in updated node.
        // For example : Addition of 2 lines in local.
        // Suppose: $count_ancestor = 2 and $count_remote = 2
        // then, $count_local would be 4 now.
        if ($count_ancestor != $count_local
            && $count_local!= $count_remote
            && $count_ancestor != $count_remote
        ) {
            $merged = $this->linesAddedRemovedAndModified(
                $ancestor,
                $local,
                $remote,
                $count_ancestor,
                $count_local,
                $count_remote
            );
        } else {
            // Store the updated count value in a variable $count.
            if ($count_ancestor == $count_local) {
                $count = $count_remote;
            } else {
                $count = $count_local;
            }
            // If $count > $count_ancestor, that means lines have been added.
            // Otherwise, lines has been removed or modified.
            if ($count > $count_ancestor) {
                $merged = $this->linesAddedOrModified(
                    $ancestor,
                    $local,
                    $remote,
                    $count,
                    $count_remote,
                    $count_ancestor,
                    $count_local
                );
            } else {
                $merged = $this->linesRemovedOrModified(
                    $ancestor,
                    $local,
                    $remote,
                    $count_ancestor,
                    $count_local,
                    $count_remote
                );
            }
        }
        // Convert returned array back to string.
        $merged[$key] = implode(PHP_EOL, $merged);
        return $merged[$key];
    }

    /**
     * Handles the addition of lines.
     *
     * @param array $ancestor
     * @param array $local
     * @param array $remote
     * @param $count
     * @param $count_remote
     * @param $count_ancestor
     * @param $count_local
     *
     * @return array
     * @throws Exception
     */
    protected function linesAddedOrModified(
        array $ancestor,
        array $local,
        array $remote,
        $count,
        $count_remote,
        $count_ancestor,
        $count_local
    ) {
        $merged = [];
        $counter = 0;
        // For all ancestors lines, it will check local and remote
        // and make sure only one of them has been edited.
        // Otherwise, throw an Exception.
        foreach ($ancestor as $key => $value) {
            $counter = $counter + 1;
            if ($ancestor[$key] == $local[$key]) {
                $merged[$key] = $remote[$key];
            } elseif ($ancestor[$key] == $remote[$key]
                || $local[$key] == $remote[$key]) {
                $merged[$key] = $local[$key];
            } else {
                throw new ConflictException("A conflict has occured");
            }
        }
        // Once done with ancestor lines, we have hunk of
        // lines added. We will add them as they are.
        // If the lines are added in both remote and local,
        // We will make sure they are same or throw exception.
        for ($i = $count_ancestor; $i < $count; $i++) {
            if ($count_ancestor == $count_remote) {
                $merged[$i] == $local[$i];
            } elseif ($count_ancestor == $count_local) {
                $merged[$i] = $remote[$i];
            } elseif ($count_local == $count_remote) {
                if ($local[$i] == $remote[$i]) {
                    $merged[$i] = $local[$i];
                } else {
                    throw new ConflictException("A conflict has occured");
                }
            }
        }
        return $merged;
    }

    /**
     * Handles removal or modification of lines
     *
     * @param array $ancestor
     * @param array $local
     * @param array $remote
     * @param int $count_ancestor
     * @param int $count_local
     * @param int $count_remote
     *
     * @return array
     * @throws Exception
     * @internal param int $count
     *
     */
    protected function linesRemovedOrModified(
        array $ancestor,
        array $local,
        array $remote,
        $count_ancestor,
        $count_local,
        $count_remote
    ) {
        $merged = [];
        $count_array = [$count_ancestor, $count_local, $count_remote];
        sort($count_array);
        $mincount = min($count_local, $count_ancestor, $count_remote);

        // First for loop compares all 3 nodes and returns updated node.
        for ($key = 0; $key < $mincount; $key++) {
            if ($ancestor[$key] == $local[$key]) {
                $merged[$key] = $remote[$key];
            } elseif ($ancestor[$key] == $remote[$key]
                || $local[$key] == $remote[$key]) {
                $merged[$key] = $local[$key];
            } else {
                throw new ConflictException("A conflict has occured");
            }
        }

        for ($key = $mincount; $key < $count_array[1]; $key++) {
            if ($mincount == $count_local && $ancestor[$key] != $remote[$key]) {
                throw new ConflictException("A whole new conflict arised");
            } elseif ($mincount == $count_remote
                && $ancestor[$key] != $local[$key]) {
                throw new ConflictException("A whole new conflict arised");
            }
        }
        return $merged;
    }

    /**
     * Method to deal with the case where Addition and removal.
     * takes place simuntaneously.
     * Example: 2 lines in ancestor, 3 lines in local.
     * and 1 line in remote.
     *
     * @param array $ancestor
     * @param array $local
     * @param array $remote
     * @param int   $count_ancestor
     * @param int   $count_local
     * @param int   $count_remote
     *
     * @return array
     * @throws Exception
     */
    protected function linesAddedRemovedAndModified(
        array $ancestor,
        array $local,
        array $remote,
        $count_ancestor,
        $count_local,
        $count_remote
    ) {
        $merged = [];
        $count_array = [$count_ancestor, $count_local, $count_remote];
        sort($count_array);
        $mincount = min($count_local, $count_ancestor, $count_remote);
        $maxcount = max($count_local, $count_ancestor, $count_remote);

        // First for loop compares all 3 nodes and returns updated node.
        for ($key = 0; $key < $mincount; $key++) {
            if ($ancestor[$key] == $local[$key]) {
                $merged[$key] = $remote[$key];
            } elseif ($ancestor[$key] == $remote[$key]
                || $local[$key] == $remote[$key]) {
                $merged[$key] = $local[$key];
            } else {
                throw new ConflictException("A conflict has occured");
            }
        }

        // Second for loop compares 2 nodes and if they are identical
        // add the changes to new array otherwise throw conflict exception.
        for ($key = $mincount; $key < $count_array[1]; $key++) {
            if ($count_ancestor == $mincount
                && ($count_remote == $maxcount || $count_local == $maxcount)
            ) {
                if ($local[$key] == $remote[$key]) {
                    $merged[$key] = $local[$key];
                } else {
                    throw new ConflictException("A conflict has occured");
                }
            } elseif ($count_local == $mincount
                && ($count_ancestor == $maxcount
                    || $count_remote == $maxcount)
            ) {
                if ($ancestor[$key] == $remote[$key]) {
                    if (!isset($local[$key])) {
                        unset($merged[$key]);
                    }
                } else {
                    throw new ConflictException("A conflict has occured");
                }
            } elseif ($count_remote == $mincount
                && ($count_ancestor == $maxcount
                    || $count_local == $maxcount)) {
                if ($local[$key] == $ancestor[$key]) {
                    if (!isset($remote[$key])) {
                        unset($merged[$key]);
                    }
                } else {
                    throw new ConflictException("A conflict has occured");
                }
            }
        }

        // Third for loops just adds the newly added lines to new array.
        for ($key = $count_array[1]; $key < $maxcount; $key++) {
            if ($count_remote == $maxcount) {
                $merged[$key] = $remote[$key];
            } elseif ($count_ancestor == $maxcount) {
                $merged[$key] = $ancestor[$key];
            } elseif ($count_local == $maxcount) {
                $merged[$key] = $local[$key];
            }
        }
        return $merged;
    }
}


<?php
/*
 * This file is part of the Invite Wsapi Bundle
 *
 * The bundle provides a mapping to Cisco's IOS UC Gateway Api.
 *
 * (c) Invite Networks Inc. <info@invitenetworks.com>
 *
 * For the full copyright and license information,
 * please view the LICENSE file that was distributed
 * with this source code.
 */
namespace Invite\Component\Cisco\Wsapi\Request;

use Invite\Component\Cisco\Wsapi\Request\WsapiRequest;
use Invite\Component\Cisco\Wsapi\Model\XcdrListenerInterface;

/**
 * INVITE WsApi Xcdr Request.
 *
 * @category   API
 * @author     Josh Whiting <josh@invitenetworks.com>
 * @version    Release: @package_version@
 * @since      Class available since Release 1.1.0
 */
class XcdrRequest extends WsapiRequest
{
    /**
     * Cisco Xcdr api xml schema
     */

    const XCDR_SCHEMA = 'http://www.cisco.com/schema/cisco_xcdr/v1_0';

    /**
     * @var \Invite\Component\Cisco\Wsapi\Model\XcdrListenerInterface
     */
    protected $listener;
    protected $cdrFormat;
    protected $cdrType;
    protected $cdrRecord;

    /**
     * Xcdr Soap Handler construct.
     *
     * @param \Invite\Component\Cisco\Wsapi\Model\XcdrListenerInterface $listener
     */
    public function __construct(XcdrListenerInterface $listener, array$options = array())
    {
        parent::__construct($options);
        $this->listener = $listener;
        $this->schema = self::XCDR_SCHEMA;
    }

    /**
     * Respond to wsapi keepalive probing response.
     */
    public function SolicitXcdrProbing($msgHeader, $sequence, $interval, $failureCount, $registered, $providerStatus)
    {
        $responseXml = $this->probing($msgHeader, $sequence, $interval, $failureCount, $registered, $providerStatus);
        $response = $this->listener->processProbing($this, $responseXml);

        if (!$this->isValid()) return;
        return $response;
    }

    /**
     * Respond to wsapi xcdr unregister response.
     */
    public function SolicitXcdrProviderUnRegister($msgHeader)
    {
        $responseXml = $this->unregister($msgHeader);
        $response = $this->listener->processUnregister($this, $responseXml);

        if (!$this->isValid()) return;
        return $response;
    }

    /**
     * Respond to wsapi xcdr status change message.
     */
    public function NotifyXcdrStatus($msgHeader, $applicationData, $providerData, $providerStatus)
    {
        $responseXml = $this->status($msgHeader, $applicationData, $providerData, $providerStatus);
        $response = $this->listener->processStatus($this, $responseXml);

        if (!$this->isValid()) return;
        return $response;
    }

    /**
     * Parse and save wsapi cdr record.
     */
    public function NotifyXcdrRecord($msgHeader, $format, $type, $cdr)
    {
        $this->msgHeader = $msgHeader;
        $this->registrationID = $msgHeader->registrationID;
        $this->transactionID = $msgHeader->transactionID;
        $this->cdrFormat = $format;
        $this->cdrType = $type;
        $this->cdrRecord = $cdr;

        $response = $this->listener->processRecord($this, null);

        if (!$this->isValid()) return;
        return $response;
    }

    /**
     * @return std Object
     */
    public function getCdrFormat()
    {
        return $this->cdrFormat;
    }

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

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

    /**
     * @return std Object
     */
    public function getCdrProvider()
    {
        return 'xcdr';
    }

}


<?php
/**
 * WordPress_Provider class.
 *
 * @package metis
 */

namespace Metis;

use Pimple\ServiceProviderInterface;
use Pimple\Container as PimpleContainer;

/**
 * Defines the WordPress provider class.
 */
class WordPress_Provider implements ServiceProviderInterface {
	/**
	 * Register a number of WordPress globals in the container.
	 *
	 * @param  PimpleContainer $container The container instance.
	 *
	 * @return void
	 */
	public function register( PimpleContainer $container ) {
		$container['wp'] = $container->factory( function() {
			return isset( $GLOBALS['wp'] ) ? $GLOBALS['wp'] : null;
		} );

		$container['wpdb'] = $container->factory( function() {
			return isset( $GLOBALS['wpdb'] ) ? $GLOBALS['wpdb'] : null;
		} );

		$container['wp_query'] = $container->factory( function() {
			return isset( $GLOBALS['wp_query'] ) ? $GLOBALS['wp_query'] : null;
		} );

		$container['wp_rewrite'] = $container->factory( function() {
			return isset( $GLOBALS['wp_rewrite'] ) ? $GLOBALS['wp_rewrite'] : null;
		} );

		$container['wp_filesystem'] = $container->factory( function() {
			if ( ! function_exists( 'WP_Filesystem' ) ) {
				require_once ABSPATH . '/wp-admin/includes/file.php';
			}

			if ( ! isset( $GLOBALS['wp_filesystem'] ) ) {
				WP_Filesystem();
			}

			return $GLOBALS['wp_filesystem'];
		} );

		$container['wp_object_cache'] = $container->factory( function() {
			if ( ! isset( $GLOBALS['wp_object_cache'] ) && function_exists( 'wp_cache_init' ) ) {
				wp_cache_init();
			}

			return isset( $GLOBALS['wp_object_cache'] ) ? $GLOBALS['wp_object_cache'] : null;
		} );
	}
}


<?php namespace Shamiao\L4mysqlqueue;

use Illuminate\Support\ServiceProvider;

class L4mysqlqueueServiceProvider extends ServiceProvider {

	/**
	 * Indicates if loading of the provider is deferred.
	 *
	 * @var bool
	 */
	protected $defer = false;

	/**
	 * Bootstrap the application events.
	 *
	 * @return void
	 */
	public function boot()
	{
		$this->package('shamiao/l4mysqlqueue');
        $manager = $this->app['queue'];
		$manager->addConnector('mysql', function()
		{
		    return new Queue\Connectors\MysqlConnector;
		});
	}

	/**
	 * Register the service provider.
	 *
	 * @return void
	 */
	public function register()
	{

	}

	/**
	 * Get the services provided by the provider.
	 *
	 * @return array
	 */
	public function provides()
	{
		return array();
	}

}


<?php
namespace Ivoba\Silex;

use Pimple\Container;
use Pimple\ServiceProviderInterface;

class EnvProvider implements ServiceProviderInterface
{

    const CONFIG_KEY_DEFAULT = 'default';
    const CONFIG_KEY_REQUIRED = 'required';
    const CONFIG_KEY_ALLOWED = 'allowed';
    const CONFIG_KEY_CAST = 'typecast';

    const CAST_TYPE_BOOLEAN = 'bool';
    const CAST_TYPE_STRING = 'string';
    const CAST_TYPE_INT = 'int';
    const CAST_TYPE_FLOAT = 'float';

    /*
    'use_dotenv' => function($app){return ($app['env' !== 'prod'])},
    1. run EnvProvider, set all given vars to app
    2. if usedotenv, run dotenv and run envprovider again
    3. apply options, check for required, set default etc
     */

    /**
     * @inheritdoc
     */
    public function register(Container $app)
    {
        $app['env.default_options'] = [
            'prefix' => 'SILEX',
            'use_dotenv' => function () {
                return true;
            },
            'dotenv_dir' => __DIR__.'/../../../..', //vendor/ivoba/dotenv-service-provider/src
            'var_config' => [],
        ];

        $app['env.load'] = function ($app) {
            if (!isset($app['env.options'])) {
                $app['env.options'] = [];
            }
            $app['env.options'] = array_merge($app['env.default_options'], $app['env.options']);

            $this->addEnvVarsToApp($app);
            if ($app['env.options']['use_dotenv']()) {
                \Dotenv::load($app['env.options']['dotenv_dir']);
                //again pls
                $this->addEnvVarsToApp($app);
            }

            $this->applyConfigs($app, $app['env.options']['var_config']);
        };

    }

    /**
     * applies config options to expected vars
     *
     * @param Container $app
     * @param $config
     */
    protected function applyConfigs(Container $app, $config)
    {
        foreach ($config as $varName => $options) {
            if (isset($options[self::CONFIG_KEY_DEFAULT])) {
                if (isset($app[$varName]) === false) {
                    $app[$varName] = $options[self::CONFIG_KEY_DEFAULT];
                }
            }

            if (isset($options[self::CONFIG_KEY_REQUIRED])) {
                if ($options[self::CONFIG_KEY_REQUIRED]) {
                    \Dotenv::required($app['env.options']['prefix'].'_'.strtoupper($varName));
                }
            }

            if (isset($options[self::CONFIG_KEY_ALLOWED])) {
                \Dotenv::required(
                    $app['env.options']['prefix'].'_'.strtoupper($varName),
                    $options[self::CONFIG_KEY_ALLOWED]
                );
            }

            if (isset($options[self::CONFIG_KEY_CAST])) {
                switch ($options[self::CONFIG_KEY_CAST]) {
                    case self::CAST_TYPE_INT:
                        $app[$varName] = (int)$app[$varName];
                        break;
                    case self::CAST_TYPE_FLOAT:
                        $app[$varName] = (float)$app[$varName];
                        break;
                    case self::CAST_TYPE_BOOLEAN:
                        $app[$varName] = filter_var(($app[$varName]), FILTER_VALIDATE_BOOLEAN);
                        break;
                    default: //string
                        break;
                }
            }

        }

    }

    /**
     * collect vars and sets them to the DIC
     *
     * @param Container $app
     */
    protected function addEnvVarsToApp(Container $app)
    {
        $hasPrefix = function ($elem) use ($app) {
            return strpos($elem, $app['env.options']['prefix'].'_') !== false;
        };
        $arrayFilterKeys = function ($input, $callback) {
            if (!is_array($input)) {
                trigger_error(
                    'array_filter_key() expects parameter 1 to be array, '.gettype($input).' given',
                    E_USER_WARNING
                );

                return null;
            }

            if (empty($input)) {
                return $input;
            }

            $filteredKeys = array_filter(array_keys($input), $callback);
            if (empty($filteredKeys)) {
                return array();
            }

            $input = array_intersect_key(array_flip($filteredKeys), $input);

            return $input;
        };

        $envVars = $arrayFilterKeys($_ENV, $hasPrefix);
        $envVars = array_merge($arrayFilterKeys($_SERVER, $hasPrefix), $envVars);
        foreach ($envVars as $envVar => $empty) {
            $var = \Dotenv::findEnvironmentVariable($envVar);
            if ($var) {
                $key = strtolower(str_replace($app['env.options']['prefix'].'_', '', $envVar));
                $app[$key] = $var;
            }
        }
    }

}


<?php namespace Shamiao\L4mysqlqueue\Queue;

use DateTime;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Queue\Queue;
use Illuminate\Queue\QueueInterface;
use ErrorException;

class MysqlQueue extends Queue implements QueueInterface {

    /**
     * Name of queue table.
     *
     * @var string
     */
    protected $table;

    /**
     * The name of queue.
     *
     * @var string
     */
    protected $queue;

    /**
     * Create a new Mysql queue instance.
     *
     * @param  string  $queue_name
     * @return void
     */
    public function __construct($queue = null)
    {
        $this->table = \Illuminate\Support\Facades\
            Config::get('queue.connections.mysql.table', 'queue');

        if ($queue === null) { $queue = 'default'; }
        $this->queue = $queue;
    }

    /**
     * Push a new job onto the queue.
     *
     * @param  string  $job
     * @param  mixed   $data
     * @param  string  $queue
     * @return mixed
     */
    public function push($job, $data = '', $queue = null)
    {
        if ($queue === null) { $queue = $this->queue; }
        return $this->pushRaw($this->createPayload($job, $data), $queue);
    }

    /**
     * Push a raw payload onto the queue.
     *
     * @param  string  $payload
     * @param  string  $queue
     * @param  array   $options
     * @return mixed
     */
    public function pushRaw($payload, $queue = null, array $options = array())
    {
        if ($queue === null) { $queue = $this->queue; }
        $jobId = $this->insertJobRecord($payload, Carbon::now(), $queue);
        return 0;
    }

    /**
     * Push a new job onto the queue after a delay.
     *
     * @param  \DateTime|int  $delay
     * @param  string  $job
     * @param  mixed   $data
     * @param  string  $queue
     * @return mixed
     */
    public function later($delay, $job, $data = '', $queue = null)
    {
        if ($queue === null) { $queue = $this->queue; }
        if ($delay instanceof DateTime) {
            $time = $delay;
        } elseif (is_int($delay)) {
            $time = Carbon::now()->addSeconds($delay);
        } else {
            throw new ErrorException('DateTime or int $delay required. ');
        }
        $jobId = $this->insertJobRecord($this->createPayload($job, $data),
            $time, $queue);
        return 0;
    }

    /**
     * Pop the next job off of the queue.
     *
     * @param  string  $queue
     * @return \Illuminate\Queue\Jobs\Job|null
     */
    public function pop($queue = null) {
        if ($queue === null) { $queue = $this->queue; }
        $query = DB::table($this->table)->where('queue_name', $queue)
            ->where('status', 'pending')
            ->where('fireon', '<', time())
            ->orderBy('fireon', 'asc');
        if ($query->count() == 0) {return null;}
        $record = $query->first();
        return new Jobs\MysqlJob($this->container, $record->ID, $record);
    }

    /**
     * Insert a job record into database.
     *
     * @param  string   $payload Payload string.
     * @param  DateTime $time    Exact firing time of the job.
     * @param  string   $queue   Queue name of the job.
     * @return int               ID of new record inserted.
     */
    private function insertJobRecord($payload, $time, $queue)
    {
        if (!$time instanceof DateTime) {
            throw new ErrorException('An explicit DateTime value $time is required. ');
        }
        $jobId = DB::table($this->table)->insertGetId([
            'queue_name' => $queue,
            'payload'  => $payload,
            'status'   => 'pending',
            'attempts' => 1,
            'fireon'   => $time->getTimestamp(),
        ]);
        return $jobId;
    }
}


<?php
/*
 * This file is part of the Invite Wsapi Library
 *
 * (c) Invite Networks Inc. <info@invitenetworks.com>
 *
 * For the full copyright and license information,
 * please view the LICENSE file that was distributed
 * with this source code.
 */
namespace Invite\Component\Cisco\Wsapi\Client;

use Invite\Component\Cisco\Wsapi\Exception\SoapTimeoutException;
use Invite\Component\Cisco\Wsapi\Client\WsApiClient;
use Invite\Component\Cisco\Wsapi\Request\XcdrRequest;

/**
 * INVITE Cisco WsApi XCDR Client
 *
 * @category   CDR
 * @author     Josh Whiting <josh@invitenetworks.com>
 * @version    Release: @package_version@
 * @since      Class available since Release 1.1.0
 */
class XcdrClient
{

    /**
     * @var \Invite\Component\Cisco\Wsapi\Soap\Client\WsApiSoapClient
     */
    protected $soapClient;

    /**
     * Cisco IOS XCDR Provider Registration
     */
    public function requestXcdrRegister($host, $appUrl, array$options = array())
    {
        $protocol = array_key_exists('protocol', $options) ? $options['protocol'] : 'http';
        $url = $protocol . '://' . $host . ':8090/cisco_xcdr';
        $schema = XcdrRequest::XCDR_SCHEMA;
        $appName = array_key_exists('appName', $options) ? $options['appName'] : 'invite_xcdr';
        $transactionID = array_key_exists('transactionID', $options) ? $options['transactionID'] : uniqid('xcdr');

        $socket = array_key_exists('socket', $options) ? $options['socket'] : 25;
        ini_set('default_socket_timeout', $socket);

        $connection = array_key_exists('connection', $options) ? $options['connection'] : 25;
        $trace = array_key_exists('trace', $options) ? $options['trace'] : false;
        $exception = array_key_exists('exception', $options) ? $options['exception'] : false;

        $this->soapClient = new WsApiClient(null, array(
            "location" => $url,
            "uri" => $schema,
            "soap_version" => SOAP_1_2,
            "connection_timeout" => $connection,
            "trace" => $trace,
            "exception" => $exception
                ), $schema // Used to send API namespace to SOAP Client
        );

        $soapObjectXML = '<applicationData>
                                <name>' . $appName . '</name>
                                <url>' . $appUrl . '</url>
                            </applicationData>
                            <msgHeader>
                                <transactionID>' . $transactionID . '</transactionID>
                            </msgHeader>
                            <providerData>
                                <url>' . $url . '</url>
                            </providerData>'
        ;

        $soapXML = new \SoapVar($soapObjectXML, XSD_ANYXML, null, null, null, $schema);

        try {
            $result = $this->soapClient->RequestXcdrRegister($soapXML);
        } catch (SoapTimeoutException $e) {
            return array(
                'status' => 'error',
                'type' => 'soap_fault',
                'message' => 'XCDR Soap Client Timeout. ' . $e->getMessage(),
                'class' => get_class($this)
            );
        } catch (\Exception $e) {
            return array(
                'status' => 'error',
                'type' => 'exception',
                'message' => 'XCDR Soap Client Exception. ' . $e->getMessage(),
                'class' => get_class($this)
            );
        }

        if (is_soap_fault($result)) {
            return array(
                'status' => 'error',
                'type' => 'soap_fault',
                'code' => $result->faultcode,
                'message' => $result->faultstring,
                'class' => get_class($this)
            );
        }

        $cdrFormat = array_key_exists('cdr_format', $options) ? $options['cdr_format'] : 'compact';

        if ($cdrFormat === 'detailed') {
            $cdrResult = $this->requestXcdrSetAttribute($result, $schema);
            if ($cdrResult['status'] === 'error') {
                return $cdrResult;
            }
        }

        $result['app.name'] = $appName;
        $result['app.url'] = $appUrl;
        $result['schema'] = $schema;
        $result['provider.url'] = $url;

        return array(
            'status' => 'success',
            'message' => $host . ' registered successfully!',
            'result' => $result
        );
    }

    /**
     * Cisco IOS XCDR Provider Registration
     */
    public function requestXcdrUnRegister($host, $registrationID, $transactionID, array$options = array())
    {
        $protocol = array_key_exists('protocol', $options) ? $options['protocol'] : 'http';
        $url = $protocol . '://' . $host . ':8090/cisco_xcdr';
        $schema = XcdrHandler::XCDR_SCHEMA;

        $socket = array_key_exists('socket', $options) ? $options['socket'] : 25;
        ini_set('default_socket_timeout', $socket);

        $connection = array_key_exists('connection', $options) ? $options['connection'] : 25;
        $trace = array_key_exists('trace', $options) ? $options['trace'] : false;
        $exception = array_key_exists('exception', $options) ? $options['exception'] : false;

        $this->soapClient = new WsApiClient(null, array(
            "location" => $url,
            "uri" => $schema,
            "soap_version" => SOAP_1_2,
            "connection_timeout" => $connection,
            "trace" => $trace,
            "exception" => $exception
                ), $schema // Used to send API namespace to SOAP Client
        );

        $soapObjectXML = '<msgHeader>
                            <transactionID>' . $transactionID . '</transactionID>
                            <registrationID>' . $registrationID . '</registrationID>
                          </msgHeader>'
        ;

        $soapXML = new \SoapVar($soapObjectXML, XSD_ANYXML, null, null, null, $schema);

        try {
            $result = $this->soapClient->RequestXcdrUnRegister($soapXML);
        } catch (SoapTimeoutException $e) {
            return array(
                'status' => 'error',
                'type' => 'soap_fault',
                'message' => 'XCDR Soap Client Timeout. ' . $e->getMessage(),
                'class' => get_class($this)
            );
        } catch (\Exception $e) {
            return array(
                'status' => 'error',
                'type' => 'exception',
                'message' => 'XCDR Soap Client Exception. ' . $e->getMessage(),
                'class' => get_class($this)
            );
        }

        if (is_soap_fault($result)) {
            return array(
                'status' => 'error',
                'type' => 'soap_fault',
                'code' => $result->faultcode,
                'message' => $result->faultstring,
                'class' => get_class($this)
            );
        }

        return array(
            'status' => 'success',
            'message' => $host . ' unregistered successfully!',
            'result' => $result
        );
    }

    /**
     * Cisco IOS XCDRProvider Set Attribute Request
     */
    private function requestXcdrSetAttribute($result, $schema)
    {
        $msgHeader = $result['msgHeader'];

        $soapObjectXML = '<format>DETAIL</format>
                        <msgHeader>
				<transactionID>' . $msgHeader->transactionID . '</transactionID>
                                <registrationID>' . $msgHeader->registrationID . '</registrationID>
			</msgHeader>'
        ;

        $soapXML = new \SoapVar($soapObjectXML, XSD_ANYXML, null, null, null, $schema);

        try {
            $result = $this->soapClient->RequestXcdrSetAttribute($soapXML);
        } catch (SoapTimeoutException $e) {
            return array(
                'status' => 'error',
                'type' => 'soap_fault',
                'message' => 'XCDR Soap Client Timeout. ' . $e->getMessage(),
                'class' => get_class($this)
            );
        } catch (\Exception $e) {
            return array(
                'status' => 'error',
                'type' => 'exception',
                'message' => 'XCDR Soap Client Exception. ' . $e->getMessage(),
                'class' => get_class($this)
            );
        }

        if (is_soap_fault($result)) {
            return array(
                'status' => 'error',
                'type' => 'soap_fault',
                'code' => $result->faultcode,
                'message' => $result->faultstring,
                'class' => get_class($this)
            );
        }

        return array(
            'status' => 'success',
            'result' => $result
        );
    }

}


<?php namespace Potter\Utils\Form\Traits;

use HtmlObject\Element;

trait Field
{
    /**
     * @var string
     */
    protected $label;

    /**
     * @var string
     */
    protected $container = 'p';

    /**
     * @var bool
     */
    public $inputCheckable = false;

    /**
     * @param array $attributes
     *
     * @return $this
     */
    public function replaceAttributes($attributes)
    {
        if (isset($attributes['label'])):
            $this->label = $attributes['label'];
            unset($attributes['label']);
        else:
            $this->label = $this->name;
        endif;

        $this->attributes = (array)$attributes;

        return $this;
    }

    /**
     * @param $value
     *
     * @return $this
     */
    public function setLabel($value)
    {
        $this->label = $value;

        return $this;
    }

    /**
     * @param $value
     *
     * @return $this
     */
    public function setContainer($value)
    {
        $this->container = $value;

        return $this;
    }

    /**
     * @return string
     */
    public function render()
    {
        $label = Element::label($this->label)->for($this->id);

        if ($this->inputCheckable):
            $p = Element::create($this->container)->nest(
                [
                    'field' => parent::render(),
                    'label' => $label,
                    'close' => '<br>'
                ]
            );

        else:
            $p = Element::create($this->container)->nest(
                [
                    'label' => $label,
                    'field' => parent::render()
                ]
            );

        endif;

        return $p->render();
    }
}


<?php

namespace Potter\Post;

use Illuminate\Support\Str;
use Potter\Utils\Metabox;

abstract class Type
{
    /**
     * @var string
     */
    protected $type;
    /**
     * @var array
     */
    protected $args = array();
    /**
     * @var bool
     */
    protected $autoRegister = true;
    /**
     * @var array
     */
    protected $taxonomies = array();
    /**
     * @var array
     */
    protected $labels = array();
    /**
     * @var string
     */
    protected $singular;
    /**
     * @var string
     */
    protected $plural;
    /**
     * @var array
     */
    protected $capabilities = array();
    /**
     * @var array
     */
    protected $supports = array('title', 'editor', 'thumbnail', 'revisions', 'excerpt', 'page-attributes');
    /**
     * @see https://developer.wordpress.org/resource/dashicons/
     * @var string
     */
    protected $icon = 'dashicons-admin-post';
    /**
     * @var string
     */
    protected $capability_type = 'page';
    /**
     * @var boolean
     */
    protected $public = true;
    /**
     * @var boolean
     */
    protected $show_ui = true;
    /**
     * @var bool
     */
    protected $has_archive = true;
    /**
     * @var int
     */
    protected $menu_position = 5;
    /**
     * @var string
     */
    protected $description;
    /**
     * @var string
     */
    protected $route;
    /**
     * @var array
     */
    protected $queryArgs = array();
    /**
     * @var bool
     */
    protected $hierarchical = false;
    /**
     * @var array
     */
    protected $meta_boxes = array();

    public function __construct()
    {
        $this->setSingular();
        $this->setPlural();

        if (!empty($this->meta_boxes)) $this->parseMetaboxes();

        if ($this->autoRegister) add_action('init', array($this, '_register'));
    }

    /**
     * @param string $singular
     *
     * @return $this
     */
    public function setSingular($singular = null)
    {
        if (!empty($singular)) $this->singular = $singular;

        if (empty($this->singular)) $this->singular = Str::title($this->getPostType());

        return $this;
    }

    /**
     * @param string $plural
     *
     * @return $this
     */
    public function setPlural($plural = null)
    {
        if (!empty($plural)) $this->plural = $plural;

        if (empty($this->plural)) $this->plural = Str::plural($this->singular);

        return $this;
    }

    /**
     * @return string
     */
    public function getPostType()
    {
        if (empty($this->type)):
            $class      = get_class($this);
            $this->type = str_replace('Model', '', $class);
            $this->type = str_replace('Type', '', $this->type);
            $this->type = Str::snake($this->type);
        endif;

        return $this->type;
    }

    /**
     * @return array
     */
    protected function parseMetaboxes()
    {
        $default = array(
            'title'    => __('Data'),
            'pages'    => array($this->getPostType()),
            'context'  => 'normal',
            'priority' => 'high',
            'fields'   => array()
        );

        foreach ($this->meta_boxes as $key => $mbox):
            $default['id'] = $key;
            $attributes    = wp_parse_args($mbox, $default);

            new Metabox($attributes);

        endforeach;
    }

    /**
     * @param array $customArgs
     *
     * @return array
     */
    protected function getArgs($customArgs = [])
    {
        $args = [
            'label'         => $this->plural,
            'description'   => $this->description,
            'labels'        => $this->getLabels(),
            'supports'      => $this->supports,
            'taxonomies'    => $this->taxonomies,
            'hierarchical'  => $this->hierarchical,
            'public'        => $this->public,
            'show_ui'       => $this->show_ui,
            'menu_position' => $this->menu_position,
            'has_archive'   => $this->has_archive,
            'menu_icon'     => $this->icon ? $this->icon : false,
        ];

        if (!empty($this->route)):
            $args['rewrite'] = array('slug' => $this->route, 'with_front' => true);
        endif;

        $args = wp_parse_args($args, $customArgs);

        return wp_parse_args($this->args, $args);
    }

    /**
     * @return array
     */
    private function getLabels()
    {
        return wp_parse_args(
            $this->labels,
            array(
                'name'               => __($this->plural),
                'singular_name'      => __($this->singular),
                'menu_name'          => __($this->plural),
                'parent_item_colon'  => __('Parent Item:'),
                'all_items'          => __($this->plural),
                'view_item'          => __('View') . ' ' . __($this->singular),
                'add_new_item'       => __('Add') . ' ' . __($this->singular),
                'add_new'            => __('Add') . ' ' . __($this->singular),
                'edit_item'          => __('Edit') . ' ' . __($this->singular),
                'update_item'        => __('Update') . ' ' . __($this->singular),
                'search_items'       => __('Search') . ' ' . __($this->singular),
                'not_found'          => __('Not found'),
                'not_found_in_trash' => __('Not found in Trash'),
            )
        );
    }

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

    /**
     * Extra commands to be executed before registration.
     */
    protected function beforeRegister()
    {
        // Do what you want.
    }

    /**
     * Register
     */
    public function _register()
    {
        $this->beforeRegister();

        $args = $this->getArgs();

        register_post_type($this->type, $args);
    }
}


<?php
namespace Zf2FileUploader\Filter\Thumbnail;

use Zend\Filter\Exception;
use Zend\Filter\FilterInterface;

class PathFilter implements FilterInterface
{
    /**
     * @var int
     */
    protected $width;

    /**
     * @var int
     */
    protected $height;

    /**
     * @param int $width
     * @param int $height
     */
    public function __construct($width, $height)
    {
        $this->width = $width;
        $this->height = $height;
    }

    /**
     * Returns the result of filtering $value
     *
     * @param  mixed $value It is must be path to file on FS
     * @throws Exception\RuntimeException If filtering $value is impossible
     * @return mixed
     */
    public function filter($value)
    {
        $pathInfo = pathinfo($value);
        return sprintf('%s/%s_%sx%s.%s', $pathInfo['dirname'], $pathInfo['filename'],
                                         $this->width, $this->height, $pathInfo['extension']);
    }
}


<?php
namespace elnebuloso\Flex\Converter;

/**
 * Class StringToCamelCase
 *
 * @author Jeff Tunessen <jeff.tunessen@gmail.com>
 */
class StringToCamelCase
{
    /**
     * convert string to camelcase
     *
     * @param string $string
     * @param string $delimiter
     * @return string
     */
    public function convert($string, $delimiter = '_')
    {
        $func = create_function('$c', 'return strtoupper($c[1]);');

        return preg_replace_callback('/[\s]+(.)/', $func, str_replace($delimiter, ' ', $string));
    }
}


<?php namespace Potter\Utils\Form;

use Illuminate\Support\Collection;

class Widget
{
    protected static $fieldsInput    = ['url', 'password', 'text', 'tel', 'number', 'date'];
    protected static $fieldsTextarea = ['textarea'];
    protected static $fieldsSelect   = ['select', 'multi-select'];
    protected static $fieldsCheckbox = ['checkbox'];
    protected static $fieldsRadio    = ['radio'];

    /**
     * @var Collection
     */
    protected $fields;

    /**
     * @var \Potter\Utils\Widget
     */
    protected $widget;

    /**
     * @var Collection
     */
    protected $values;

    public function __construct(&$widget, $fields, $values)
    {
        $this->widget = $widget;
        $this->fields = new Collection();
        $this->values = new Collection($values);

        $this->parseFields($fields);

    }

    /**
     * @param $fields
     *
     * @return $this
     */
    public function parseFields($fields)
    {
        foreach ($fields as $id => $options):
            $field = $this->makeField($id, $options);
            $this->fields->put($id, $field);
        endforeach;

        return $this;
    }

    /**
     * @param $id
     * @param $options
     *
     * @return $this
     */
    public function addField($id, $options)
    {
        $field = $this->makeField($id, $options);
        $this->fields->put($id, $field);

        return $this;
    }

    /**
     * @param $id
     * @param $options
     *
     * @return \HtmlObject\Traits\Tag
     */
    protected function makeField($id, $options)
    {
        $options = wp_parse_args(
            $options, array(
                'label' => $id,
                'type'  => 'text',
                'id'    => $id,
                'name'  => $id,
                'value' => null,
                'class' => 'widefat'
            )
        );

        $options['name'] = $this->widget->get_field_name($options['name']);
        $options['id']   = $this->widget->get_field_id($options['id']);

        $type = $options['type'];

        $value = $this->values->get($id, $options['value']);

        if (in_array($type, self::$fieldsInput)):
            $field = new Fields\Input($type, $options['name'], $value, $options);
        elseif (in_array($type, self::$fieldsTextarea)):
            $field = new Fields\Textarea($type, $options['name'], $value, $options);
        elseif (in_array($type, self::$fieldsSelect)):
            $field = new Fields\Select($type, $options['name'], $value, $options);
        elseif (in_array($type, self::$fieldsCheckbox)):
            $field = new Fields\Checkable($type, $options['name'], $value, $options);
        elseif (in_array($type, self::$fieldsRadio)):
            $field = new Fields\Radio($type, $options['name'], $value, $options);
        else:
            $field = new Fields\Input($type, $options['name'], $value, $options);
        endif;

        return $field;
    }

    /**
     * @return string
     */
    public function render()
    {
        $html = [];
        foreach ($this->fields as $field):
            $html[] = $field->render();
        endforeach;

        return implode("\n", $html);
    }

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


<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 * http://www.yiiframework.com/doc-2.0/yii-jui-datepicker.html
 */
/**
 * Copyright (c) 2012 Paul Bakaus, http://jqueryui.com/
 */
/**
/*! jQuery Timepicker Addon not yet - v1.6.3 - 2016-04-20
* http://trentrichardson.com/examples/timepicker
* Copyright (c) 2016 Trent Richardson; Licensed MIT */
/**
 * @copyright Copyright © Wattanapong Suttapak, 2017
 * @version 1.0.0
 */

namespace wattanapong\datetime;

use Yii;
use yii\base\InvalidParamException;
use yii\helpers\FormatConverter;
use yii\helpers\Html;
use yii\helpers\Json;
use yii\jui\InputWidget;
use yii\jui\JuiAsset;
use yii\jui\DatePickerLanguageAsset;
use common\components\Util;

/**
 * DateTimePicker widget is a Yii2 wrapper for the Bootstrap DateTimePicker plugin by smalot
 * This is a fork of the DatePicker plugin by @eternicode and adds the time functionality.
 *
 * @author Kartik Visweswaran <kartikv2@gmail.com>
 * @since 1.0
 * @see http://www.malot.fr/bootstrap-datetimepicker/
 */
class DateTimePicker extends InputWidget
{
    /**
     * @var string the locale ID (e.g. 'fr', 'de', 'en-GB') for the language to be used by the date picker.
     * If this property is empty, then the current application language will be used.
     *
     * Since version 2.0.2 a fallback is used if the application language includes a locale part (e.g. `de-DE`) and the language
     * file does not exist, it will fall back to using `de`.
     */
    public $language;
    /**
     * @var boolean If true, shows the widget as an inline calendar and the input as a hidden field.
     */
    public $inline = false;
    /**
     * @var array the HTML attributes for the container tag. This is only used when [[inline]] is true.
     * @see \yii\helpers\Html::renderTagAttributes() for details on how attributes are being rendered.
     */
    public $containerOptions;
    /**
     * @var string the format string to be used for formatting the date value. This option will be used
     * to populate the [[clientOptions|clientOption]] `dateFormat`.
     * The value can be one of "short", "medium", "long", or "full", which represents a preset format of different lengths.
     *
     * It can also be a custom format as specified in the [ICU manual](http://userguide.icu-project.org/formatparse/datetime#TOC-Date-Time-Format-Syntax).
     * Alternatively this can be a string prefixed with `php:` representing a format that can be recognized by the
     * PHP [date()](http://php.net/manual/de/function.date.php)-function.
     *
     * For example:
     *
     * ```php
     * 'MM/dd/yyyy' // date in ICU format
     * 'php:m/d/Y' // the same date in PHP format
     * ```
     *
     * If not set the default value will be taken from `Yii::$app->formatter->dateFormat`.
     */
    public $dateFormat;
    /**
     * @var string the model attribute that this widget is associated with.
     * The value of the attribute will be converted using [[\yii\i18n\Formatter::asDate()|`Yii::$app->formatter->asDate()`]]
     * with the [[dateFormat]] if it is not null.
     */
    public $attribute;
    public $from,$to;
    public $valueTo;
    private $isRange = false;
    public $separate = ' ถึง ';
    /**
     * @var string the input value.
     * This value will be converted using [[\yii\i18n\Formatter::asDate()|`Yii::$app->formatter->asDate()`]]
     * with the [[dateFormat]] if it is not null.
     */
    public $value;

    /**
     *
     * @var theme for jquery ui theme base on vendor\bower\jquery-ui\themes\
     */
    public $theme;

    /*
     * @array for plugin jquery datepicker
     */

    public $pluginOptions;

    public $isDateTime = true;
    /**
     * @inheritdoc
     */
    public function init()
    {
        parent::init();

        if ($this->inline && !isset($this->containerOptions['id'])) {
            $this->containerOptions['id'] = $this->options['id'] . '-container';
        }
        if ($this->dateFormat === null) {
            $this->dateFormat = Yii::$app->formatter->dateFormat;
        }

        //check is from to attribute
        $isFrom = $isTo = false ;
        $this->isRange = true;
        if ($this->from !== null && $this->from !== ''  ) $isFrom = true;
        if ($this->to !== null && $this->to !== ''  ) $isTo = true;

        if ( $isFrom && !$isTo ) $this->to = $this->from;
        elseif ( !$isFrom && $isTo ) $this->from = $this->to;
        elseif ( !$isFrom && !$isTo )  $this->isRange = false;

        //config maxDate
        if ( isset($this->pluginOptions['maxDate'] ) && $this->pluginOptions['maxDate'] !== null
        		&& $this->pluginOptions['maxDate'] !== ''  ){
        	$this->pluginOptions['maxDate'] = $this->getMaxMin($this->pluginOptions['maxDate']);
        }

        //config minDate
        if ( isset($this->pluginOptions['minDate'] ) && $this->pluginOptions['minDate'] !== null
        		&& $this->pluginOptions['minDate'] !== ''  ){
        	$this->pluginOptions['minDate'] = $this->getMaxMin($this->pluginOptions['minDate'],false);
        }

        //config maxDate
        if ( isset($this->pluginOptions['maxDateTo'] ) && $this->pluginOptions['maxDateTo'] !== null
        		&& $this->pluginOptions['maxDateTo'] !== ''  ){
        			$this->pluginOptions['maxDateTo'] = $this->getMaxMin($this->pluginOptions['maxDateTo']);
        }

        //config minDate
        if ( isset($this->pluginOptions['minDateTo'] ) && $this->pluginOptions['minDateTo'] !== null
        		&& $this->pluginOptions['minDateTo'] !== ''  ){
        			$this->pluginOptions['minDateTo'] = $this->getMaxMin($this->pluginOptions['minDateTo'],false);
        }

        //get Theme
        $this->theme = isset($this->pluginOptions['theme'])?$this->pluginOptions['theme']:"base";

        //merge pluginOptions to clientOptions
       $this->clientOptions = array_merge($this->clientOptions,$this->pluginOptions);
    }

    /**
     * Renders the widget.
     */
    public function run()
    {
        echo ($this->isRange?$this->renderWidgetDateRange():$this->renderWidget()) . "\n";

        $containerID = $this->inline ? $this->containerOptions['id'] : $this->options['id'];
        $language = $this->language ? $this->language : Yii::$app->language;
        $language = strtolower( substr($language, 0,2));

        if (strncmp($this->dateFormat, 'php:', 4) === 0) {
            $this->clientOptions['dateFormat'] = FormatConverter::convertDatePhpToJui(substr($this->dateFormat, 4));
        } else {
            $this->clientOptions['dateFormat'] = FormatConverter::convertDateIcuToJui($this->dateFormat, 'date', $language);
        }

        if ($language !== 'en-US' && $language !== 'en' && $language !== 'EN' ) {
            $view = $this->getView();
            //$assetBundle = DatePickerLanguageAsset::register($view);
            $assetBundle = DateTimePickerAsset::register($view);
           	$assetBundle->language = $language;
            $options = Json::htmlEncode($this->clientOptions);
            $language = Html::encode($language);

            $picker = "date".($this->isDateTime?"time":"")."picker";

            	if (!$this->isRange){
            		$script = "$('#{$containerID}').{$picker}($.extend({}, $.datepicker.regional['{$language}'], $options));";

            	}else {
            		$script = "$('#{$this->from}').{$picker}($.extend({}, $.datepicker.regional['{$language}'], $options));";
            		//$script .= ".on( 'change', function() { $('#{$this->to}').{$picker}( 'option', 'minDate', getDate( this ) );}),";

            		//parsing maxDateTo and minDateTo to clientOptions afterward jsonencode to $options
            		//Util::viewArr( $this->clientOptions);
            		$this->clientOptions['maxDate'] = isset($this->clientOptions['maxDateTo'])?$this->clientOptions['maxDateTo']:'' ;
            		$this->clientOptions['minDate'] =  isset($this->clientOptions['minDateTo'])? $this->clientOptions['minDateTo']:'';
            		$options = Json::htmlEncode($this->clientOptions);

            		$script .= "$('#{$this->to}').{$picker}($.extend({}, $.datepicker.regional['{$language}'], $options));";
            		//$script .= ".on( 'change', function() { $('#{$this->from}').{$picker}( $.extend({}, $.datepicker.regional['{$language}'], $options) );});";

            		$script .= "
            				function getDate( element ) {
						      var date;
						      try {
						        date = $.datepicker.parseDate( dateFormat, element.value );
						      } catch( error ) {
						        date = null;
						      }

						      return date;
						    }";
            	}

            $view->registerJs($script);
            	$bundle = $this->getView()->assetManager->getBundle('wattanapong\datetime\DateTimePickerAsset' );
            	$bundle->js[] = ['js/locales/jquery.ui.datepicker-'.$language.'.js'];

            	if ($language == 'th')
            		$bundle->js[] = ['js/locales/jquery.ui.datetimepicker-'.$language.'.js'];
        } else {
            $this->registerClientOptions('datetimepicker', $containerID);
        }

        $this->registerClientEvents('datetimepicker', $containerID);

        $bundle = $this->getView()->assetManager->getBundle('yii\jui\JuiAsset' );
        $bundle->css = [
        						'themes/'.$this->theme.'/jquery-ui.css',
        ];
    }

    /**
     * Renders the DatePicker widget.
     * @return string the rendering result.
     */
    protected function renderWidget()
    {
        $contents = [];

        // get formatted date value
        $value = $this->value;
        if ( ($value == null || $value == '' )  && $this->hasModel() ) {
        		$value = Html::getAttributeValue($this->model, $this->attribute);
        }

        if ($value !== null && $value !== '') {
            // format value according to dateFormat
            try {
                $value = Yii::$app->formatter->asDate($value, $this->dateFormat);
            } catch(InvalidParamException $e) {
                // ignore exception and keep original value if it is not a valid date
            }
        }
        $options = $this->options;
        $options['value'] = $value;

        if ($this->inline === false) {
            // render a text input
            if ($this->hasModel()) {
                $contents[] = Html::activeTextInput($this->model, $this->attribute, $options);
            } else {
                $contents[] = Html::textInput($this->name, $value, $options);
            }
        } else {
            // render an inline date picker with hidden input
            if ($this->hasModel()) {
                $contents[] = Html::activeHiddenInput($this->model, $this->attribute, $options);
            } else {
                $contents[] = Html::hiddenInput($this->name, $value, $options);
            }
            $this->clientOptions['defaultDate'] = $value;
            $this->clientOptions['altField'] = '#' . $this->options['id'];
            $contents[] = Html::tag('div', null, $this->containerOptions);
        }

        return implode("\n", $contents);
    }

    /**
     * Renders the DatePicker widget in DateRange Mode.
     * @return string the rendering result.
     */
    protected function renderWidgetDateRange()
    {
    	$contents = [];
    	$content2s = [];

    	$value = $this->value;
    	$valueTo= $this->valueTo;

    	//send value to hasModel() in InputWidget
    	$this->attribute = $this->from;

    	// get formatted date value
    	if ( ($value == null || $value == '' )  && $this->hasModel() ) {
    		$value = Html::getAttributeValue($this->model, $this->from);
    	}

    	if ( ($valueTo == null || $valueTo == '' )  && $this->hasModel() ) {
    		$valueTo = Html::getAttributeValue($this->model, $this->to);
    	}

    	if ($value !== null && $value !== '') {
    		// format value according to dateFormat
    		try {
    			$value = Yii::$app->formatter->asDate($value, $this->dateFormat);
    		} catch(InvalidParamException $e) {
    			// ignore exception and keep original value if it is not a valid date
    		}
    	}

    	if ($valueTo !== null && $valueTo !== '') {
    		// format value according to dateFormat
    		try {
    			$valueTo = Yii::$app->formatter->asDate($valueTo, $this->dateFormat);
    		} catch(InvalidParamException $e) {
    			// ignore exception and keep original value if it is not a valid date
    		}
    	}

    	$options = $this->options;
    	$options['value'] = $value;

    	if ($this->inline === false) {
    		// render a text input
    		if ($this->hasModel()) {
    			$options['id'] = $this->from;
    			$contents[] = Html::activeTextInput($this->model, $this->from, $options);

    			$options['id'] = $this->to;
    			$options['value'] = $valueTo;
    			$content2s[] = Html::activeTextInput($this->model, $this->to, $options);
    		} else {
    			$options['id'] = $this->from;
    			$contents[] = Html::textInput($this->from, $value, $options);

    			$options['value'] = $valueTo;
    			$options['id'] = $this->to;
    			$content2s[] = Html::textInput($this->to, $valueTo, $options);
    		}
    	} else {
    		// render an inline date picker with hidden input
    		if ($this->hasModel()) {
    			$contents[] = Html::activeHiddenInput($this->model, $this->from, $options);
    			$options['value'] = $valueTo;
    			$content2s[] = Html::activeHiddenInput($this->model, $this->to, $options);
    		} else {
    			$contents[] = Html::hiddenInput($this->from, $value, $options);
    			$options['value'] = $valueTo;
    			$content2s[] = Html::hiddenInput($this->to, $valueTo, $options);
    		}
    		$this->clientOptions['defaultDate'] = $value;
    		$this->clientOptions['altField'] = '#' . $this->from;
    		$contents[] = Html::tag('div', null, $this->containerOptions);

    		$this->clientOptions['defaultDate'] = $valueTo;
    		$this->clientOptions['altField'] = '#' . $this->to;
    		$content2s[] = Html::tag('div', null, $this->containerOptions);
    	}

    	return '

'.
    	implode("\n", $contents).
    	'
 '.$this->separate.'
'.
    	implode("\n", $content2s).
    	'

';
    }

    private function getMaxMin($datetime,$isMax=true){
    	$start = new \DateTime('now');// (new \DateTime())->format('d M Y');
    	$end = new \DateTime($datetime);

    	if ($isMax)
    		$end->add(new \DateInterval('P1D'));

    	$interval = $start->diff($end);
    	return $interval->format('%R%yY %R%mM %R%dD');
    }
}


<?php

namespace Simples\Model;

use function array_merge;
use Exception;
use Simples\Data\Collection;
use Simples\Data\Error\SimplesRecordReadonlyError;
use Simples\Data\Error\SimplesResourceError;
use Simples\Data\Error\SimplesValidationError;
use Simples\Data\Record;
use Simples\Error\SimplesRunTimeError;
use Simples\Model\Error\SimplesActionError;
use Simples\Model\Error\SimplesHookError;
use Simples\Persistence\Field;
use Simples\Persistence\Filter;
use function is_array;

/**
 * Class DataMapper
 * @package Simples\Model
 */
abstract class DataMapper extends ModelAbstract
{
    /**
     * DataMapper constructor
     */
    public function __construct()
    {
        parent::__construct();

        $this->construct();
    }

    /**
     *  Model constructor
     * @return void
     */
    abstract public function construct();

    /**
     * Method with the responsibility of create a record of model
     * @param array|Record $record (null)
     * @param string $alias ('create')
     * @return Record
     * @throws SimplesHookError
     * @throws SimplesRecordReadonlyError
     * @throws SimplesRunTimeError
     */
    final public function create($record = null, string $alias = null): Record
    {
        $record = Record::parse($record);

        foreach ($this->getParents() as $relationship => $parent) {
            /** @var DataMapper $parent */
            $create = $parent->create($record);
            $record->set($relationship, $create->get($parent->getPrimaryKey()));
            $record->import($create->all());
        }

        $action = coalesce($alias, Action::CREATE);

        if (!$this->before($action, $record)) {
            throw new SimplesHookError(get_class($this), $action, 'before');
        }
        if (!$record->get($this->hashKey)) {
            $record->set($this->hashKey, $this->hashKey());
        }

        $create = $this->configureRecord(Action::CREATE, $record);
        $fields = $create->keys();
        $values = $create->values();

        foreach ($this->createKeys as $type => $timestampsKey) {
            $fields[] = $timestampsKey;
            $values[] = $this->getTimestampValue($type);
        }

        $created = $this
            ->source($this->getCollection())
            ->fields($fields)
            ->register($values);

        $this->reset();

        if ($this->getPrimaryKey()) {
            $record->set($this->getPrimaryKey(), $created);
        }
        $record->merge($create->all());

        if (!$this->after($action, $record)) {
            throw new SimplesHookError(get_class($this), $action, 'after');
        }
        return $record;
    }

    /**
     * Read records with the filters informed
     * @param array|Record $record (null)
     * @param string $alias ('read')
     * @param bool $trash (false)
     * @param bool $clean (false)
     * @return Collection
     * @throws SimplesHookError
     * @throws SimplesRunTimeError
     * @throws Exception
     */
    final public function read($record = null, string $alias = null, $trash = false, $clean = false): Collection
    {
        $record = Record::parse(coalesce($record, []));

        $action = coalesce($alias, Action::READ);

        if (!$this->before($action, $record)) {
            throw new SimplesHookError(get_class($this), $action, 'before');
        }

        $filters = [];
        $values = [];
        if (!$record->isEmpty()) {
            $filters = $this->parseFilterFields($record->all());
            $values = $this->parseFilterValues($filters);
        }

        if ($this->destroyKeys) {
            $filters[] = $this->getDestroyFilter($this->destroyKeys['at'], $trash);
        }

        $fields = $this->getActionFields(Action::READ, false);
        if ($clean) {
            $fields = $this->clear($fields);
        }

        $order = is_array($this->order) ? $this->order : [$this->order];

        $where = off($this->getClauses(), 'where', []);
        if ($where) {
            $filters = array_merge($filters, $where);
            $values = array_merge($values, off($this->getClauses(), 'values', []));
        }

        $array = $this
            ->source($this->getCollection())
            ->relation($this->parseReadRelations($this->fields))
            ->fields($fields)
            ->order($order)
            ->where($filters)// TODO: needs review
            ->recover($values);

        $this->reset();

        $after = $this->after($action, $record, $array);
        if (!is_array($after)) {
            throw new SimplesHookError(get_class($this), $action, 'after');
        }
        $array = $after;

        return Collection::make($array);
    }

    /**
     * Update the record given
     * @param array|Record $record (null)
     * @param string $alias ('update')
     * @param bool $trash (false)
     * @return Record
     * @throws SimplesActionError
     * @throws SimplesHookError
     * @throws SimplesResourceError
     * @throws SimplesRunTimeError
     */
    final public function update($record = null, string $alias = null, bool $trash = false): Record
    {
        $record = Record::parse($record);

        foreach ($this->getParents() as $parent) {
            /** @var DataMapper $parent */
            $record->import($parent->update($record)->all());
        }

        $action = coalesce($alias, Action::UPDATE);

        $previous = $this->previous($record, $this->hashKey, $trash);

        if ($previous->isEmpty()) {
            throw new SimplesResourceError([$this->getHashKey() => $record->get($this->getHashKey())]);
        }

        if (!$this->before($action, $record, $previous)) {
            throw new SimplesHookError(get_class($this), $action, 'before');
        }

        $record->setPrivate($this->getHashKey());

        $update = $this->configureRecord(Action::UPDATE, $record, $previous, !$trash);
        $fields = $update->keys();
        $values = $update->values();

        foreach ($this->updateKeys as $type => $timestampsKey) {
            $fields[] = $timestampsKey;
            $values[] = $this->getTimestampValue($type);
        }

        $filter = new Filter($this->get($this->getPrimaryKey()), $record->get($this->getPrimaryKey()));

        $updated = $this
            ->source($this->getCollection())
            ->fields($fields)
            ->where([$filter])// TODO: needs review
            ->change($values, [$filter->getValue()]);

        $this->reset();

        if (!$updated) {
            throw new SimplesActionError(get_class($this), $action);
        }
        $record->setPublic($this->getHashKey());
        $record = $previous->merge($record->all());

        if (!$this->after($action, $record)) {
            throw new SimplesHookError(get_class($this), $action, 'after');
        }
        return $record;
    }

    /**
     * Remove the given record of database
     * @param array|Record $record (null)
     * @param string $alias ('destroy')
     * @return Record
     * @throws SimplesActionError
     * @throws SimplesHookError
     * @throws SimplesResourceError
     * @throws SimplesRunTimeError
     */
    final public function destroy($record = null, string $alias = null): Record
    {
        $record = Record::parse($record);

        foreach ($this->getParents() as $parent) {
            /** @var DataMapper $parent */
            $record->import($parent->destroy($record)->all());
        }

        $action = coalesce($alias, Action::DESTROY);

        $previous = $this->previous($record, $this->hashKey);

        if ($previous->isEmpty()) {
            throw new SimplesResourceError([$this->getHashKey() => $record->get($this->getHashKey())]);
        }

        if (!$this->before($action, $record, $previous)) {
            throw new SimplesHookError(get_class($this), $action, 'before');
        }

        $filter = new Filter($this->get($this->getPrimaryKey()), $record->get($this->getPrimaryKey()));
        $filters = [$filter];

        if ($this->destroyKeys) {
            $fields = [];
            $values = [];
            foreach ($this->destroyKeys as $type => $deletedKey) {
                $fields[] = $deletedKey;
                $values[] = $this->getTimestampValue($type);
            }

            $removed = $this
                ->source($this->getCollection())
                ->fields($fields)
                ->where($filters)// TODO: needs review
                ->change($values, [$filter->getValue()]);
        }

        if (!isset($removed)) {
            $removed = $this
                ->source($this->getCollection())
                ->where($filters)// TODO: needs review
                ->remove([$record->get($this->getPrimaryKey())]);
        }

        $this->reset();

        if (!$removed) {
            throw new SimplesActionError(get_class($this), $action);
        }
        $record = $previous->merge($record->all());

        if (!$this->after($action, $record)) {
            throw new SimplesHookError(get_class($this), $action, 'after');
        }
        return $record;
    }

    /**
     * Recycle a destroyed record
     * @param array|Record $record (null)
     * @return Record
     * @throws SimplesActionError
     * @throws SimplesHookError
     * @throws SimplesResourceError
     * @throws SimplesRunTimeError
     * @throws SimplesValidationError
     */
    final public function recycle($record = null): Record
    {
        if (!$this->destroyKeys) {
            throw new SimplesValidationError(
                ['destroyKeys' => 'requires'],
                "Recycle needs the `destroyKeys`"
            );
        }

        $record = Record::parse($record);
        foreach ($this->destroyKeys as $deletedKey) {
            $record->set($deletedKey, __NULL__);
        }

        return $this->update($record, 'recycle', true);
    }

    /**
     * Get total of records based on filters
     * @param Record $record
     * @return int
     * @throws Exception
     * @throws SimplesActionError
     * @throws SimplesHookError
     * @throws SimplesRunTimeError
     */
    final public function count(Record $record): int
    {
        $alias = 'count';
        $collection = $this->getCollection();
        $name = $this->getPrimaryKey();
        $type = Field::AGGREGATOR_COUNT;
        $options = ['alias' => $alias];
        $fields = [Field::make($collection, $name, $type, $options)];

        $this->reset();

        $count = $this
            ->fields($fields)
            ->limit(null)
            ->read($record, null, false)
            ->current();

        $this->reset();

        if (!$count->has($alias)) {
            throw new SimplesActionError(get_class($this), $alias);
        }

        return (int)$count->get($alias);
    }

    /**;
     *
     * @param string $action
     * @param bool $strict
     * @return array|mixed
     */
    protected function getActionFields(string $action, bool $strict = true)
    {
        if (off($this->getClauses(), 'fields')) {
            $fields = off($this->getClauses(), 'fields');
            if (!is_array($fields)) {
                $fields = [$fields];
            }
            $this->fields(null);
        }
        if (!isset($fields)) {
            $fields = $this->getFields($action, $strict);
        }
        return $fields;
    }

    /**
     * @param array $fields
     * @return array
     */
    private function clear(array $fields): array
    {
        foreach ([$this->destroyKeys, $this->createKeys, $this->updateKeys] as $keys) {
            foreach ($keys as $name) {
                unset($fields[$name]);
            }
        }
        return $fields;
    }
}


<?php
/**
 * Cookie - Library untuk framework kecik, library ini khusus untuk membantu masalah Database
 *
 * @author 		Dony Wahyu Isp
 * @copyright 	2015 Dony Wahyu Isp
 * @link 		http://github.io/database
 * @license		MIT
 * @version 	1.1.0
 * @package		Kecik\Database
 **/
namespace Kecik;

/**
 * Database
 * @package 	Kecik\Database
 * @author 		Dony Wahyu Isp
 * @since 		1.0.1-alpha
 **/
class Database {
	/**
	 * @var Kecik Class $app
	 **/
	private $app;

	/**
	 * @var string $dsn, $driver, $hostname, $username, $password, $dbname
	 **/
	private $dsn;
	private $driver;
	private $hostname;
	private $username;
	private $password;
	private $dbname;
	//-- End

	/**
	 * @var Driver Class $db
	 **/
	private $db=NULL;
	/**
	 * @var string $table
	 **/
	private $table='';
	/**
	 * @var array $dsnuser ID: Driver yang menggunakan dsn | EN: Driver use dsn
	 **/
	private $dsnuse = ['pdo', 'oci8', 'pgsql', 'mongo'];
	private $failOver = [];
	/**
 	 * __construct
 	 * @param Kecik $app
 	 **/
	public function __construct() {
		$app = Kecik::getInstance();
		$this->app = $app;

		$config = $app->config;

		$this->dsn = ($config->get('database.dsn') != '')?$config->get('database.dsn'):'';
		$this->driver = ($config->get('database.driver') != '')?strtolower($config->get('database.driver')):'';
		$this->hostname = ($config->get('database.hostname') != '')?$config->get('database.hostname'):'';
		$this->username = ($config->get('database.username') != '')?$config->get('database.username'):'';
		$this->password = ($config->get('database.password') != '')?$config->get('database.password'):'';
		$this->dbname = ($config->get('database.dbname') != '')?$config->get('database.dbname'):'';
		$this->charset = ($config->get('database.charset') != '')?$config->get('database.charset'):'';

		$this->failOver = ($config->get('database.failover') != '' && is_array($config->get('database.failover')))?$config->get('database.failover'):[];
	}

	/**
	 * connect
	 * @return res id
	 **/
	public function connect() {

		if (file_exists(dirname( __FILE__ )."/drivers/".$this->driver.".php")) {
			$this->db = include_once("drivers/".$this->driver.".php");
			$failover = (count($this->failOver) > 0)? TRUE:FALSE;

			$con = FALSE;
			if (!isset($_SESSION['failover']) || empty($_SESSION['failover'])) {
				if (in_array($this->driver, ['sqlite', 'sqlite3']))
					$con = @$this->db->connect($this->dbname, $failover);
				elseif (in_array($this->driver, $this->dsnuse))
					$con = @$this->db->connect($this->dsn, $this->dbname, $this->hostname, $this->username, $this->password, $failover);
				else
					$con = @$this->db->connect($this->dbname, $this->hostname, $this->username, $this->password, $failover, $this->charset);
			}

			if (!$con && count($this->failOver) > 0) {
				$fo = $this->failOver;
				if (isset($_SESSION['failover']) && !empty($_SESSION['failover'])) {
					$fo_id = base64_decode($_SESSION['failover']);
					if (in_array($fo[$fo_id]['driver'], ['sqlite', 'sqlite3']))
						$con = @$this->db->connect($fo[$fo_id]['dbname'], $failover);
					elseif (in_array($fo[$fo_id]['driver'], $this->dsnuse))
						$con = @$this->db->connect($fo[$fo_id]['dsn'], $fo[$fo_id]['dbname'], $fo[$fo_id]['hostname'], $fo[$fo_id]['username'], $fo[$fo_id]['password'], $failover);
					else
						$con = @$this->db->connect($fo[$fo_id]['dbname'], $fo[$fo_id]['hostname'], $fo[$fo_id]['username'], $fo[$fo_id]['password'], $failover);
				} else {
					while(list($id, $fo_config) = each($fo)) {
						if (in_array($fo_config['driver'], ['sqlite', 'sqlite3']))
							$con = @$this->db->connect($fo_config['dbname'], $failover);
						elseif (in_array($fo_config['driver'], $this->dsnuse))
							$con = @$this->db->connect($fo_config['dsn'], $fo_config['dbname'], $fo_config['hostname'], $fo_config['username'], $fo_config['password'], $failover);
						else
							$con = @$this->db->connect($fo_config['dbname'], $fo_config['hostname'], $fo_config['username'], $fo_config['password'], $failover);

						if ($con) {
							$_SESSION['failover'] = base64_encode($id);
							break;
						}
					}

				}

				if (!$con) {
					header('X-Error-Message: Fail Connecting', true, 500);
					die('All Connecting Database Error');
					$this->db = NULL;
				}
				return $this->db;
			} else {
				if (isset($_SESSION['failover']))
					unset($_SESSION['failover']);
			}

			return $this->db;

		} else
			throw new \Exception('Database Library: Unknown Driver');

	}

	/**
	 * exec
	 * @param string $query
	 * @return res
	 **/
	public function exec($query) {
		$this->table = '';
		return $this->db->exec($query);
	}

	/**
	 * fetch
	 * @param res ID: dari exec() | EN: from exec()
	 * @return array object
	 **/
	public function fetch($res) {
		return $this->db->fetch($res);
	}

	/**
	 * affected
	 **/
	public function affected() {
		if (in_array($this->driver, ['sqlite', 'sqlite3','oci8']) )
			echo 'Fungsi tidak support untuk driver '.$this->driver;

		return $this->db->affected();
	}

	/**
	 * __get
	 * @param string $table ID: nama table | EN: table name
	 **/
	public function __get($table) {
        $this->table = $table;
        return $this;
    }

    /**
     * insert
     * @param array $data
     * @param string $table
     * @return res
     **/
	public function insert($data, $table='') {
		$table = (!empty($this->table))?$this->table:$table;

		return $this->db->insert($table, $data);
	}

	/**
     * update
     * @param array $id primary key
     * @param array $data
     * @param string $table
     * @return res
     **/
	public function update($id, $data, $table='') {
		$table = (!empty($this->table))?$this->table:$table;

		return $this->db->update($table, $id, $data);
	}

	/**
     * insert
     * @param array $id primary key
     * @param string $table
     * @return res
     **/
	public function delete($id, $table='') {
		$table = (!empty($this->table))?$this->table:$table;

		return $this->db->delete($table, $id);
	}

	/**
     * insert
     * @param array $condition
     * @param string $table
     * @return res
     **/
	public function find($condition=[], $limit=[], $order_by=[],$table='') {
		$table = (!empty($this->table))?$this->table:$table;

		return $this->db->find($table, $condition, $limit, $order_by);
	}

	public function raw_find($condition=[], $limit=[], $order_by=[],$table='') {
		$table = (!empty($this->table))?$this->table:$table;

		return $this->db->raw_find($table, $condition, $limit, $order_by);
	}

	public function fields() {
		$table = (!empty($this->table))?$this->table:$table;

		return $this->db->fields($table);
	}

	public function num_rows() {
		return $this->db->num_rows();
	}

	public function insert_id() {
		return $this->db->insert_id();
	}

	public function set_pk($pk) {
		$this->db->set_pk($pk);
	}

	public function __destruct() {
		unset($this->db);
	}

}


<?php

namespace Potter\Utils;

use Illuminate\Support\Collection;
use RW_Meta_Box;

class Metabox extends Collection
{
    protected $attributes;

    public function __construct(array $attributes, array $fields = array(), $autoRegister = true)
    {
        $this->parseAttributes($attributes);

        $this->addFields($fields);

        if ($autoRegister and is_admin()) add_filter('admin_init', array($this, 'register'));
    }

    /**
     * @param array $attributes
     */
    private function parseAttributes($attributes)
    {
        if (isset($attributes['fields']) && is_array($attributes['fields'])):
            $this->addFields($attributes['fields']);
            unset($attributes['fields']);
        endif;

        $default = array(
            'title'    => __('Data'),
            'pages'    => array('page'),
            'context'  => 'normal',
            'priority' => 'high',
            'autosave' => false,
        );

        $this->attributes = wp_parse_args($attributes, $default);
    }

    /**
     * @param array $fields
     *
     * @return $this
     */
    public function addFields(array $fields)
    {
        foreach ($fields as $key => $field):
            $this->addField($key, $field);
        endforeach;

        return $this;
    }

    /**
     * @param string $id
     * @param array  $attributes
     *
     * @return $this
     */
    public function addField($id, array $attributes)
    {
        if (is_string($id) and !isset($attributes['id'])):
            $attributes['id'] = $id;
        endif;

        $this->push($attributes);

        return $this;
    }

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

    /**
     * @param $key
     * @param $value
     *
     * @return $this
     */
    public function setAttribute($key, $value)
    {
        $this->attributes[$key] = $value;

        return $this;
    }

    /**
     * @param array $pages
     *
     * @return $this
     */
    public function setPages()
    {
        $args = func_get_args();

        if (count($args) == 1):
            $pages = (array)$args[0];
        else:
            $pages = $args;
        endif;

        $this->setPages('pages', $pages);

        return $this;
    }

    /**
     * @param $key
     *
     * @return mixed
     */
    public function getAttribute($key)
    {
        return array_get($this->attributes, $key);
    }

    /**
     * @return array
     */
    public function toArray()
    {
        $box    = $this->attributes;
        $fields = $this->getFields();

        $box['fields'] = $fields;

        return $box;
    }

    /**
     * @see https://github.com/rilwis/meta-box/blob/master/demo/better-include.php#L60
     * @return bool
     */
    protected function canRegister()
    {
        // Include in back-end only
        if (!defined('WP_ADMIN') || !WP_ADMIN) return false;
        // Always include for ajax
        if (defined('DOING_AJAX') && DOING_AJAX) return true;

        $conditions = $this->get('conditions', []);

        if (empty($conditions)) return true;

        if (isset($_GET['post'])):
            $post_id = intval($_GET['post']);
        elseif (isset($_POST['post_ID'])):
            $post_id = intval($_POST['post_ID']);
        else:
            $post_id = false;
        endif;

        $post_id = (int)$post_id;

        $post = get_post($post_id);

        foreach ($conditions as $cond => $v):

            if (!is_array($v)) $v = array($v); // Catch non-arrays too

            switch ($cond):
                case 'id':
                    if (in_array($post_id, $v)) return true;

                    break;
                case 'parent':
                    $post_parent = $post->post_parent;
                    if (in_array($post_parent, $v)) return true;

                    break;
                case 'slug':
                    $post_slug = $post->post_name;
                    if (in_array($post_slug, $v)) return true;

                    break;
                case 'category': //post must be saved or published first
                    $categories = get_the_category($post->ID);
                    $catslugs   = array();

                    foreach ($categories as $category):
                        array_push($catslugs, $category->slug);
                    endforeach;

                    if (array_intersect($catslugs, $v)) return true;

                    break;
                case 'template':
                    $template = get_post_meta($post_id, '_wp_page_template', true);

                    if (in_array($template, $v)) return true;

                    break;
            endswitch;
        endforeach;

        return false;
    }

    /**
     * @return bool|RW_Meta_Box
     */
    public function register()
    {
        if(!$this->canRegister()) return false;

        $box = $this->toArray();

        return new RW_Meta_Box($box);
    }
}


<?php

namespace Potter\Post;

use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use WP_Query;

/**
 * Class Query
 * @package Potter\Post
 */
class Query
{
    private $args;

    public function __construct(array $args = array(), $postType = null, $perPage = null)
    {
        $this->args = new Collection($args);
        if (!empty($postType)) $this->postType($postType);
        if (!empty($perPage)) $this->perPage($perPage);

    }

    /**
     * @param $type
     *
     * @return Query
     */
    public function postType($type)
    {
        return $this->put('post_type', $type);
    }

    /**
     * @param $key
     * @param $value
     *
     * @return Query;
     */
    private function put($key, $value)
    {
        $this->args->put($key, $value);

        return $this;
    }

    /**
     * @param $perPage
     *
     * @return Query
     */
    public function perPage($perPage)
    {
        return $this->put('posts_per_page', $perPage);
    }

    /**
     * @param $value
     *
     * @return Query
     */
    public function order($value)
    {
        return $this->put('order', $value);
    }

    /**
     * @param $value
     *
     * @return Query
     */
    public function orderBy($value)
    {
        return $this->put('orderby', $value);
    }

    /**
     * @param int   $limit
     * @param array $args
     *
     * @return WP_Query
     */
    public function get($limit, $args = array())
    {
        if (is_numeric($limit)):
            return $this->perPage($limit)->exe($args);
        else:
            return $this->exe($args);
        endif;
    }

    /**
     * @param $id
     *
     * @return WP_Query
     */
    public function byParent($id)
    {
        return $this->put('post_parent', $id)->exe();
    }

    /**
     * @param $ids
     *
     * @return WP_Query
     */
    public function byParents($ids)
    {
        $ids = (array)$ids;

        return $this->put('post_parent__in', $ids)->exe();
    }

    /**
     * @param $ids
     *
     * @return Query
     */
    public function exclude($ids)
    {
        $ids = (array)$ids;

        return $this->put('post__not_in', $ids);
    }

    /**
     * @param $id
     *
     * @return WP_Query
     */
    function byID($id)
    {
        return $this->put('p', $id)->exe();
    }

    /**
     * @param $ids
     *
     * @return WP_Query
     */
    function byIDs($ids)
    {
        return $this->put('post__in', $ids)->exe();
    }

    /**
     * @param array|int $id
     *
     * @return WP_Query
     */
    public function notID($id)
    {
        return $this->notIDs($id);
    }

    /**
     * @param array $ids
     *
     * @return WP_Query
     */
    public function notIDs($ids)
    {
        return $this->exclude($ids)->exe();
    }

    /**
     * @return WP_Query
     */
    public function all()
    {
        return $this->perPage(-1)->exe();
    }

    /**
     * @param array $args
     *
     * @return \WP_Post
     */
    public function first($args = array())
    {
        $query = $this->perPage(1)->exe($args);

        return $query->post;
    }

    /**
     * @param array $args
     *
     * @return WP_Query
     */
    public function exe($args = array())
    {
        $_query = wp_parse_args($this->args->all(), $args);
        $_query = new WP_Query($_query);

        return $_query;
    }

    /**
     * @param $key
     *
     * @return mixed
     */
    public function __get($key)
    {
        return $this->args->get($key);
    }

    /**
     * @param $key
     * @param $value
     *
     * @return Query
     */
    public function __set($key, $value)
    {
        return $this->put($key, $value);
    }

    /**
     * @param $name
     * @param $args
     *
     * @return Query
     */
    public function __call($name, $args)
    {
        $name = Str::snake($name);

        switch (count($args)):
            case 0:
                $this->__set($name, true);
                break;
            case 1:
                $this->__set($name, $args[0]);
                break;
            default:
                $this->__set($name, $args);
                break;
        endswitch;

        return $this;
    }
}


<?php namespace Potter\Utils;

use Illuminate\Support\Collection;

/**
 * Class Paginator
 * @package Potter\Utils
 *
 * @property string $before
 * @property string $after
 * @property string $before_link
 * @property string $after_link
 * @property string $link
 * @property array  $class
 * @property array  $labels
 */
class Paginator
{
    /**
     * @var Collection
     */
    protected     $args;
    protected     $wp_query, $currentPage, $pages, $range, $showItens;
    protected     $element     = '';
    public static $argsDefault = array(
        'before'      => '
',
        'after'       => '
',
        'before_link' => '
',
        'after_link'  => '
',
        'link'        => '%2$s',
        'class'       => array(
            'disabled' => 'disabled',
            'active'   => 'active',
            'before'   => '',
            'prev'     => 'prev',
            'after'    => '',
            'first'    => 'first',
            'last'     => 'last',
            'back'     => 'back',
            'next'     => 'next',
            'link'     => ''
        ),
        'labels'      => array(
            'first'  => 'first',
            'last'   => 'last',
            'prev'   => '«',
            'next'   => '»',
            'active' => '%1$s (current)'
        )
    );

    public function __construct(array $args = [], $pages = null, $range = 2, $_wp_query = null)
    {
        $this->setArgs($args);
        $this->setQuery($_wp_query);
        $this->setPages($pages);
        $this->setCurrentPage();
        $this->range     = $range;
        $this->showItens = ($this->range * 2) + 1;
    }

    /**
     * @param $key
     *
     * @return mixed|null
     */
    public function __get($key)
    {
        return $this->get($key);
    }

    /**
     * @param      $key
     * @param null $default
     *
     * @return mixed
     */
    protected function get($key, $default = null)
    {
        return $this->args->get($key, $default);
    }

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

    /**
     * @return string
     */
    public function render()
    {
        if (empty($this->element)):
            $this->run();
        endif;

        return $this->element;
    }

    protected function run()
    {
        if ($this->pages > 1):
            $this->_before(); //Before

            $this->_first(); // First

            $this->_prev(); // Prev

            $this->_loop(); // Loop

            $this->_next(); // next

            $this->_last(); // Last

            $this->_after();// After
        endif;
    }

    /**
     * @return $this
     */
    protected function _before()
    {
        $before = sprintf($this->before, $this->class['before']);
        $this->addToElement($before);

        return $this;
    }

    /**
     * @return $this
     */
    protected function _after()
    {
        $before = sprintf($this->after, $this->class['after']);
        $this->addToElement($before);

        return $this;
    }

    /**
     * @return $this
     */
    protected function _first()
    {
        if ($this->currentPage > 2 && $this->currentPage > $this->range + 1 && $this->showItens < $this->pages) :
            $url  = get_pagenum_link(1);
            $link = $this->_makeLink($url, $this->labels['first']);

            $this->_item($this->class['first'], $link);
        endif;

        return $this;
    }

    /**
     * @return $this
     */
    protected function _last()
    {
        if ($this->currentPage < $this->pages - 1 && $this->currentPage + $this->range - 1 < $this->pages && $this->showitems < $this->pages) :
            $url  = get_pagenum_link($this->pages);
            $link = $this->_makeLink($url, $this->labels['last']);

            $this->_item($this->class['last'], $link);
        endif;

        return $this;
    }

    /**
     * @return $this
     */
    protected function _prev()
    {
        $label = $this->labels['prev'];
        $class = $this->class['prev'];

        if ($this->currentPage > 1 && $this->showItens < $this->pages) :
            $url = get_pagenum_link($this->currentPage - 1);
        else:
            $class .= ' ' . $this->class['disabled'];
            $url = 'javascript:;';
        endif;

        $link = $this->_makeLink($url, $label);
        $this->_item($class, $link);

        return $this;
    }

    /**
     * @return $this
     */
    protected function _next()
    {
        $label = $this->labels['next'];
        $class = $this->class['next'];

        if ($this->currentPage < $this->pages && $this->showItens < $this->pages) :
            $url = get_pagenum_link($this->currentPage + 1);
        else:
            $class = $this->class['prev'] . ' ' . $this->class['disabled'];
            $url   = 'javascript:;';
        endif;

        $link = $this->_makeLink($url, $label);
        $this->_item($class, $link);

        return $this;
    }

    /**
     * @return void
     */
    protected function _loop()
    {
        for ($i = 1; $i <= $this->pages; $i++) :
            if (1 != $this->pages && (!($i >= $this->currentPage + $this->range + 1 || $i <= $this->currentPage - $this->range - 1) || $this->pages <= $this->showItens)):
                if ($this->currentPage == $i):
                    $class = $this->class['active'] . ' link-' . $i;
                    $url   = 'javascript:;';
                    $label = sprintf($this->labels['active'], $i);
                    $link  = $this->_makeLink($url, $label);
                else :
                    $url   = get_pagenum_link($i);
                    $class = 'link-' . $i;
                    $label = $i;
                    $link  = $this->_makeLink($url, $label);
                endif;

                $this->_item($class, $link);
            endif;
        endfor;
    }

    /**
     * @param string $class
     * @param string $link
     *
     * @return $this
     */
    protected function _item($class, $link)
    {
        $before = sprintf($this->before_link, $class);
        $after  = $this->after_link;
        $item   = $before . $link . $after;

        $this->addToElement($item);

        return $this;
    }

    /**
     * @param      $url
     * @param      $text
     * @param null $class
     *
     * @return $this
     */
    protected function _makeLink($url, $text, $class = null)
    {
        $class .= ' ' . $this->class['link'];
        $link = sprintf($this->link, $url, $text, $class);

        return $link;
    }

    /**
     * @param string $el
     *
     * @return $this
     */
    protected function addToElement($el)
    {
        $this->element .= $el . "\n";

        return $this;
    }

    /**
     * @param null $_wp_query
     *
     * @return void
     */
    private function setQuery($_wp_query)
    {
        if (is_null($_wp_query)):
            global $wp_query;
            $this->wp_query = $wp_query;
        else:
            $this->wp_query = $_wp_query;
        endif;
    }

    /**
     * @param null $_currentPage
     *
     * @return void
     */
    private function setCurrentPage($_currentPage = null)
    {
        if (is_null($_currentPage)):
            global $paged;
            $this->currentPage = $paged;
        else:
            $this->currentPage = $_currentPage;
        endif;

        if (empty($this->currentPage)):
            $this->currentPage = 1;
        endif;
    }

    /**
     * @param $_pages
     *
     * @return void
     */
    private function setPages($_pages)
    {
        if (empty($_pages)):
            $_pages = $this->wp_query->max_num_pages;
        endif;

        if (!$_pages):
            $this->pages = 1;
        else:
            $this->pages = $_pages;
        endif;
    }

    /**
     * @param array $args
     *
     * @return void
     */
    private function setArgs(array $args)
    {
        $args       = wp_parse_args($args, self::$argsDefault);
        $this->args = new Collection($args);
    }

    /**
     * @param array $args
     *
     * @return static;
     */
    public static function make(array $args = array(), $pages = null, $range = 2, $_wp_query = null)
    {
        return new static ($args, $pages, $range, $_wp_query);
    }

}