<?php

namespace CottaCush\Yii2\Controller;

use Lukasoppermann\Httpstatus\Httpstatus;
use Yii;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\web\Controller;
use yii\web\Response;

/**
 * Class BaseController
 * @package app\controllers
 * @author Adegoke Obasa <goke@cottacush.com>
 * @codeCoverageIgnore
 */
class BaseController extends Controller
{
    /**
     * @var Httpstatus $httpStatuses
     */
    protected $httpStatuses;

    const FLASH_SUCCESS_KEY = 'success';
    const FLASH_ERROR_KEY = 'error';

    public function init()
    {
        parent::init();
        $this->httpStatuses = new Httpstatus();
    }

    /**
     * Executed after action
     * @author Adegoke Obasa <goke@cottacush.com>
     * @param \yii\base\Action $action
     * @param mixed $result
     * @return mixed
     */
    public function afterAction($action, $result)
    {
        $result = parent::afterAction($action, $result);
        $this->setSecurityHeaders();

        /**
         * Set Current Transaction in New Relic
         * @author Adegoke Obasa <goke@cottacush.com>
         */
        if (extension_loaded('newrelic')) {
            newrelic_name_transaction($action->controller->id . '/' . $action->id);
        }
        return $result;
    }

    /**
     * Set Headers to prevent Click-jacking and XSS
     * @author Adegoke Obasa <goke@cottacush.com>
     */
    private function setSecurityHeaders()
    {
        $headers = Yii::$app->response->headers;
        $headers->add('X-Frame-Options', 'DENY');
        $headers->add('X-XSS-Protection', '1');
    }

    /**
     * Allow sending success response
     * @author Oluwarotimi Akintewe <akintewe.rotimi@gmail.com>
     * @author Adegoke Obasa <goke@cottacush.com>
     * @param $data
     * @return array
     */
    public function sendSuccessResponse($data)
    {
        \Yii::$app->response->format = Response::FORMAT_JSON;
        \Yii::$app->response->setStatusCode(200, $this->httpStatuses->getReasonPhrase(200));

        return [
            'status' => 'success',
            'data' => $data
        ];
    }

    /**
     * Allows sending error response
     * @author Oluwarotimi Akintewe <akintewe.rotimi@gmail.com>
     * @author Adegoke Obasa <goke@cottacush.com>
     * @param $message
     * @param $code
     * @param $httpStatusCode
     * @param null $data
     * @return array
     */
    public function sendErrorResponse($message, $code, $httpStatusCode, $data = null)
    {

        \Yii::$app->response->format = Response::FORMAT_JSON;
        \Yii::$app->response->setStatusCode($httpStatusCode, $this->httpStatuses->getReasonPhrase($httpStatusCode));

        $response = [
            'status' => 'error',
            'message' => $message,
            'code' => $code
        ];

        if (!is_null($data)) {
            $response["data"] = $data;
        }

        return $response;
    }

    /**
     * Sends fail response
     * @param $data
     * @author Oluwarotimi Akintewe <akintewe.rotimi@gmail.com>
     * @author Adegoke Obasa <goke@cottacush.com>
     * @param int $httpStatusCode
     * @return array
     */
    public function sendFailResponse($data, $httpStatusCode = 500)
    {
        \Yii::$app->response->format = Response::FORMAT_JSON;
        \Yii::$app->response->setStatusCode($httpStatusCode, $this->httpStatuses->getReasonPhrase($httpStatusCode));

        return [
            'status' => 'fail',
            'data' => $data
        ];
    }

    /**
     * This flashes error message and sends to the view
     * @author Adegoke Obasa <goke@cottacush.com>
     * @author Olawale Lawal <wale@cottacush.com>
     * @param $messages
     */
    public function flashError($messages)
    {
        $this->flash(self::FLASH_ERROR_KEY, $messages);
    }

    /**
     * This flashes success message and sends to the view
     * @author Adegoke Obasa <goke@cottacush.com>
     * @author Olawale Lawal <wale@cottacush.com>
     * @param $messages
     */
    public function flashSuccess($messages)
    {
        $this->flash(self::FLASH_SUCCESS_KEY, $messages);
    }

    /**
     * @author Olawale Lawal <wale@cottacush.com>
     * @param $key
     * @param $messages
     */
    protected function flash($key, $messages)
    {
        if (is_array($messages)) {
            foreach ($messages as $message) {
                Yii::$app->session->addFlash($key, $message);
            }
        } else {
            \Yii::$app->session->setFlash($key, $messages);
        }
    }

    /**
     * Get Yii2 request object
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return \yii\console\Request|\yii\web\Request
     */
    public function getRequest()
    {
        return Yii::$app->request;
    }

    /**
     * Get Yii2 response object
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return \yii\console\Request|\yii\web\Response
     */
    public function getResponse()
    {
        return Yii::$app->response;
    }

    /**
     * Get Yii2 session object
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return mixed|\yii\web\Session
     */
    public function getSession()
    {
        return Yii::$app->session;
    }

    /**
     * Get Yii2 security object
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return \yii\base\Security
     */
    public function getSecurity()
    {
        return Yii::$app->security;
    }

    /**
     * Get web user
     * @author Adegoke Obasa <goke@cottacush.com>
     */
    public function getUser()
    {
        return Yii::$app->user;
    }

    /**
     * show flash messages
     * @author Adeyemi Olaoye <yemi@cottacush.com>
     * @param bool $sticky
     * @return string
     */
    public function showFlashMessages($sticky = false)
    {
        $timeout = $sticky ? 0 : 5000;
        $flashMessages = [];
        $allMessages = $this->getSession()->getAllFlashes();
        foreach ($allMessages as $key => $message) {
            if (is_array($message)) {
                $message = $this->mergeFlashMessages($message);
            }
            $flashMessages[] = [
                'message' => $message,
                'type' => $key,
                'timeout' => $timeout
            ];
        }
        $this->getSession()->removeAllFlashes();
        return Html::script('var notifications =' . json_encode($flashMessages));
    }

    /**
     * merge flash messages
     * @author Adeyemi Olaoye <yemi@cottacush.com>
     * @param $messageArray
     * @return string
     */
    protected function mergeFlashMessages($messageArray)
    {
        $messages = array_values($messageArray);
        $flashMessage = '';
        $flashMessageArr = [];
        foreach ($messages as $message) {
            if (is_array($message)) {
                if (strlen($flashMessage) > 0) {
                    $flashMessage .= '
';
                }
                $flashMessage .= $this->mergeFlashMessages($message);
            } else {
                $flashMessageArr[] = $message;
            }
        }

        return $flashMessage . implode('
', $flashMessageArr);
    }

    /**
     * Returns the user for the current module
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return \yii\web\User null|object
     * @throws \yii\base\InvalidConfigException
     */
    public function getModuleUser()
    {
        return $this->module->get('user');
    }

    /**
     * @author Olawale Lawal <wale@cottacush.com>
     * @param $url
     */
    public function sendTerminalResponse($url)
    {
        $this->redirect($url)->send();
        Yii::$app->end();
    }

    /**
     * Checks if the current request is a POST and handles redirection
     * @author Olawale Lawal <wale@cottacush.com>
     * @param null $redirectUrl
     * @return bool
     */
    public function isPostCheck($redirectUrl = null)
    {
        if ($this->getRequest()->isPost) {
            return true;
        }
        if (is_null($redirectUrl)) {
            return false;
        }
        $this->sendTerminalResponse($redirectUrl);
    }

    public function loginRequireBeforeAction()
    {
        $excludedPaths = ArrayHelper::getValue(\Yii::$app->params, 'excludedPaths', []);

        $currentRoute = $this->getRoute();

        /**
         * Check if route is in the excluded path
         */
        if ($this->getUser()->isGuest) {
            if (!in_array($currentRoute, $excludedPaths)) {
                $this->getUser()->loginRequired();
                return false;
            }
        }

        return true;
    }

    /**
     * @author Adeyemi Olaoye <yemi@cottacush.com>
     * @param $message
     * @param null $redirectUrl
     * @return Response
     */
    public function returnError($message, $redirectUrl = null)
    {
        $this->flashError($message);
        if (is_null($redirectUrl)) {
            $redirectUrl = $this->getRequest()->getReferrer();
        }
        return $this->redirect($redirectUrl);
    }

    /**
     * @author Adeyemi Olaoye <yemi@cottacush.com>
     * @param $message
     * @param null $redirectUrl
     * @return Response
     */
    public function returnSuccess($message, $redirectUrl = null)
    {
        $this->flashSuccess($message);
        if (is_null($redirectUrl)) {
            $redirectUrl = $this->getRequest()->getReferrer();
        }
        return $this->redirect($redirectUrl);
    }

    /**
     * @author Adeyemi Olaoye <yemi@cottacush.com>
     * @param $widget
     * @param $config
     * @param null $redirectToOnFail URL to redirect to on fail or if request is not an ajax request
     * @return string
     */
    public function renderWidgetAsAjax($widget, $config, $redirectToOnFail = null)
    {
        $referrer = $this->getRequest()->getReferrer() ?: Yii::$app->homeUrl;

        if (!$this->getRequest()->isAjax) {
            if (is_null($redirectToOnFail)) {
                return $referrer;
            } else {
                return $this->redirect($redirectToOnFail);
            }
        }

        ob_start();
        ob_implicit_flush(false);

        $this->view->beginPage();
        $this->view->head();
        $this->view->beginBody();
        echo $widget::widget($config);
        $this->view->endBody();
        $this->view->endPage(true);

        return ob_get_clean();
    }

    /**
     * Sets a session variable and redirects to the URL
     * @author Taiwo Ladipo <ladipotaiwo01@gmail.com>
     * @param $key
     * @param $value
     * @param $redirectUrl
     * @return \yii\web\Response
     */
    public function setSessionAndRedirect($key, $value, $redirectUrl)
    {
        $this->getSession()->set($key, $value);
        return $this->redirect($redirectUrl);
    }

    /**
     * Get Permission Based Access Manager Configuration
     * @author Taiwo Ladipo <ladipotaiwo01@gmail.com>
     * @return mixed
     */
    public function getPermissionManager()
    {
        return Yii::$app->permissionManager;
    }

    /**
     * Handle access based on permissions
     * @author Taiwo Ladipo <ladipotaiwo01@gmail.com>
     * @param $permissionKeys
     * @param bool $redirect
     * @param $fullAccessKey
     * @param $errorMsg
     * @param $defaultUrl
     * @return bool|Response
     * @throws \yii\base\ExitException
     * @throws \yii\web\ForbiddenHttpException
     */
    public function canAccess($permissionKeys, $fullAccessKey, $errorMsg, $defaultUrl, $redirect = false)
    {
        if ($this->getUser()->isGuest) {
            return $this->getUser()->loginRequired();
        }

        if ($this->getPermissionManager()->canAccess($fullAccessKey)) {
            return true;
        }

        if (!is_array($permissionKeys)) {
            $permissionKeys = [$permissionKeys];
        }

        foreach ($permissionKeys as $permissionKey) {
            if ($this->getPermissionManager()->canAccess($permissionKey)) {
                return true;
            }
        }

        if ($redirect) {
            $this->flashError($errorMsg);

            $request = $this->getRequest();
            $referrerUrl = $request->referrer;

            $redirectUrl = ($referrerUrl == $request->url || is_null($referrerUrl)) ?
                $defaultUrl : $referrerUrl;

            $this->redirect($redirectUrl)->send();
            Yii::$app->end(); //this enforces the redirect
        }
        return false;
    }
}


<?php

namespace Circuit;

use Circuit\Interfaces\Middleware;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use FastRoute\RouteParser;
use FastRoute\DataGenerator;

/**
 * Based on nikic\FastRoute RouteCollector, but with added Middleware support
 *
 * @author Nik Barham <nik@brokencube.co.uk>
 */
class RouteCollector
{
    /** @var RouteParser FastRoute compatible Route Parser as set in Router::$options */
    protected $routeParser;

