PHP Classes
elePHPant
Icontem

File: src/Plugin/Manager.php

Recommend this page to a friend!
  Classes of Thierry Feuzeu  >  Jaxon  >  src/Plugin/Manager.php  >  Download  
File: src/Plugin/Manager.php
Role: Class source
Content type: text/plain
Description: Class source
Class: Jaxon
Call PHP classes from JavaScript using AJAX
Author: By
Last change: Added a new attribute in the Package class.
Date: 2 months ago
Size: 11,037 bytes
 

 

Contents

Class file image Download
<?php

/**
 * Manager.php - Jaxon plugin manager
 *
 * Register Jaxon plugins, generate corresponding code, handle request
 * and redirect them to the right plugin.
 *
 * @package jaxon-core
 * @author Jared White
 * @author J. Max Wilson
 * @author Joseph Woolley
 * @author Steffen Konerow
 * @author Thierry Feuzeu <thierry.feuzeu@gmail.com>
 * @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
 * @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White  & J. Max Wilson
 * @copyright 2016 Thierry Feuzeu <thierry.feuzeu@gmail.com>
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
 * @link https://github.com/jaxon-php/jaxon-core
 */

namespace Jaxon\Plugin;

use Jaxon\Jaxon;
use Jaxon\Plugin\Package;
use Jaxon\Plugin\Code\Generator as CodeGenerator;
use Jaxon\Request\Support\CallableRepository;
use Jaxon\Request\Plugin\CallableClass;
use Jaxon\Request\Plugin\CallableDir;
use Jaxon\Request\Plugin\CallableFunction;
use Jaxon\Request\Plugin\FileUpload;
use Jaxon\Response\Plugin\JQuery as JQueryPlugin;
use Jaxon\Utils\Config\Config;

use Closure;

class Manager
{
    use \Jaxon\Features\Manager;
    use \Jaxon\Features\Config;
    use \Jaxon\Features\Event;
    use \Jaxon\Features\Translator;

    /**
     * Request plugins, indexed by name
     *
     * @var array
     */
    private $aRequestPlugins = [];

    /**
     * Response plugins, indexed by name
     *
     * @var array
     */
    private $aResponsePlugins = [];

    /**
     * The code generator
     *
     * @var CodeGenerator
     */
    private $xCodeGenerator;

    /**
     * The constructor
     *
     * @param CodeGenerator     $xCodeGenerator
     */
    public function __construct(CodeGenerator $xCodeGenerator)
    {
        $this->xCodeGenerator = $xCodeGenerator;
    }

    /**
     * Get the request plugins
     *
     * @return array
     */
    public function getRequestPlugins()
    {
        return $this->aRequestPlugins;
    }

    /**
     * Get the response plugins
     *
     * @return array
     */
    public function getResponsePlugins()
    {
        return $this->aResponsePlugins;
    }

    /**
     * Get a package instance
     *
     * @param string        $sClassName           The package class name
     *
     * @return Package
     */
    public function getPackage($sClassName)
    {
        $sClassName = trim($sClassName, '\\ ');
        return jaxon()->di()->get($sClassName);
    }

    /**
     * Register a plugin
     *
     * Below is a table for priorities and their description:
     * - 0 thru 999: Plugins that are part of or extensions to the jaxon core
     * - 1000 thru 8999: User created plugins, typically, these plugins don't care about order
     * - 9000 thru 9999: Plugins that generally need to be last or near the end of the plugin list
     *
     * @param Plugin         $xPlugin               An instance of a plugin
     * @param integer        $nPriority             The plugin priority, used to order the plugins
     *
     * @return void
     */
    public function registerPlugin(Plugin $xPlugin, $nPriority = 1000)
    {
        $bIsUsed = false;
        if($xPlugin instanceof Request)
        {
            // The name of a request plugin is used as key in the plugin table
            $this->aRequestPlugins[$xPlugin->getName()] = $xPlugin;
            $this->xCodeGenerator->addGenerator($xPlugin, $nPriority);
            $bIsUsed = true;
        }
        elseif($xPlugin instanceof Response)
        {
            // The name of a response plugin is used as key in the plugin table
            $this->aResponsePlugins[$xPlugin->getName()] = $xPlugin;
            $this->xCodeGenerator->addGenerator($xPlugin, $nPriority);
            $bIsUsed = true;
        }

        // This plugin implements the Message interface
        if($xPlugin instanceof \Jaxon\Contracts\Dialogs\Message)
        {
            jaxon()->dialog()->setMessage($xPlugin);
            $bIsUsed = true;
        }
        // This plugin implements the Question interface
        if($xPlugin instanceof \Jaxon\Contracts\Dialogs\Question)
        {
            jaxon()->dialog()->setQuestion($xPlugin);
            $bIsUsed = true;
        }
        // Register the plugin as an event listener
        if($xPlugin instanceof \Jaxon\Contracts\Event\Listener)
        {
            $this->addEventListener($xPlugin);
            $bIsUsed = true;
        }

        if(!$bIsUsed)
        {
            $sErrorMessage = $this->trans('errors.register.invalid', ['name' => get_class($xPlugin)]);
            throw new \Jaxon\Exception\Error($sErrorMessage);
        }
    }

    /**
     * Register a package
     *
     * @param string        $sClassName           The package class name
     * @param array         $aOptions           The package options
     *
     * @return void
     */
    public function registerPackage($sClassName, array $aOptions)
    {
        $sClassName = trim($sClassName, '\\ ');
        $jaxon = jaxon();
        $jaxon->di()->set($sClassName, function($di) use($sClassName, $aOptions) {
            $xPackage = $di->make($sClassName);
            // Set the package options
            $cSetter = function($_aOptions) {
                $this->aOptions = $_aOptions;
                $this->xConfig = jaxon()->di()->newConfig($_aOptions);
            };
            // Can now access protected attributes
            \call_user_func($cSetter->bindTo($xPackage, $xPackage), $aOptions);
            return $xPackage;
        });

        // Read and apply the package config.
        $aPackageConfig = $jaxon->config()->read($sClassName::getConfigFile());
        $xPackageConfig = $jaxon->di()->newConfig($aPackageConfig);
        $this->_registerFromConfig($xPackageConfig);
        // Register the view namespaces
        $jaxon->di()->getViewManager()->addNamespaces($xPackageConfig);
        // Register the package as a code generator.
        $xPackage = $this->getPackage($sClassName);
        $this->xCodeGenerator->addGenerator($xPackage, 500);
    }

    /**
     * Register a function or callable class
     *
     * Call the request plugin with the $sType defined as name.
     *
     * @param string        $sType          The type of request handler being registered
     * @param string        $sCallable      The callable entity being registered
     * @param array|string  $aOptions       The associated options
     *
     * @return void
     */
    public function registerCallable($sType, $sCallable, $aOptions = [])
    {
        if(!key_exists($sType, $this->aRequestPlugins))
        {
            throw new \Jaxon\Exception\Error($this->trans('errors.register.plugin', ['name' => $sType]));
        }

        $xPlugin = $this->aRequestPlugins[$sType];
        $xPlugin->register($sType, $sCallable, $aOptions);
    }

    /**
     * Register callables from a section of the config
     *
     * @param Config        $xAppConfig        The config options
     * @param string        $sSection          The config section name
     * @param string        $sCallableType     The type of callable to register
     *
     * @return void
     */
    private function registerCallablesFromConfig(Config $xAppConfig, $sSection, $sCallableType)
    {
        $aConfig = $xAppConfig->getOption($sSection, []);
        foreach($aConfig as $xKey => $xValue)
        {
            if(is_integer($xKey) && is_string($xValue))
            {
                // Register a function without options
                $this->registerCallable($sCallableType, $xValue);
            }
            elseif(is_string($xKey) && (is_array($xValue) || is_string($xValue)))
            {
                // Register a function with options
                $this->registerCallable($sCallableType, $xKey, $xValue);
            }
            else
            {
                continue;
                // Todo: throw an exception
            }
        }
    }

    /**
     * Read and set Jaxon options from a JSON config file
     *
     * @param Config        $xAppConfig        The config options
     *
     * @return void
     */
    private function _registerFromConfig(Config $xAppConfig)
    {
        // Register functions
        $this->registerCallablesFromConfig($xAppConfig, 'functions', Jaxon::CALLABLE_FUNCTION);

        // Register classes
        $this->registerCallablesFromConfig($xAppConfig, 'classes', Jaxon::CALLABLE_CLASS);

        // Register directories
        $this->registerCallablesFromConfig($xAppConfig, 'directories', Jaxon::CALLABLE_DIR);

        // Register classes in DI container
        $di = jaxon()->di();
        $aContainerConfig = $xAppConfig->getOption('container', []);
        foreach($aContainerConfig as $sClassName => $xClosure)
        {
            $di->set($sClassName, $xClosure);
        }
    }

    /**
     * Read and set Jaxon options from a JSON config file
     *
     * @param Config        $xAppConfig        The config options
     *
     * @return void
     */
    public function registerFromConfig(Config $xAppConfig)
    {
        $this->_registerFromConfig($xAppConfig);

        // Register packages
        $aPackageConfig = $xAppConfig->getOption('packages', []);
        foreach($aPackageConfig as $sClassName => $aOptions)
        {
            $this->registerPackage($sClassName, $aOptions);
        }
    }


    /**
     * Find the specified response plugin by name and return a reference to it if one exists
     *
     * @param string        $sName                The name of the plugin
     *
     * @return \Jaxon\Plugin\Response
     */
    public function getResponsePlugin($sName)
    {
        if(array_key_exists($sName, $this->aResponsePlugins))
        {
            return $this->aResponsePlugins[$sName];
        }
        return null;
    }

    /**
     * Find the specified request plugin by name and return a reference to it if one exists
     *
     * @param string        $sName                The name of the plugin
     *
     * @return \Jaxon\Plugin\Request
     */
    public function getRequestPlugin($sName)
    {
        if(array_key_exists($sName, $this->aRequestPlugins))
        {
            return $this->aRequestPlugins[$sName];
        }
        return null;
    }

    /**
     * Register the Jaxon request plugins
     *
     * @return void
     */
    public function registerRequestPlugins()
    {
        $di = jaxon()->di();
        $this->registerPlugin($di->get(CallableClass::class), 101);
        $this->registerPlugin($di->get(CallableDir::class), 102);
        $this->registerPlugin($di->get(CallableFunction::class), 103);
        $this->registerPlugin($di->get(FileUpload::class), 104);
    }

    /**
     * Register the Jaxon response plugins
     *
     * @return void
     */
    public function registerResponsePlugins()
    {
        $di = jaxon()->di();
        // Register an instance of the JQuery plugin
        $this->registerPlugin($di->get(JQueryPlugin::class), 700);
    }
}