    /** @var DataGenerator FastRoute compatible Data Generator as set in Router::$options */
    protected $dataGenerator;

    /** @var string Route prefix for current group(s) */
    protected $currentGroupPrefix;

    /** @var Middleware|string[] Stack of middleware to append to defined routes. Will be temporarily added to during
                                 ->addGroup() calls */
    protected $middlewareStack = [];

    /**
     * Constructs a route collector.
     *
     * @param RouteParser          $routeParser    FastRoute compatible Route Parser as set in Router::$options
     * @param DataGenerator        $dataGenerator  FastRoute compatible Data Generator as set in Router::$options
     * @param Middleware|string[]  $middleware     Array of middle ware to apply to all routes
     */
    public function __construct(RouteParser $routeParser, DataGenerator $dataGenerator, array $middleware = [])
    {
        $this->routeParser = $routeParser;
        $this->dataGenerator = $dataGenerator;
        $this->currentGroupPrefix = '';
        $this->middlewareStack = $middleware;
    }

    /**
     * Adds a route to the collection.
     *
     * The syntax used in the $route string depends on the used route parser.
     *
     * @param string|string[] $httpMethod      HTTP Verb(s) for this route
     * @param string $route                    The route
     * @param mixed  $handler                  Either a handler specified Laravel style: "ControllerClass@MethodName"
     *                                         or a pregenerated HandlerContainer object
     * @param Middleware|string[] $middleware  List of middleware (Middleware objects or named middleware) to add to
     *                                         this route
     */
    public function addRoute($httpMethod, $route, $handler, array $middleware = [])
    {
        if (!$handler instanceof HandlerContainer) {
            $handler = new HandlerContainer($handler, array_merge($this->middlewareStack, $middleware));
        } else {
            $handler->addMiddleware(array_merge($this->middlewareStack, $middleware));
        }

        $handler = serialize($handler);

        $route = $this->currentGroupPrefix . $route;
        $routeDatas = $this->routeParser->parse($route);
        foreach ((array) $httpMethod as $method) {
            foreach ($routeDatas as $routeData) {
                $this->dataGenerator->addRoute($method, $routeData, $handler);
            }
        }
    }

    /**
     * Create a route group with a common prefix.
     *
     * All routes created in the passed callback will have the given group prefix prepended.
     *
     * @param string              $prefix      String to be prepended to this route
     * @param Middleware|string[] $middleware  Middleware to be added to all routes in this group
     * @param callable            $callback    Definition callback
     */
    public function addGroup($prefix, array $middleware, callable $callback)
    {
        $previousMiddlewareStack = $this->middlewareStack;
        $previousGroupPrefix = $this->currentGroupPrefix;
        $this->currentGroupPrefix = $previousGroupPrefix . $prefix;
        $this->middlewareStack = array_merge($previousMiddlewareStack, $middleware);
        $callback($this);
        $this->currentGroupPrefix = $previousGroupPrefix;
        $this->middlewareStack = $previousMiddlewareStack;
    }

    /**
     * Adds a GET route to the collection
     *
     * This is simply an alias of $this->addRoute('GET', $route, $handler, $middleware)
     *
     * @param string              $route       Defined route
     * @param mixed               $handler     Either a handler specified Laravel style: "ControllerClass@MethodName"
     *                                         or a pregenerated HandlerContainer object
     * @param Middleware|string[] $middleware  List of middleware (Middleware objects or named middleware) to add to
     *                                         this route
     */
    public function get($route, $handler, array $middleware = [])
    {
        $this->addRoute('GET', $route, $handler, $middleware);
    }

    /**
     * Adds a POST route to the collection
     *
     * This is simply an alias of $this->addRoute('POST', $route, $handler, $middleware)
     *
     * @param string              $route       Defined route
     * @param mixed               $handler     Either a handler specified Laravel style: "ControllerClass@MethodName"
     *                                         or a pregenerated HandlerContainer object
     * @param Middleware|string[] $middleware  List of middleware (Middleware objects or named middleware) to add to
     *                                         this route
     */
    public function post($route, $handler, array $middleware = [])
    {
        $this->addRoute('POST', $route, $handler, $middleware);
    }

    /**
     * Adds a PUT route to the collection
     *
     * This is simply an alias of $this->addRoute('PUT', $route, $handler, $middleware)
     *
     * @param string              $route       Defined route
     * @param mixed               $handler     Either a handler specified Laravel style: "ControllerClass@MethodName"
     *                                         or a pregenerated HandlerContainer object
     * @param Middleware|string[] $middleware  List of middleware (Middleware objects or named middleware) to add to
     *                                         this route
     */
    public function put($route, $handler, array $middleware = [])
    {
        $this->addRoute('PUT', $route, $handler, $middleware);
    }

    /**
     * Adds a DELETE route to the collection
     *
     * This is simply an alias of $this->addRoute('DELETE', $route, $handler, $middleware)
     *
     * @param string              $route       Defined route
     * @param mixed               $handler     Either a handler specified Laravel style: "ControllerClass@MethodName"
     *                                         or a pregenerated HandlerContainer object
     * @param Middleware|string[] $middleware  List of middleware (Middleware objects or named middleware) to add to
     *                                         this route
     */
    public function delete($route, $handler, array $middleware = [])
    {
        $this->addRoute('DELETE', $route, $handler, $middleware);
    }

    /**
     * Adds a PATCH route to the collection
     *
     * This is simply an alias of $this->addRoute('PATCH', $route, $handler, $middleware)
     *
     * @param string              $route       Defined route
     * @param mixed               $handler     Either a handler specified Laravel style: "ControllerClass@MethodName"
     *                                         or a pregenerated HandlerContainer object
     * @param Middleware|string[] $middleware  List of middleware (Middleware objects or named middleware) to add to
     *                                         this route
     */
    public function patch($route, $handler, array $middleware = [])
    {
        $this->addRoute('PATCH', $route, $handler, $middleware);
    }

    /**
     * Adds a HEAD route to the collection
     *
     * This is simply an alias of $this->addRoute('HEAD', $route, $handler, $middleware)
     *
     * @param string              $route       Defined route
     * @param mixed               $handler     Either a handler specified Laravel style: "ControllerClass@MethodName"
     *                                         or a pregenerated HandlerContainer object
     * @param Middleware|string[] $middleware  List of middleware (Middleware objects or named middleware) to add to
     *                                         this route
     */
    public function head($route, $handler, array $middleware = [])
    {
        $this->addRoute('HEAD', $route, $handler, $middleware);
    }

    /**
     * Returns the collected route data, as provided by the data generator.
     *
     * @return array
     */
    public function getData()
    {
        return $this->dataGenerator->getData();
    }
}


<?php

namespace mrstroz\wavecms\components\helpers;

use mrstroz\wavecms\models\AuthItem;
use Yii;
use yii\base\Component;
use yii\helpers\VarDumper;

class NavHelper extends Component
{

    public static $active = [];

    /**
     * Sort navigation by position attribute
     * @param $Nav
     */
    public static function sortNav(&$Nav)
    {
        usort($Nav, array(self::class, 'sort'));
    }

    /**
     * Sort function user in sortNav
     * @param $a
     * @param $b
     * @return int
     */
    public static function sort($a, $b)
    {
        if (!isset($a['position'])) {
            return 0;
        }

        if (!isset($b['position'])) {
            return 0;
        }

        if ($a['position'] === $b['position']) {
            return 0;
        }
        return ($a['position'] < $b['position']) ? -1 : 1;
    }

    /**
     * Apply active attriute depends on route
     * @param $Nav
     */
    public static function applyActive(&$Nav)
    {
        if ($Nav) {
            foreach ($Nav as &$one) {
                if (isset($one['items'])) {
                    self::applyActive($one['items']);
                }

                if (!isset($one['active'])) {
                    if (is_array($one['url'])) {

                        $url = $one['url'][0];
                        $route = Yii::$app->requestedRoute;
                        $params = Yii::$app->request->getQueryParams();

                        if ($url === '/' && $route === Yii::$app->controller->module->id . '/dashboard/index') {
                            $one['active'] = true;
                        } else {
                            $url = $one['url'];
                            $urlExploded = explode('/', $url[0]);

                            $one['submenuTemplate'] = '';
                            foreach (self::$active as $activeAction) {
                                $urlExploded[count($urlExploded) - 1] = $activeAction;
                                $url[0] = implode('/', $urlExploded);

                                $one['items'][] =
                                    [
                                        'label' => $one['label'] . ' - ' . $activeAction,
                                        'url' => $url,
                                        'options' => [
                                            'class' => 'hidden'
                                        ]
                                    ];

                                if ('/' . Yii::$app->request->getQueryParam('parentRoute') === trim($url[0])) {
                                    $one['items'][] =
                                        [
                                            'label' => $one['label'] . ' - Sub List',
                                            'url' => array_merge(['/' . $route], $params),
                                            'options' => [
                                                'class' => 'hidden'
                                            ]
                                        ];
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * Apply visible attribute depends on permission or url
     * @param $Nav
     */
    public static function applyVisible(&$Nav)
    {
        if ($Nav) {
            foreach ($Nav as &$one) {
                if (!isset($one['visible'])) {
                    if (isset($one['permission'])) {
                        $authItemModel = Yii::createObject(AuthItem::class);
                        $one['visible'] = Yii::$app->user->can($authItemModel::SUPER_ADMIN) || Yii::$app->user->can($one['permission']);
                    } else {
                        if (is_array($one['url'])) {
                            $url = explode('/', trim($one['url'][0], '/'));
                            if (isset($url['0']) && isset($url['1'])) {
                                $one['visible'] = Yii::$app->user->can('Super admin') || Yii::$app->user->can($url[0] . '/' . $url[1]);
                            }
                        }
                    }
                }

                if (isset($one['items'])) {
                    self::applyVisible($one['items']);
                }
            }
        }

    }

}


<?php
/**
 * Controller.php
 * @author    Daniel Mason <daniel@ayeayeapi.com>
 * @copyright (c) 2015 - 2016 Daniel Mason <daniel@ayeayeapi.com>
 * @license   MIT
 * @see       https://github.com/AyeAyeApi/Api
 */

namespace AyeAye\Api;

use AyeAye\Api\Injector\StatusInjector;

/**
 * Class Controller
 * Describes endpoints and child controllers
 * @package AyeAye/Api
 * @see     https://github.com/AyeAyeApi/Api
 */
class Controller
{
    use StatusInjector;

    /**
     * Methods (controllers and endpoints) that should not be publicly listed.
     * @var string[]
     */
    private $hiddenMethods = [
        'getIndexEndpoint' => true, // Value not used
    ];

    /**
     * Hide a method
     *
     * When a controller or endpoint method is hidden, it will no longer be
     * automatically listed in the controllers index. It will, however, still
     * be accessible.
     *
     * @param $methodName
     * @return $this
     * @throws Exception
     */
    protected function hideMethod($methodName)
    {
        if (!method_exists($this, $methodName)) {
            throw new Exception(500, "The method '$methodName' does not exist in ".get_called_class());
        }
        $this->hiddenMethods[$methodName] = true;
        return $this;
    }

    /**
     * Is a method currently hidden.
     *
     * This is used to determine if it should be indexed or not.
     *
     * @param $methodName
     * @return bool
     * @throws Exception
     */
    public function isMethodHidden($methodName)
    {
        if (!method_exists($this, $methodName)) {
            throw new Exception(500, "The method '$methodName' does not exist in ".get_called_class());
        }
        return isset($this->hiddenMethods[$methodName]);
    }

    /**
     * Show a hidden method.
     *
     * This reveals what would otherwise be a hidden method, allowing it to be
     * indexed. If the named method does not exist, it will throw an exception
     * via isMethodHidden.
     *
     * If the method exists but is not hidden this will not do anything.
     *
     * @param $methodName
     * @return $this
     * @throws Exception
     */
    protected function showMethod($methodName)
    {
        if ($this->isMethodHidden($methodName)) {
            unset($this->hiddenMethods[$methodName]);
        }
        return $this;
    }
}


<?php

namespace mrstroz\wavecms\controllers;

use dosamigos\editable\Editable;
use mrstroz\wavecms\components\grid\ActionColumn;
use mrstroz\wavecms\components\grid\CheckboxColumn;
use mrstroz\wavecms\components\grid\EditableColumn;
use mrstroz\wavecms\components\grid\EditableSelectColumn;
use mrstroz\wavecms\components\helpers\Flash;
use mrstroz\wavecms\components\helpers\FontAwesome;
use mrstroz\wavecms\components\helpers\NavHelper;
use mrstroz\wavecms\components\web\Controller;
use mrstroz\wavecms\forms\AssignRoleForm;
use mrstroz\wavecms\models\AuthAssignment;
use mrstroz\wavecms\models\search\UserSearch;
use mrstroz\wavecms\models\User;
use Yii;
use yii\base\InvalidConfigException;
use yii\bootstrap\Html;
use yii\data\ActiveDataProvider;
use yii\db\ActiveQuery;
use yii\grid\DataColumn;
use yii\helpers\ArrayHelper;
use yii\web\NotFoundHttpException;

class UserController extends Controller
{

    public function init()
    {
        $this->heading = Yii::t('wavecms/user', 'Users');

        /** @var User $modelUser */
        $userModel = Yii::createObject(User::className());

        $this->query = $userModel::find()
            ->select(['user.*', 'roles' => 'GROUP_CONCAT(auth_assignment.item_name SEPARATOR ",")'])
            ->leftJoin('auth_assignment', 'user.id = auth_assignment.user_id')
            ->groupBy('user.id');

        $this->dataProvider = new ActiveDataProvider([
            'query' => $this->query,
        ]);

        $this->columns = array(
            [
                'class' => CheckboxColumn::className()
            ],
            'id',
            [
                'class' => EditableColumn::className(),
                'attribute' => 'first_name',
            ],
            [
                'class' => EditableColumn::className(),
                'attribute' => 'last_name',
            ],
            [
                'class' => EditableColumn::className(),
                'attribute' => 'email',
            ],
            [
                'class' => EditableSelectColumn::className(),
                'attribute' => 'is_admin',
                'source' => [
                    [
                        'value' => $userModel::IS_ADMIN_NO,
                        'text' => Yii::t('wavecms/user', 'No'),
                        'class' => 'label label-danger'
                    ],
                    [
                        'value' => $userModel::IS_ADMIN_YES,
                        'text' => Yii::t('wavecms/user', 'Yes'),
                        'class' => 'label label-success'
                    ]
                ],
                'filter' => [
                    $userModel::IS_ADMIN_NO => Yii::t('wavecms/user', 'No'),
                    $userModel::IS_ADMIN_YES => Yii::t('wavecms/user', 'Yes')
                ],
            ],
            [
                'class' => EditableSelectColumn::className(),
                'attribute' => 'status',
                'source' => [
                    [
                        'value' => $userModel::STATUS_DELETED,
                        'text' => Yii::t('wavecms/user', 'Not active'),
                        'class' => 'label label-danger'
                    ],
                    [
                        'value' => $userModel::STATUS_ACTIVE,
                        'text' => Yii::t('wavecms/user', 'Active'),
                        'class' => 'label label-success'
                    ]
                ],
                'filter' => [
                    $userModel::STATUS_DELETED => Yii::t('wavecms/user', 'Not active'),
                    $userModel::STATUS_ACTIVE => Yii::t('wavecms/user', 'Active'),
                ],
            ],

            [
                'class' => DataColumn::className(),
                'attribute' => 'roles',
                'content' => function ($model, $key, $index, $column) {
                    $roles = explode(',', $model->roles);

                    $column = [];
                    foreach (explode(',', $model->roles) as $role) {
                        $class = 'label-light-gray';

                        if ($role === 'Super admin') {
                            $class = 'label-primary';
                        }

                        $column[] = '' . $role . '';
                    }

                    return Html::a(
                            FontAwesome::icon('user-plus'),
                            ['assign', 'id' => $model->id],
                            [
                                'class' => 'btn btn-xs btn-default'
                            ]) . ' ' . implode(' ', $column);
                },
                'filter' => ArrayHelper::map(AuthAssignment::find()->select('item_name')->asArray()->all(), 'item_name', 'item_name')
            ],
            [
                'class' => ActionColumn::className(),
            ],
        );

        $this->filterModel = Yii::createObject(UserSearch::className());

        $this->on(self::EVENT_BEFORE_MODEL_SAVE, function ($event) {
            if ($event->model->password) {
                $event->model->setPassword($event->model->password);
                $event->model->generateAuthKey();

                Flash::message('password_changed', 'success', ['message' => Yii::t('wavecms/user', 'Password has been changed')]);
            }
        });

        parent::init();
    }

    public function beforeAction($action)
    {
        if ($action->id === 'create') {
            $this->scenario = User::SCENARIO_CREATE;
        }

        return parent::beforeAction($action); // TODO: Change the autogenerated stub
    }

    public function behaviors()
    {
        $behaviors = parent::behaviors(); // TODO: Change the autogenerated stub

        $behaviors['access']['rules'][] = [
            'allow' => true,
            'actions' => [
                'assign',
                'un-assign'
            ],
            'roles' => [
                '@'
            ],
        ];

        return $behaviors;
    }

    public function actionAssign($id)
    {

        $this->_checkConfig();
        $model = $this->_fetchOne($id);

        $this->returnUrl = ['index'];
        $this->view->params['h1'] = Yii::t('wavecms/user', 'Assign role to user {user}', ['user' => $model->email]);
        $this->view->title = $this->view->params['h1'];

        array_unshift($this->view->params['buttons_top'], Html::a('Return', $this->returnUrl, ['class' => 'btn btn-default']));
        NavHelper::$active[] = 'assign';

        $roleForm = Yii::createObject(AssignRoleForm::className());
        $authAssignmentModel = Yii::createObject(AuthAssignment::className());

        $assignedRolesDataProvider = new ActiveDataProvider([
            'query' => $authAssignmentModel::find()->where(['user_id' => $id])
        ]);

        if (Yii::$app->request->isPost) {
            $roleForm->load(Yii::$app->request->post());
            if ($roleForm->validate()) {
                $auth = Yii::$app->authManager;
                $role = $auth->getRole($roleForm->role);

                if (!$role)
                    throw new NotFoundHttpException(Yii::t('wavecms/user', 'Role not found'));

                $auth->assign($role, $id);

                Flash::message(
                    'after_create',
                    'success',
                    ['message' => Yii::t('wavecms/user', 'Role has been assigned')]
                );

                return $this->redirect([
                    'assign',
                    'id' => $model->id
                ]);
            }
        }

        return $this->render('assign', [
            'model' => $model,
            'roleForm' => $roleForm,
            'assignedRolesDataProvider' => $assignedRolesDataProvider
        ]);

    }

    public function actionUnAssign($id, $role)
    {

        $this->_checkConfig();
        $model = $this->_fetchOne($id);

        $auth = Yii::$app->authManager;
        $role = $auth->getRole($role);

        if (!$role)
            throw new NotFoundHttpException(Yii::t('wavecms/user', 'Role not found'));

        $auth->revoke($role, $model->id);

        Flash::message('after_create', 'success', ['message' => Yii::t('wavecms/user', 'Role has been revoked')]);

        return $this->redirect([
            'assign',
            'id' => $model->id
        ]);
    }

    protected function _fetchOne($id)
    {
        $query = $this->query;
        $modelClass = Yii::createObject($query->modelClass);

        /** @var ActiveRecord $model */
        $model = $query->andWhere([$modelClass::tableName() . '.id' => $id])->one();

        if (!$model)
            throw new NotFoundHttpException(Yii::t('wavecms/main', 'Element not found'));

        if ($this->scenario) {
            $model->scenario = $this->scenario;
        }

        return $model;
    }

    /**
     * Check if $this->query is set
     * @throws \yii\base\InvalidConfigException
     */
    protected function _checkConfig()
    {
        if (!$this->query)
            throw new InvalidConfigException(Yii::t('wavecms/main', 'The "query" property must be set.'));

        if (!$this->query instanceof ActiveQuery)
            throw new InvalidConfigException(Yii::t('wavecms/main', 'The "query" property is not instance of ActiveQuery.'));
    }

}


<?php

/* This file is part of Version.
 *
 * (c) 2012 Kevin Herrera
 *
 * For the full copyright and license information, please
 * view the LICENSE file that was distributed with this
 * source code.
 */

namespace KevinGH\Version;

use InvalidArgumentException;

/**
 * Manages a semantic version string.
 *
 * @author Kevin Herrera <me@kevingh.com>
 */
class Version
{
    /**
     * The semantic version regular expression.
     *
     * @var string
     */
    const REGEX = '/^\d+\.\d+\.\d+(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/';

    /**
     * The build information.
     *
     * @var array
     */
    private $build;

    /**
     * The major version number.
     *
     * @var integer
     */
    private $major = 0;

    /**
     * The minor version number.
     *
     * @var integer
     */
    private $minor = 0;

    /**
     * The patch number.
     *
     * @var integer
     */
    private $patch = 0;

    /**
     * The pre-release information.
     *
     * @var array
     */
    private $pre;

    /**
     * Parses the string representation of the version information.
     *
     * @param string $string The string representation.
     */
    public function __construct($string = '')
    {
        if (false === empty($string)) {
            $this->parseString($string);
        }
    }

    /**
     * Generates a string using the current version information.
     *
     * @return string The string representation of the information.
     *
     * @api
     */
    public function __toString()
    {
        $string = sprintf('%d.%d.%d', $this->major, $this->minor, $this->patch);

        if ($this->pre) {
            $string .= '-' . join('.', $this->pre);
        }

        if ($this->build) {
            $string .= '+' . join('.', $this->build);
        }

        return $string;
    }

    /**
     * Compares one version to another.
     *
     * @param Version $version Another version.
     *
     * @return -1 If this one is greater, 0 if equal, or 1 if $version is greater.
     *
     * @api
     */
    public function compareTo($version)
    {
        $major = $version->getMajor();
        $minor = $version->getMinor();
        $patch = $version->getPatch();
        $pre = $version->getPreRelease();
        $build = $version->getBuild();

        switch (true) {
            case ($this->major < $major):
                return 1;
            case ($this->major > $major):
                return -1;
            case ($this->minor > $minor):
                return -1;
            case ($this->minor < $minor):
                return 1;
            case ($this->patch > $patch):
                return -1;
            case ($this->patch < $patch):
                return 1;
            // @codeCoverageIgnoreStart
        }
        // @codeCoverageIgnoreEnd

        if ($pre || $this->pre) {
            if (empty($this->pre) && $pre) {
                return -1;
            }

            if ($this->pre && empty($pre)) {
                return 1;
            }

            if (0 !== ($weight = $this->precedence($this->pre, $pre))) {
                return $weight;
            }
        }

        if ($build || $this->build) {
            if ((null === $this->build) && $build) {
                return 1;
            }

            if ($this->build && (null === $build)) {
                return -1;
            }

            return $this->precedence($this->build, $build);
        }

        return 0;
    }

    /**
     * Creates a new Version instance.
     *
     * @param string $string The string representation.
     *
     * @return Version The Version instance.
     *
     * @api
     */
    public static function create($string = '')
    {
        return new static($string);
    }

    /**
     * Checks if the version is equal to the given one.
     *
     * @param Version $version The version to compare against.
     *
     * @return boolean TRUE if equal, FALSE if not.
     *
     * @api
     */
    public function isEqualTo(Version $version)
    {
        return ((string)$this == (string)$version);
    }

    /**
     * Checks if this version is greater than the given one.
     *
     * @param Version $version The version to compare against.
     *
     * @return boolean TRUE if greater, FALSE if not.
     */
    public function isGreaterThan(Version $version)
    {
        return (0 > $this->compareTo($version));
    }

    /**
     * Checks if this version is less than the given one.
     *
     * @param Version $version The version to compare against.
     *
     * @return boolean TRUE if less than, FALSE if not.
     *
     * @api
     */
    public function isLessThan(Version $version)
    {
        return (0 < $this->compareTo($version));
    }

    /**
     * Checks if the version is for a stable release.
     *
     * @return boolean TRUE if stable, FALSE if not.
     */
    public function isStable()
    {
        return empty($this->pre);
    }

    /**
     * Checks if the string is a valid string representation of a version.
     *
     * @param string $string The string.
     *
     * @return boolean TRUE if valid, FALSE if not.
     *
     * @api
     */
    public static function isValid($string)
    {
        return (bool) preg_match(static::REGEX, $string);
    }

    /**
     * Returns the build version information.
     *
     * @return array|null The build version information.
     *
     * @api
     */
    public function getBuild()
    {
        return $this->build;
    }

    /**
     * Returns the pre-release version information.
     *
     * @return array|null The pre-release version information.
     *
     * @api
     */
    public function getPreRelease()
    {
        return $this->pre;
    }

    /**
     * Returns the major version number.
     *
     * @return integer The major version number.
     *
     * @api
     */
    public function getMajor()
    {
        return $this->major;
    }

    /**
     * Returns the minor version number.
     *
     * @return integer The minor version number.
     *
     * @api
     */
    public function getMinor()
    {
        return $this->minor;
    }

    /**
     * Returns the patch version number.
     *
     * @api
     * @return integer The patch version number.
     */
    public function getPatch()
    {
        return $this->patch;
    }

    /**
     * Sets the build version information.
     *
     * @param array|integer|string $build The build version information.
     *
     * @api
     */
    public function setBuild($build)
    {
        $this->build = array_values((array)$build);

        array_walk(
            $this->build,
            function (&$v) {
                if (preg_match('/^[0-9]+$/', $v)) {
                    $v = (int)$v;
                }
            }
        );
    }

    /**
     * Sets the pre-release version information.
     *
     * @param array|integer|string $pre The pre-release version information.
     *
     * @api
     */
    public function setPreRelease($pre)
    {
        $this->pre = array_values((array)$pre);

        array_walk(
            $this->pre,
            function (&$v) {
                if (preg_match('/^[0-9]+$/', $v)) {
                    $v = (int)$v;
                }
            }
        );
    }

    /**
     * Sets the major version number.
     *
     * @param integer|string $major The major version number.
     *
     * @api
     */
    public function setMajor($major)
    {
        $this->major = (int)$major;
    }

    /**
     * Sets the minor version number.
     *
     * @param integer|string $minor The minor version number.
     *
     * @api
     */
    public function setMinor($minor)
    {
        $this->minor = (int)$minor;
    }

    /**
     * Sets the patch version number.
     *
     * @param integer|string $patch The patch version number.
     *
     * @api
     */
    public function setPatch($patch)
    {
        $this->patch = (int)$patch;
    }

    /**
     * Parses the version string, replacing current any data.
     *
     * @param string $string The string representation.
     *
     * @throws InvalidArgumentException If the string is invalid.
     */
    protected function parseString($string)
    {
        $this->build = null;
        $this->major = 0;
        $this->minor = 0;
        $this->patch = 0;
        $this->pre = null;

        if (false === static::isValid($string)) {
            throw new InvalidArgumentException(sprintf('The version string "%s" is invalid.', $string));
        }

        if (false !== strpos($string, '+')) {
            list($string, $build) = explode('+', $string);

            $this->setBuild(explode('.', $build));
        }

        if (false !== strpos($string, '-')) {
            list($string, $pre) = explode('-', $string);

            $this->setPreRelease(explode('.', $pre));
        }

        $version = explode('.', $string);

        $this->major = (int)$version[0];

        if (isset($version[1])) {
            $this->minor = (int)$version[1];
        }

        if (isset($version[2])) {
            $this->patch = (int)$version[2];
        }
    }

    /**
     * Checks the precedence of each data set.
     *
     * @param array $a A data set.
     * @param array $b A data set.
     *
     * @return integer -1 if $a > $b, 0 if $a = $b, 1 if $a < $b.
     */
    protected function precedence($a, $b)
    {
        if (count($a) > count($b)) {
            $l = -1;
            $r = 1;
            $x = $a;
            $y = $b;
        } else {
            $l = 1;
            $r = -1;
            $x = $b;
            $y = $a;
        }

        foreach (array_keys($x) as $i) {
            if (false === isset($y[$i])) {
                return $l;
            }

            if ($x[$i] === $y[$i]) {
                continue;
            }

            $xi = is_integer($x[$i]);
            $yi = is_integer($y[$i]);

            if ($xi && $yi) {
                return ($x[$i] > $y[$i]) ? $l : $r;
            } elseif ((false === $xi) && (false === $yi)) {
                return (max($x[$i], $y[$i]) == $x[$i]) ? $l : $r;
            } else {
                return $xi ? $r : $l;
            }
        }

        return 0;
    }
}


<?php

namespace Vinelab\Auth\Social\Providers\Twitter;

use Vinelab\Auth\Social\Providers\Twitter\Contracts\OAuthTokenInterface;
use Vinelab\Auth\Social\Providers\Twitter\Contracts\OAuthConsumerInterface;

class OAuthSignature implements Contracts\OAuthSignatureInterface
{
    protected $method = 'HMAC-SHA1';

    /**
     * Returns the signing method name used.
     *
     * @return string
     */
    public function method()
    {
        return $this->method;
    }

    /**
     * Get a signature for the request.
     *
     * @param OAuthConsumerInterface $consumer
     * @param OAuthTokenInterface    $token
     * @param string                 $httpverb
     * @param string                 $url
     * @param array                  $params
     *
     * @return string
     */
    public function get(OAuthConsumerInterface $consumer,
                        OAuthTokenInterface $token,
                        $httpverb,
                        $url,
                        $params = [])
    {
        uksort($params, 'strcmp');

        $base_url = $this->baseURL($httpverb, $url, $params);
        $key = $consumer->secret.'&'.$token->secret;

        return base64_encode(hash_hmac('sha1', $base_url, $key, true));
    }

   /**
    * Build the signature base url.
    *
    * @param  string $httpverb
    * @param  string $url
    * @param  array $params
    *
    * @return string
    */
   public function baseURL($httpverb, $url, $params)
   {
       uksort($params, 'strcmp');

       return strtoupper($httpverb).'&'.
                rawurlencode($url).'&'.
                rawurlencode(http_build_query($params));
   }
};


<?php
/**
 * WriterFactoryInjector.php
 * @author    Daniel Mason <daniel@ayeayeapi.com>
 * @copyright (c) 2016 Daniel Mason <daniel@ayeayeapi.com>
 * @license   MIT
 * @see       https://github.com/AyeAyeApi/Api
 */

namespace AyeAye\Api\Injector;

use AyeAye\Formatter\WriterFactory;
use AyeAye\Formatter\Writer\Json;
use AyeAye\Formatter\Writer\Xml;

/**
 * Trait WriterFactoryInjector
 * Allows the injection and management of a WriterFactory object. Provides a default if one isn't set.
 * Note: The default WriterFactory provides writers for Json and XML
 * @package AyeAye/Api
 * @see     https://github.com/AyeAyeApi/Api
 */
trait WriterFactoryInjector
{
    /**
     * A collection of writers available
     * @var WriterFactory
     */
    private $writerFactory;

    /**
     * Sets the writer factory.
     *
     * Use for dependency injection.
     *
     * @param WriterFactory $writerFactory
     * @returns $this
     */
    public function setWriterFactory(WriterFactory $writerFactory)
    {
        $this->writerFactory = $writerFactory;
        return $this;
    }

    /**
     * Get the writer factory.
     *
     * If none is set it will create a default format factory for xml and json
     *
     * @return WriterFactory
     */
    public function getWriterFactory()
    {
        if (!$this->writerFactory) {
            $xmlFormatter = new Xml();
            $jsonFormatter = new Json();
            $this->writerFactory = new WriterFactory([
                // xml
                'xml' => $xmlFormatter,
                'text/xml' => $xmlFormatter,
                'application/xml' => $xmlFormatter,
                // json
                'json' => $jsonFormatter,
                'application/json' => $jsonFormatter,
            ]);
        }
        return $this->writerFactory;
    }
}


<?php

namespace mrstroz\wavecms\components\behaviors;

use yii\base\Behavior;
use yii\db\ActiveRecord;

/**
 * Class CheckboxListBehavior
 * @package mrstroz\wavecms\components\behaviors
 * Behavior used for save checkboxes list in WaveCMS
 */
class CheckboxListBehavior extends Behavior
{

    /**
     * @var array List of fields proceed by behavior
     */
    public $fields = [];

    /**
     * @inheritdoc
     * @return array
     */
    public function events()
    {
        return [
            ActiveRecord::EVENT_BEFORE_UPDATE => 'beforeUpdate',
            ActiveRecord::EVENT_BEFORE_INSERT => 'beforeUpdate',
            ActiveRecord::EVENT_AFTER_FIND => 'afterFind'
        ];
    }

    /**
     * Change array to string separate by ;
     * @param $event
     */
    public function beforeUpdate($event)
    {

        if (is_array($this->fields)) {
            foreach ($this->fields as $field) {
                if (is_array($event->sender->{$field})) {
                    $event->sender->{$field} = implode(';', $event->sender->{$field});
                }
            }
        }

    }

    /**
     * Change string separated by ; to array
     * @param $event
     */
    public function afterFind($event)
    {

        if (is_array($this->fields)) {
            foreach ($this->fields as $field) {
                if ($event->sender->{$field}) {
                    $event->sender->{$field} = explode(';', $event->sender->{$field});
                }
            }
        }

    }
}


<?php
/**
 * Request.php
 * @author    Daniel Mason <daniel@ayeayeapi.com>
 * @copyright (c) 2015 - 2016 Daniel Mason <daniel@ayeayeapi.com>
 * @license   MIT
 * @see       https://github.com/AyeAyeApi/Api
 */

namespace AyeAye\Api;

use AyeAye\Formatter\Reader\Json;
use AyeAye\Formatter\Reader\Xml;
use AyeAye\Formatter\ReaderFactory;

/**
 * Class Request.
 *
 * Describes the details of a request from the client.
 *
 * @package AyeAye/Api
 * @see     https://github.com/AyeAyeApi/Api
 */
class Request implements \JsonSerializable
{
    // HTTP verbs as defined in http://www.ietf.org/rfc/rfc2616
    const METHOD_GET = 'GET';
    const METHOD_HEAD = 'HEAD';
    const METHOD_POST = 'POST';
    const METHOD_PUT = 'PUT';
    const METHOD_DELETE = 'DELETE';
    const METHOD_TRACE = 'TRACE';
    const METHOD_OPTIONS = 'OPTIONS';
    const METHOD_CONNECT = 'CONNECT';
    const METHOD_PATCH = 'PATCH';

    const DEFAULT_FORMAT = 'json';

    /**
     * A list of accepted HTTP verbs. By default everything is accepted
     * however, you could extend Request and provide a different list.
     * @var array
     */
    public $allowedMethods = [
        self::METHOD_GET,
        self::METHOD_HEAD,
        self::METHOD_POST,
        self::METHOD_PUT,
        self::METHOD_DELETE,
        self::METHOD_TRACE,
        self::METHOD_OPTIONS,
        self::METHOD_CONNECT,
        self::METHOD_PATCH,
    ];

    /**
     * The method of request
     * @var string
     */
    protected $requestMethod = null;

    /**
     * What uri did the client request
     * @var string
     */
    protected $requestedUri = '';

    /**
     * The requested uri as an array.
     * @var array
     */
    protected $requestChain = null;

    /**
     * An amalgamation of all parameters sent in any way.
     * @var array
     */
    protected $parameters = [];

    /**
     * The reader factory contains readers that might be able to read the body
     * @var ReaderFactory
     */
    protected $readerFactory;

    /**
     * Request constructor.
     *
     * To take the request as is from PHP, instantiate this class without
     * specifying and arguments. The constructor can be used to immediately
     * override any part of the request or even be used to arbitrarily define
     * request parameters.
     *
     * Note: If any parameters are defined, this will block the actual request
     * parameters from being used.
     *
     * @param string $requestedMethod
     * @param string $requestedUri
     * @param ReaderFactory $readerFactory
     * @param array|object ...$parameters Any number of arrays or objects containing request parameters such as _GET,
     *                                   _POST. This will override the defaults which will otherwise be taken from the
     *                                   url and _REQUEST global variable.
     */
    public function __construct(
        $requestedMethod = null,
        $requestedUri = null,
        ReaderFactory $readerFactory = null
    ) {
        $this->readerFactory = $readerFactory;

        $parameters = array_slice(func_get_args(), 3);
        foreach ($parameters as $parameterGroup) {
            $this->setParameters($parameterGroup);
        }

        $this->requestMethod = $requestedMethod ?: $this->getRequestMethod();
        $this->requestedUri  = $requestedUri    ?: $this->getRequestedUri();
        if (!$this->parameters) {
            $this->parameters = $this->useActualParameters();
        }
    }

    /**
     * Get the reader factory.
     *
     * If none is set, then create one, set it and return it. By default it
     * will only be able to read Xml and Json.
     *
     * @return ReaderFactory
     */
    protected function getReaderFactory()
    {
        if (!$this->readerFactory) {
            $this->readerFactory = new ReaderFactory([
                new Json(),
                new Xml(),
            ]);
        }
        return $this->readerFactory;
    }

    /**
     * Get the HTTP verb for this request.
     *
     * The actual verb can be overridden simply by setting it in the
     * constructor. If no verb is set, and for some reason it can not be found
     * in the _SERVER global variable, a default of 'GET' will be returned.
     *
     * @SuppressWarnings(PHPMD.Superglobals)
     * @return string
     */
    protected function getRequestMethod()
    {
        if ($this->requestMethod) {
            return $this->requestMethod;
        }
        if (array_key_exists('REQUEST_METHOD', $_SERVER)) {
            return $_SERVER['REQUEST_METHOD'];
        }
        return static::METHOD_GET;
    }

    /**
     * Get the requested uri.
     *
     * The actual uri can be overridden simply by setting it in the
     * constructor. If no uri is set, and for some reason it can not be found
     * in the _SERVER global variable, a default of '' will be returned.
     *
     * @SuppressWarnings(PHPMD.Superglobals)
     * @return string
     */
    protected function getRequestedUri()
    {
        if ($this->requestedUri) {
            return $this->requestedUri;
        }
        if (array_key_exists('REQUEST_URI', $_SERVER)) {
            return $_SERVER['REQUEST_URI'];
        }
        return '';
    }

    /**
     * Get parameters associated with this request.
     *
     * Starts the url itself, then the _REQUEST super global, adds headers,
     * then body, overriding in that order (i.e. if a body variable overrides
     * a header, the body will be used instead).
     *
     * @return array
     * @SuppressWarnings(PHPMD.Superglobals)
     */
    protected function useActualParameters()
    {
        $this->setParameters($this->urlToParameters($this->getRequestedUri()));
        $this->setParameters($_REQUEST);
        $this->setParameters($this->parseHeader($_SERVER));
        $this->setParameters($this->stringToArray($this->readBody()));
        return $this->getParameters();
    }

    /**
     * Parse headers.
     *
     * This method should be passed the _SERVER global array. Most http headers
     * in PHP are prefixed with HTTP_ however, there are two values prefixed
     * with CONTENT_. All other values in the array will be ignored.
     *
     * @param string[] $headers
     * @return string
     */
    protected function parseHeader(array $headers = [])
    {
        $processedHeaders = array();
        foreach ($headers as $key => $value) {
            if (substr($key, 0, 5) == 'HTTP_') {
                $name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($key, 5)))));
                $processedHeaders[$name] = $value;
            } elseif ($key == 'CONTENT_TYPE') {
                $processedHeaders['Content-Type'] = $value;
            } elseif ($key == 'CONTENT_LENGTH') {
                $processedHeaders['Content-Length'] = $value;
            }
        }
        return $processedHeaders;
    }

    /**
     * Reads in the body of the request.
     *
     * Uses php streams to get the body of a request.
     *
     * @return string
     */
    protected function readBody()
    {
        return file_get_contents('php://input');
    }

    /**
     * Turns a url string into an array of parameters.
     *
     * This can be a little bit confusing but it allows people to create
     * pretty uri's for an API. This array simply parametrises the uri
     * by assuming each slug is the key for the following one.
     *
     * @example 'here/is/an/example' => ['here' => 'is', 'is' => 'an', 'an' => 'example']
     *
     * @param string $url
     * @return array
     * @SuppressWarnings(PHPMD.Superglobals)
     */
    protected function urlToParameters($url)
    {
        $urlParameters = [];
        $url = parse_url($url, PHP_URL_PATH);
        $urlParts = explode('/', $url);
        reset($urlParts); // Note, the first entry will always be blank
        $key = next($urlParts);
        while (($value = next($urlParts)) !== false) {
            $urlParameters[$key] = $value;
            $key = $value;
        }
        return $urlParameters;
    }

    /**
     * Tries to turn a string of data into an array.
     *
     * This method uses a ReaderFactory that will attempt to read the sting
     * as a number of predefined strings, accepting the first one that returns
     * something. Failing all else, if there was a string it will return an
     * array with the text attached to a 'text' key
     * eg. $this->stringToArray('fail')['body'] == 'fail'
     *
     * @param string $string
     * @return array
     */
    protected function stringToArray($string)
    {
        if (!$string || !is_string($string)) {
            return [];
        }

        $result = $this->getReaderFactory()->read($string);
        if ($result) {
            return $result;
        }

        $array = [];
        $array['text'] = $string;
        return $array;
    }

    /**
     * The http method being used.
     *
     * Get the http verb used for the request.
     *
     * @return string
     */
    public function getMethod()
    {
        return $this->requestMethod;
    }

    /**
     * Look up the value of a requested parameter.
     *
     * A default can be specified. If the parameter is not found the default
     * will be returned. The 'default' defaults to null.
     *
     * @param string $key
     * @param bool $default
     * @return mixed
     */
    public function getParameter($key, $default = null)
    {
        // Request _should_ contain get, post and cookies
        if (array_key_exists($key, $this->parameters)) {
            return $this->parameters[$key];
        }
        // We can also flatten out the variable names to see if they exist
        $flatKey = $this->flatten($key);
        foreach ($this->parameters as $index => $value) {
            if ($flatKey == $this->flatten($index)) {
                return $value;
            }
        }
        return $default;
    }

    /**
     * Flatten a variable name.
     *
     * Simply removes all non alpha numeric characters (except hyphen and
     * underscore) and makes it lower case.
     *
     * @param $name
     * @return string
     */
    protected function flatten($name)
    {
        return strtolower(preg_replace('/[\W_-]/', '', $name));
    }

    /**
     * Returns all parameters.
     *
     * This method should only be used for debugging.
     *
     * @return array
     */
    public function getParameters()
    {
        return $this->parameters;
    }

    /**
     * Get the requested route.
     *
     * Breaks the uri into an array that can be used by the router to determine
     * which controller and endpoint should be called.
     *
     * @return string[]
     */
    public function getRequestChain()
    {
        if (is_null($this->requestChain)) {
            $this->requestChain = $this->getRequestChainFromUri($this->requestedUri);
        }
        return $this->requestChain;
    }

    /**
     * Returns an array of possible formats.
     *
     * The request could specify the desired response format in a number of
     * ways, this method returns them all including a final default fallback.
     *
     * @return string
     */
    public function getFormats()
    {
        return [
            'header' => $this->getParameter('Accept'),
            'suffix' => $this->getFormatFromUri($this->requestedUri),
            'default' => static::DEFAULT_FORMAT,
        ];
    }

    /**
     * Used by PHP to get json object.
     *
     * This method is useful for debugging incoming requests. It should not
     * reveal anything the sender does not know, but might help explain how
     * the request has been processed.
     *
     * @return array|mixed
     */
    public function jsonSerialize()
    {
        return [
            'method' => $this->getMethod(),
            'requestedUri' => $this->requestedUri,
            'parameters' => $this->getParameters()
        ];
    }

    /**
     * Get the format from the url.
     *
     * If the request had a suffix in the url, this method will discover it and
     * return it.
     *
     * @example /hello-world.json => json
     * @example /hello-world.xml => xml
     * @example /hello-world => null
     *
     * @param $requestedUri
     * @return string|null
     */
    protected function getFormatFromUri($requestedUri)
    {
        $uriParts = explode('?', $requestedUri, 2);
        $uriWithoutGet = reset($uriParts);
        $uriAndFormat = explode('.', $uriWithoutGet);
        if (count($uriAndFormat) >= 2) {
            return end($uriAndFormat);
        }
        return null;
    }

    /**
     * Breaks up the uri.
     *
     * Breaks the uri into slugs used to work out the route.
     *
     * @param string $requestedUri
     * @return string[]
     */
    protected function getRequestChainFromUri($requestedUri)
    {
        // Trim any get variables and the requested format, eg: /requested/uri.format?get=variables
        $requestedUri = preg_replace('/[\?\.].*$/', '', $requestedUri);
        // Clear the base url

        $requestChain = explode('/', $requestedUri);

        if (!$requestChain[0]) {
            unset($requestChain[0]);
        }

        return array_values($requestChain);
    }

    /**
     * Add a set of parameters to the Request.
     *
     * This method is for internal use only. It allows setting of key => value
     * parameters, including for string objects (assuming a Reader has been set
     * up for them).
     *
     * @param array|object $newParameters
     * @throws \Exception
     * @returns $this
     */
    protected function setParameters($newParameters)
    {
        if (is_scalar($newParameters)) {
            if (!is_string($newParameters)) {
                throw new \Exception('newParameters can not be scalar');
            }
            $newParameters = $this->stringToArray($newParameters);
        }
        foreach ($newParameters as $field => $value) {
            $this->setParameter($field, $value);
        }
        return $this;
    }

    /**
     * Add a parameter
     *
     * Adds a single parameter, checking the parameter name is scalar.
     *
     * @param $name
     * @param $value
     * @return bool Returns true of value was set
     * @throws \Exception
     */
    protected function setParameter($name, $value)
    {
        if (!is_scalar($name)) {
            throw new \Exception('Parameter name must be scalar');
        }
        $this->parameters[$name] = $value;
        return $this;
    }
}


<?php

namespace Vinelab\Auth;

use Illuminate\Support\ServiceProvider;
use Vinelab\Auth\Cache\Store;
use Vinelab\Auth\Social\ProvidersManager;
use Illuminate\Foundation\Application as App;

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

    public function boot()
    {
        $this->publishes([
            __DIR__.'/../../config/social.php' => config_path('social.php'),
        ]);
    }

    /**
     * Register the service provider.
     */
    public function register()
    {
        $this->app->register('Vinelab\Http\HttpServiceProvider');
        $this->app->register('Vinelab\Assistant\AssistantServiceProvider');

        $this->app->bind('Vinelab\Auth\Contracts\StoreInterface', function (App $app) {
            return new Store($app->make('cache'));
        });

        $this->app->bind(
            'Vinelab\Auth\Social\Providers\Twitter\Contracts\OAuthSignatureInterface',
            'Vinelab\Auth\Social\Providers\Twitter\OAuthSignature'
        );

        $this->app->bind(
            'Vinelab\Auth\Social\Providers\Twitter\Contracts\OAuthConsumerInterface',
            'Vinelab\Auth\Social\Providers\Twitter\OAuthConsumer'
        );

        $this->app->bind(
            'Vinelab\Auth\Social\Providers\Twitter\Contracts\OAuthTokenInterface',
            'Vinelab\Auth\Social\Providers\Twitter\OAuthToken'
        );

        $this->app->bind(
            'Vinelab\Auth\Social\Providers\Twitter\Contracts\OAuthInterface',
            'Vinelab\Auth\Social\Providers\Twitter\OAuth'
        );

        $this->app->singleton('Vinelab\Auth\Contracts\ProvidersManagerInterface', function (App $app) {
            return new ProvidersManager(
                $app->make('config'),
                $app->make('redirect'),
                $app->make('vinelab.httpclient'),
                $app->make('Vinelab\Auth\Contracts\StoreInterface'),
                $app->make('Vinelab\Auth\Contracts\ProfileInterface'),
                $app->make('Vinelab\Auth\Social\Providers\Facebook\Contracts\AccessTokenInterface'),
                $app->make('Vinelab\Auth\Social\Providers\Twitter\Contracts\OAuthInterface'),
                $app->make('Vinelab\Auth\Social\Providers\Twitter\Contracts\OAuthTokenInterface'),
                $app->make('Vinelab\Auth\Social\Providers\Twitter\Contracts\OAuthSignatureInterface'),
                $app->make('Vinelab\Auth\Social\Providers\Twitter\Contracts\OAuthConsumerInterface')
            );
        });

        $this->app->bind('Vinelab\Auth\Contracts\ProfileInterface', 'Vinelab\Auth\Social\Profile');

        $this->app->bind(
            'Vinelab\Auth\Social\Providers\Facebook\Contracts\AccessTokenInterface',
            'Vinelab\Auth\Social\Providers\Facebook\AccessToken');

        // Expose the Facade
        $this->app->bind('vinelab.socialauth', function (App $app) {
            return new Auth($app->make('config'),
                            $app->make('redirect'),
                            $app->make('vinelab.httpclient'),
                            $app->make('Vinelab\Auth\Contracts\ProvidersManagerInterface'));
        });

        $this->app->booting(function () {
            $loader = \Illuminate\Foundation\AliasLoader::getInstance();
            $loader->alias('SocialAuth', 'Vinelab\Auth\Facades\Auth');
        });
    }

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


<?php

namespace CottaCush\Yii2\OauthClient;

use CottaCush\Yii2\OauthClient\Exceptions\Oauth2ClientException;
use linslin\yii2\curl\Curl;
use yii\authclient\OAuth2;
use yii\authclient\OAuthToken;
use yii\base\Exception;
use yii\base\InvalidParamException;
use yii\helpers\ArrayHelper;

/**
 * Class Oauth2Client
 * @property Curl $curl
 * @package app\libs
 * @author Adegoke Obasa <goke@cottacush.com>
 */
class Oauth2Client
{
    const DEFAULT_ERROR = 'An error occurred';
    const CODE_NOT_SET = 'Code not set';
    const INVALID_AUTH_URL = 'Invalid auth url %s';
    const INVALID_TOKEN_URL = 'Invalid token url %s';
    const INVALID_CLIENT_ID = 'Invalid client ID';
    const INVALID_CLIENT_SECRET = 'Invalid client secret';
    const GRANT_TYPE_AUTHORIZATION_CODE = 'authorization_code';
    const RESPONSE_TYPE_CODE = 'code';
    const STATE_ALIVE = 'alive';
    const AUTH_URL = 'authUrl';
    const TOKEN_URL = 'tokenUrl';
    const CLIENT_ID = 'clientId';
    const CLIENT_SECRET = 'clientSecret';
    const GRANT_TYPE_CLIENT_CREDENTIALS = 'client_credentials';

    protected $clientId;
    protected $clientSecret;
    protected $authUrl;
    protected $tokenUrl;
    /**
     * @var OAuth2 $oauth2
     */
    protected $oauth2;
    /**
     * @var Curl $curl
     */
    protected $curl;

    /**
     * Oauth2Client constructor.
     * @author Adegoke Obasa <goke@cottacush.com>
     * @param array $params
     */
    public function __construct($params = [])
    {
        $this->setDefaultParams($params);
        $this->oauth2 = new OAuth2();
        $this->curl = new Curl();
    }

    /**
     * Handles authorize request response
     * @author Adegoke Obasa <goke@cottacush.com>
     * @param $response
     * @return mixed
     * @throws Oauth2ClientException
     */
    private function handleAuthorizeResponse($response)
    {
        $status = ArrayHelper::getValue($response, 'status');

        if (!is_null($status) && $status == 'success') {
            $code = ArrayHelper::getValue($response, 'data.code');
            if (is_null($code)) {
                throw new Oauth2ClientException(self::CODE_NOT_SET);
            }
            return $code;
        } else {
            $message = ArrayHelper::getValue($response, 'message', self::DEFAULT_ERROR);
            throw new Oauth2ClientException($message);
        }
    }

    /**
     * Authorizes and returns authorization code
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return mixed code
     * @throws Oauth2ClientException
     * @throws InvalidParamException
     */
    public function authorize()
    {
        $this->validateAuthParams();
        try {
            $response = $this->curl->setOption(
                CURLOPT_POSTFIELDS,
                http_build_query(array(
                    'grant_type' => self::GRANT_TYPE_AUTHORIZATION_CODE,
                    'client_id' => $this->clientId,
                    'client_secret' => $this->clientSecret,
                    'response_type' => self::RESPONSE_TYPE_CODE,
                    'state' => self::STATE_ALIVE
                ))
            )->post($this->authUrl, false);
        } catch (InvalidParamException $invalidParamException) {
            throw new Oauth2ClientException($invalidParamException->getMessage());
        }
        return $this->handleAuthorizeResponse($response);
    }

    /**
     * @author Akinwunmi Taiwo <taiwo@cottacush.com>
     * @return mixed
     * @throws Oauth2ClientException
     */
    public function fetchAccessTokenWithClientCredentials()
    {
        $this->validateTokenParams();
        try {
            $response = $this->curl->setOption(
                CURLOPT_POSTFIELDS,
                http_build_query(array(
                    'grant_type' => self::GRANT_TYPE_CLIENT_CREDENTIALS,
                    'client_id' => $this->clientId,
                    'client_secret' => $this->clientSecret
                ))
            )->post($this->tokenUrl, false);
        } catch (InvalidParamException $invalidParamException) {
            throw new Oauth2ClientException($invalidParamException->getMessage());
        }

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

    /**
     * Handles token request response
     * @author Adegoke Obasa <goke@cottacush.com>
     * @param OAuthToken $response
     * @return mixed
     * @throws Oauth2ClientException
     */
    private function handleTokenResponse($response)
    {
        $params = ($response instanceof OAuthToken) ? $response->getParams() : $response;
        $status = ArrayHelper::getValue($params, 'status');
        if (!is_null($status) && $status == 'success') {
            $token = ArrayHelper::getValue($params, 'data');
            if (is_null($token)) {
                throw new Oauth2ClientException(self::CODE_NOT_SET);
            }
            return $token;
        } else {
            $message = ArrayHelper::getValue($params, 'message', self::DEFAULT_ERROR);
            throw new Oauth2ClientException($message);
        }
    }

    /**
     * Fetches the access token using the authorization code
     * @author Adegoke Obasa <goke@cottacush.com>
     * @param $code
     * @return mixed Access token
     * @throws Oauth2ClientException
     */
    public function fetchAccessToken($code)
    {
        $this->validateTokenParams();

        $this->oauth2->tokenUrl = $this->tokenUrl;
        $this->oauth2->clientId = $this->clientId;
        $this->oauth2->clientSecret = $this->clientSecret;

        try {
            $response = $this->oauth2->fetchAccessToken($code);
        } catch (Exception $ex) {
            throw new Oauth2ClientException($ex->getMessage());
        }
        return $this->handleTokenResponse($response);
    }

    /**
     * Validates params for the authorization request
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return bool
     * @throws Oauth2ClientException
     */
    protected function validateAuthParams()
    {
        if (empty($this->authUrl) || filter_var($this->authUrl, FILTER_VALIDATE_URL) === false) {
            throw new Oauth2ClientException(sprintf(self::INVALID_AUTH_URL, $this->authUrl));
        }

        if (empty($this->clientId)) {
            throw new Oauth2ClientException(self::INVALID_CLIENT_ID);
        }

        if (empty($this->clientSecret)) {
            throw new Oauth2ClientException(self::INVALID_CLIENT_SECRET);
        }

        return true;
    }

    /**
     * Validates params for the token request
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return bool
     * @throws Oauth2ClientException
     */
    protected function validateTokenParams()
    {
        if (empty($this->tokenUrl) || filter_var($this->tokenUrl, FILTER_VALIDATE_URL) === false) {
            throw new Oauth2ClientException(sprintf(self::INVALID_TOKEN_URL, $this->tokenUrl));
        }

        if (empty($this->clientId)) {
            throw new Oauth2ClientException(self::INVALID_CLIENT_ID);
        }

        if (empty($this->clientSecret)) {
            throw new Oauth2ClientException(self::INVALID_CLIENT_SECRET);
        }

        return true;
    }

    /**
     *
     * @author Adegoke Obasa <goke@cottacush.com>
     * @param $params
     */
    private function setDefaultParams($params)
    {
        $this->authUrl = ArrayHelper::getValue($params, self::AUTH_URL);
        $this->tokenUrl = ArrayHelper::getValue($params, self::TOKEN_URL);
        $this->clientId = ArrayHelper::getValue($params, self::CLIENT_ID);
        $this->clientSecret = ArrayHelper::getValue($params, self::CLIENT_SECRET);
    }

    /**
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return mixed
     */
    public function getClientId()
    {
        return $this->clientId;
    }

    /**
     * @author Adegoke Obasa <goke@cottacush.com>
     * @param mixed $clientId
     */
    public function setClientId($clientId)
    {
        $this->clientId = $clientId;
    }

    /**
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return mixed
     */
    public function getClientSecret()
    {
        return $this->clientSecret;
    }

    /**
     * @author Adegoke Obasa <goke@cottacush.com>
     * @param mixed $clientSecret
     */
    public function setClientSecret($clientSecret)
    {
        $this->clientSecret = $clientSecret;
    }

    /**
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return mixed
     */
    public function getAuthUrl()
    {
        return $this->authUrl;
    }

    /**
     * @author Adegoke Obasa <goke@cottacush.com>
     * @param mixed $authUrl
     */
    public function setAuthUrl($authUrl)
    {
        $this->authUrl = $authUrl;
    }

    /**
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return mixed
     */
    public function getTokenUrl()
    {
        return $this->tokenUrl;
    }

    /**
     * @author Adegoke Obasa <goke@cottacush.com>
     * @param mixed $tokenUrl
     */
    public function setTokenUrl($tokenUrl)
    {
        $this->tokenUrl = $tokenUrl;
    }

    /**
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return OAuth2
     */
    public function getOauth2()
    {
        return $this->oauth2;
    }

    /**
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return Curl
     */
    public function getCurl()
    {
        return $this->curl;
    }

    /**
     * Returns the access token
     * @author Adegoke Obasa <goke@cottacush.com>
     * @return mixed
     */
    public static function getAccessToken()
    {
        $oauthClientParams = ArrayHelper::getValue(\Yii::$app->params, 'oauth');
        $oauthClient = new Oauth2Client($oauthClientParams);
        $code = $oauthClient->authorize();
        $token = $oauthClient->fetchAccessToken($code);
        $accessToken = ArrayHelper::getValue($token, 'access_token');
        return $accessToken;
    }
}


<?php
/**
 * Custom Rating Grifus · Extensions For Grifus
 *
 * @author    Josantonius <hello@josantonius.com>
 * @package   Josantonius/Custom-Rating-Grifus
 * @copyright 2017 - 2018 (c) Josantonius - Custom Rating Grifus
 * @license   GPL-2.0+
 * @link      https://github.com/eliasis-framework/custom-rating-grifus.git
 * @since     1.0.0
 */

namespace EFG\Modules\CustomRatingGrifus\Model\Admin;

use Eliasis\Framework\Model;

/**
 * Rating model.
 */
class Rating extends Model {

	/**
	 * Get theme options.
	 *
	 * @since 1.0.1
	 *
	 * @return array
	 */
	public function get_theme_options() {

		return [
			'enable-dark' => get_option( 'activar-dark' ),
		];
	}

	/**
	 * Get movie votes.
	 *
	 * @since 1.0.1
	 *
	 * @param string $post_id → post id.
	 *
	 * @return array|false → votes
	 */
	public function get_movie_votes( $post_id ) {

		$votes = get_post_meta( $post_id, 'imdbTotalVotes', true );

		if ( ! empty( $votes ) ) {
			return json_decode( $votes, true );
		}

		return false;
	}

	/**
	 * Set movie votes.
	 *
	 * @since 1.0.1
	 *
	 * @param string $post_id     → post id.
	 * @param int    $total_votes → number of total votes.
	 */
	public function set_movie_votes( $post_id, $total_votes ) {

		$total_votes = $total_votes ?: 'N/B';

		if ( ! add_post_meta( $post_id, 'imdbVotes', $total_votes, true ) ) {
			update_post_meta( $post_id, 'imdbVotes', $total_votes );
		}
	}

	/**
	 * Set total votes.
	 *
	 * @since 1.0.1
	 *
	 * @param string $post_id → post id.
	 * @param array  $votes  → votes.
	 */
	public function set_total_votes( $post_id, $votes ) {

		$votes = json_encode( $votes, true );

		if ( ! add_post_meta( $post_id, 'imdbTotalVotes', $votes, true ) ) {
			update_post_meta( $post_id, 'imdbTotalVotes', $votes );
		}
	}

	/**
	 * Set movie rating.
	 *
	 * @param string    $post_id  → post id.
	 * @param int|float $rating  → movie rating.
	 */
	public function set_movie_rating( $post_id, $rating ) {

		if ( ! add_post_meta( $post_id, 'imdbRating', $rating, true ) ) {
			update_post_meta( $post_id, 'imdbRating', $rating );
		}
	}

	/**
	 * Add or update vote and associate to an IP address.
	 *
	 * @since 1.0.1
	 *
	 * @param string $post_id → post id.
	 * @param array  $votes  → votes.
	 * @param array  $vote   → vote.
	 * @param array  $ip     → ip.
	 *
	 * @return array → movie votes
	 */
	public function set_user_vote( $post_id, $votes, $vote, $ip ) {

		global $wpdb;

		$table_name = $wpdb->prefix . 'efg_custom_rating';

		$result = $wpdb->get_row(
			"
            SELECT id, vote
            FROM   $table_name
            WHERE  ip      = '$ip'
            AND    post_id = $post_id
        "
		);

		if ( ! isset( $result->id ) && ! isset( $result->vote ) ) {

			$wpdb->insert(
				$table_name,
				[
					'post_id' => $post_id,
					'ip' => $ip,
					'vote' => $vote,
				],
				[ '%d', '%s', '%d' ]
			);

			$votes[ $vote ]++;

		} else {

			if ( $result->vote != $vote ) {

				$wpdb->update(
					$table_name,
					[
						'post_id' => $post_id,
						'ip' => $ip,
						'vote' => $vote,
					],
					[ 'id' => $result->id ],
					[ '%d', '%s', '%d' ],
					[ '%d' ]
				);

				$votes[ $result->vote ]--;
				$votes[ $vote ]++;
			}
		}

		return $votes;
	}

	/**
	 * Get publish posts.
	 *
	 * @since 1.0.1
	 *
	 * @return array → posts
	 */
	public function get_posts() {

		$total_posts = wp_count_posts();
		$total_posts = isset( $total_posts->publish ) ? $total_posts->publish : 0;

		return get_posts(
			[
				'post_type'   => 'post',
				'numberposts' => $total_posts,
				'post_status' => 'publish',
			]
		);
	}

	/**
	 * Set state for restart when added a movie.
	 *
	 * @since 1.0.1
	 *
	 * @param string  $slug  → module slug.
	 * @param boolean $state → restart when added a movie.
	 */
	public function set_restart_when_add( $slug, $state ) {

		update_option( $slug . '-restart-when-add', $state );
	}
}


<?php

namespace CottaCush\Yii2\Action;

use CottaCush\Yii2\Controller\BaseController;
use yii\base\Action;
use yii\db\ActiveRecord;
use yii\web\Response;

class BaseAction extends Action
{
    /** @var ActiveRecord $model */
    public $model;

    public $postData;
    public $returnUrl = '';

    public $recordNotFound = 'Record not found';
    public $errorMessage = '';
    public $successMessage = '';

    /** @var bool Checks if the login is required before action is executed */
    public $requireLogin = true;

    /**
     * @author Olawale Lawal <wale@cottacush.com>
     * @return bool|\yii\web\Response
     */
    public function beforeRun()
    {
        if (!$this->requireLogin) {
            return true;
        }

        /** @var BaseController $controller */
        $controller = $this->controller;
        /** @var /yii/web/Response $response */
        $response = $controller->loginRequireBeforeAction();

        if ($response instanceof Response) {
            $response->send();
            return false;
        }

        return true;
    }

    /**
     * Process message that contains callback
     * @author Olawale Lawal <wale@cottacush.com>
     * @param $message
     */
    protected function processMessage(&$message)
    {
        if (!$message instanceof \Closure) {
            return;
        }

        $callback = $message;
        $message = $callback($this->model);
    }
}


<?php

namespace Circuit;

use Circuit\Interfaces\Middleware;
use Circuit\Interfaces\ParameterDereferencer;
use Circuit\Interfaces\ExceptionHandler;
use Circuit\Interfaces\Delegate;
use Circuit\Exception;
use FastRoute\Dispatcher;
use Psr\SimpleCache\CacheInterface as Psr16;
use Psr\Cache\CacheItemPoolInterface as Psr6;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Psr\Log\LoggerInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerAwareTrait;
use Psr\Container\ContainerInterface as Container;

/**
 * Circuit - FastRoute + Middleware
 *
 * An implementation of nikic\FastRoute, with added capability of pre and post route middleware,
 * modelled after PSR-15 but using HTTP Foundation Request/Response objects as well as support for
 * PSR 6 and PSR 16 based caching solutions.
 *
 * @author Nik Barham <nik@brokencube.co.uk>
 */
class Router implements Delegate, LoggerAwareInterface
{
    use LoggerAwareTrait;

    const CACHE_KEY = 'routes_v3';

    /** @var mixed[] Various options as defined by FastRoute */
    protected $options = [];

    /** @var mixed Router Collector - Concrete class defined by options. */
    protected $routeCollection;

    /** @var float Timer for debug logging purposes */
    protected $stopwatch;

    /** @var CacheWrapper PSR6/16 compatible cache item */
    protected $cache;

    /** @var bool Did we pull results from cache i.e. do we need to call the RouteCollector callback */
    protected $cached = false;

    /** @var ExceptionHandler[] List of exception handlers for particular HTTP codes */
    public $exceptionHandlers = [];

    /** @var ExceptionHandler|null Default Exception Handler */
    public $defaultExceptionHandler = null;

    /** @var mixed[] List of arguments passed to Controller constructor */
    protected $controllerArgs = [];

    /** @var Middleware[] List of registered middlewares on this router */
    protected $namedMiddleware = [];

    /** @var array List of middlewares to run before matching routes */
    protected $prerouteMiddleware = [null];

    /**
     * Create a new Router
     * See https://github.com/nikic/FastRoute for more details
     *
     * @param array $options Option overrides
     * @param Psr16|Psr6 $cache A PSR-6 or PSR-16 compatible Cache object
     */
    public function __construct(array $options = [], $cache = null, LoggerInterface $logger = null)
    {
        $this->options = $options + [
            'routeParser' => 'FastRoute\\RouteParser\\Std',
            'dataGenerator' => 'FastRoute\\DataGenerator\\GroupCountBased',
            'dispatcher' => 'FastRoute\\Dispatcher\\GroupCountBased',
            'routeCollector' => 'Circuit\\RouteCollector',
            'cacheTimeout' => 3600
        ];
        $this->logger = $logger;
        $this->cache = $cache ? new CacheWrapper($cache) : null;
        $this->routeCollection = $this->cache ? $this->cache->get(static::CACHE_KEY) : null;

        if ($this->routeCollection) {
            $this->cached = true;
        } else {
            $this->routeCollection = new $this->options['routeCollector'](
                new $this->options['routeParser'], new $this->options['dataGenerator']
            );
        }
    }

    /**
     * Define routes using a routerCollector
     * See https://github.com/nikic/FastRoute for more details
     *
     * @param callable $definitionCallback Callback that will define the routes
     * @return self
     */
    public function defineRoutes(callable $definitionCallback)
    {
        if (!$this->cached) {
            $definitionCallback($this->routeCollection);
            // Cache
            if ($this->cache) {
                $this->cache->set(static::CACHE_KEY, $this->routeCollection, $this->options['cacheTimeout']);
            }
        }

        $this->dispatcher = new $this->options['dispatcher']($this->routeCollection->getData());
        return $this;
    }

    /**
     * Execute a route
     *
     * @param Request $request Request object for current process
     */
    public function run(Request $request)
    {
        $this->stopwatch = microtime(true);
        $starttime = $request->server->get('REQUEST_TIME_FLOAT');

        $this->log("Router: ->run() called. Starting clock at REQUEST_TIME+%.2fms", microtime(true) - $starttime);
        try {
            $response = $this->process($request);
        } catch (\Throwable $e) {
            $this->log("Router: Exception");
            $response = $this->handleException($e, $request);
        }

        $this->log("Router: Preparing to send response");
        $response->prepare($request);
        $response->send();
        $this->log("Router: Response sent");
    }

    /**
     * Process a route
     * Will call pre-route middleware, then match route and execute that route (more middleware + controller)
     *
     * @param Request $request Request object for current process
     * @return Response Response to http request ready for dispatch
     */
    public function process(Request $request) : Response
    {
        // Try and run the next middleware
        $next = next($this->prerouteMiddleware);
        if ($next instanceof Middleware) {
            $this->log("Router: Calling Middleware: %s", get_class($next));
            $response = $next->process($request, $this);
            $this->log("Router: Leaving Middleware: %s", get_class($next));
            return $response;
        } elseif (is_string($next)) {
            $this->log("Router: Calling Middleware: %s", $next);
            $response = $this->getMiddleware($next)->process($request, $this);
            $this->log("Router: Leaving Middleware: %s", $next);
            return $response;
        } else {
            // Null byte poisoning protection
            list($uri) = explode('?', str_replace(chr(0), '', $request->server->get('REQUEST_URI')));
            $dispatch = $this->dispatcher->dispatch($request->server->get('REQUEST_METHOD'), $uri);
            switch ($dispatch[0]) {
                case Dispatcher::NOT_FOUND:
                    $this->log("Router: Route not matched");
                    throw new Exception\NotFound('Router: Route not matched');

                case Dispatcher::METHOD_NOT_ALLOWED:
                    $this->log("Router: Method not Allowed");
                    throw new Exception\MethodNotAllowed(
                        $dispatch[1],
                        'Router: Method not Allowed: ' . $request->getMethod()
                    );

                case Dispatcher::FOUND:
                    $dispatcher = unserialize($dispatch[1]);
                    $this->log(
                        "Router: Route matched: %s@%s",
                        $dispatcher->controllerClass,
                        $dispatcher->controllerMethod
                    );
                    return $dispatcher->startProcessing($this, $request, $uri, $dispatch[2]);
            }
        }
    }

    /**
     * Handle an exception during processing of route.
     *
     * @param Throwable $e The Exception / Error thrown.
     * @param Request $request The request that caused the exception.
     * @return Response The response to the exception (e.g. error page)
     */
    protected function handleException(\Throwable $e, Request $request) : Response
    {
        // Wrap non HTTP exception/errors
        if (!$e instanceof Exception\Exception) {
            $e = new Exception\UncaughtException($e);
        }

        // Throw to an appropriate handler
        $code = $e->getStatusCode();
        if ($this->exceptionHandlers[$code] instanceof ExceptionHandler) {
            return $this->exceptionHandlers[$code]->handle($e, $request);
        } elseif ($this->defaultExceptionHandler instanceof ExceptionHandler) {
            return $this->defaultExceptionHandler->handle($e, $request);
        } else {
            return (new \Circuit\ExceptionHandler\DefaultHandler)->handle($e, $request);
        }
    }

    /**
     * Set arguments that will be passed to the constructor for any controllers invoked
     *
     * @param Psr\Container\ContainerInterface $container Service container passed to controller constructor
     * @return self
     */
    public function setServiceContainer(Container $container)
    {
        $this->container = $container;
        return $this;
    }

    /**
     * Get arguments that will be passed to the constructor for any controllers invoked
     *
     * @return Psr\Container\ContainerInterface Service container passed to controller constructor
     */
    public function getServiceContainer()
    {
        return $this->container;
    }

    /**
     * Register a middleware against a name.
     * This allows middleware to be created on startup and then refered to in serialised/cached route table
     *
     * @param string $name Unique name for middleware instance
     * @param Middleware $middleware Middleware object
     * @return self
     */
    public function registerMiddleware($name, Middleware $middleware)
    {
        $this->namedMiddleware[$name] = $middleware;
        return $this;
    }

    /**
     * Retrieve a middleware by name.
     *
     * @param string $name Name of middleware set by ->registerMiddleware($name)
     * @throws UnexpectedValueException For unrecognised names
     * @return Middleware The referenced middleware instance
     */
    public function getMiddleware($name) : Middleware
    {
        if (!array_key_exists($name, $this->namedMiddleware)) {
            throw new \UnexpectedValueException("No middleware registered under name '{$name}'");
        }
        return $this->namedMiddleware[$name];
    }

    /**
     * Add a middleware that will be run before routes are matched
     *
     * @param mixed $middleware Middleware object or named middleware (via ->registerMiddleware($name))
     * @return self
     */
    public function addPrerouteMiddleware($middleware)
    {
        $this->prerouteMiddleware[] = $middleware;
        return $this;
    }

    /**
     * Register an exception handler for a particular HTTP code.
     *
     * @param string $code HTTP code handler is responsible for
     * @param ExceptionHandler $hander Handler
     * @return self
     */
    public function setExceptionHandler($code, ExceptionHandler $handler)
    {
        $this->exceptionHandlers[$code] = $handler;
        return $this;
    }

    /**
     * Register an exception handler for a particular HTTP code.
     *
     * @param string $code HTTP code handler is responsible for
     * @param ExceptionHandler $hander Handler
     * @return self
     */
    public function setDefaultExceptionHandler(ExceptionHandler $handler)
    {
        $this->defaultExceptionHandler = $handler;
        return $this;
    }

    /**
     * Log a debug message, and append time elapsed since ->run() was called
     *
     * @param string $message sprintf compatible string
     * @param mixed[] $args Data to pass to sprintf
     * @return self
     */
    public function log($message, ...$args)
    {
        if ($this->logger) {
            $args[] = $this->stopwatch ? microtime(true) - $this->stopwatch : 0;
            $this->logger->debug(sprintf($message . ' (%.2fs)', ...$args));
        }
        return $this;
    }
}