<?php
/**
 * YANA library
 *
 * Software:  Yana PHP-Framework
 * Version:   {VERSION} - {DATE}
 * License:   GNU GPL  http://www.gnu.org/licenses/
 *
 * This program: can be redistributed and/or modified under the
 * terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/.
 *
 * This notice MAY NOT be removed.
 *
 * @package  yana
 * @license  http://www.gnu.org/licenses/gpl.txt
 */

/**
 * Plugin configurator for creating manual plugin methods
 *
 * @access     public
 * @package    yana
 * @subpackage plugins
 */
class PluginMethodConfigurator extends PluginConfigurationMethod
{
    /**
     * is auto-generated method
     *
     * true = yes, false = no
     *
     * @access  private
     * @var     bool
     */
    private $_isAutoGenerated = false;

    /**
     * Constructor
     *
     * @access  public
     * @param   PluginReflectionMethod  $method  method reflection
     * @param   PluginReflectionClass   $class   class reflection
     */
    public function __construct(PluginReflectionMethod $method = null, PluginReflectionClass $class = null)
    {
        if (!is_null($class)) {
            parent::__construct($method, $class);
        } else {
            $this->configuration = array
            (
                PluginAnnotation::TITLE => '',
                PluginAnnotation::TEXT => '',
                PluginAnnotation::PARAM => array(),
                PluginAnnotation::RETURN_VALUE => 'bool',
                PluginAnnotation::TYPE => 'default',
                PluginAnnotation::TEMPLATE => 'null',
                PluginAnnotation::USER => array()
            );
        }
    }

    /**
     * set name
     *
     * @access  public
     * @param   string  $name  plugin name
     */
    public function setTitle($name)
    {
        switch (true)
        {
            case !is_string($name):
            case mb_strlen($name) > 64:
            case !preg_match('/^[\d\w-_ äüöß\(\)]+$/si', $name):
                $error = array(
                    'FIELD' => 'NAME',
                    'VALUE' => print_r($name, true),
                    'VALID' => 'a-z, 0-9, -, _, ß, ä, ö, ü, " "'
                );
                throw new Error("INVALID_CHARACTERS", E_USER_ERROR, $error);
            break;
            default:
                $this->configuration[PluginAnnotation::TITLE] = $name;
                $this->methodName = preg_replace('/[^\d\w_]/', '_', mb_strtolower($name));
            break;
        }
    }

    /**
     * set type
     *
     * Valid types are: default, config, read, write, security
     *
     * @access  public
     * @param   string  $type  plugin type
     */
    public function setType($type)
    {
        $type = strtolower($type);
        switch ($type)
        {
            case 'primary':
            case 'default':
            case 'config':
            case 'read':
            case 'write':
            case 'security':
                $this->configuration[PluginAnnotation::TYPE] = $type;
            break;
            default:
                $error = array(
                    'FIELD' => 'TYPE',
                    'VALUE' => print_r($type, true),
                    'VALID' => 'primary, default, config, read, write, security, library'
                );
                throw new Error("INVALID_CHARACTERS", E_USER_ERROR, $error);
            break;
        }
    }

    /**
     * set description
     *
     * @access  public
     * @param   string  $text  text describing what the plug-in does
     */
    public function setText($text)
    {
        if (!is_string($text)) {
            throw new Error("INPUT_INVALID");
        }

        $this->configuration[PluginAnnotation::TEXT] = strip_tags($text);
    }

    /**
     * set template
     *
     * @access  public
     * @param   string  $template  id of template to use
     */
    public function setTemplate($template)
    {
        if (!is_string($template)) {
            throw new Error("INPUT_INVALID");
        }

        $this->configuration[PluginAnnotation::TEMPLATE] = strip_tags($template);
    }

    /**
     * set user levels
     *
     * @access  public
     * @param   string  $group  user group
     * @param   string  $role   user role
     * @param   int     $level  user level (0..100)
     */
    public function setUserLevels($group, $role, $level)
    {
        switch (true)
        {
            case !is_string($group):
            case !preg_match('/^[\d\w-_]*$/si', $group):
                $error = array(
                    'FIELD' => 'GROUP',
                    'VALUE' => print_r($group, true),
                    'VALID' => 'a-z, 0-9, -, _'
                );
                throw new Error("INVALID_CHARACTERS", E_USER_ERROR, $error);
            break;
            case !is_string($role):
            case !preg_match('/^[\d\w-_]*$/si', $role):
                $error = array(
                    'FIELD' => 'ROLE',
                    'VALUE' => print_r($role, true),
                    'VALID' => 'a-z, 0-9, -, _'
                );
                throw new Error("INVALID_CHARACTERS", E_USER_ERROR, $error);
            break;
            case !is_numeric($level):
            case $level < 0 || $level > 100:
                $error = array(
                    'FIELD' => 'LEVEL',
                    'VALUE' => print_r($level, true),
                    'VALID' => '0-100'
                );
                throw new Error("INVALID_CHARACTERS", E_USER_ERROR, $error);
            break;
            default:
                $this->configuration[PluginAnnotation::USER][] = array(
                    PluginAnnotation::GROUP => $group,
                    PluginAnnotation::ROLE => $role,
                    PluginAnnotation::LEVEL => (int) $level
                );
            break;
        }
    }

    /**
     * set menu
     *
     * @access  public
     * @param   string  $menu  name of menu
     */
    public function setMenu($menu)
    {
        if (!is_string($menu)) {
            throw new Error("INPUT_INVALID");
        }

        $this->configuration[PluginAnnotation::MENU] = array(
            PluginAnnotation::GROUP => $menu
        );
    }

    /**
     * set action to execute on success
     *
     * @access  public
     * @param   string  $action  name of action
     */
    public function setOnSuccess($action)
    {
        if (!is_string($action)) {
            throw new Error("INPUT_INVALID");
        }
        $this->configuration[PluginAnnotation::ONSUCCESS] = array(
            PluginAnnotation::GO => $action
        );
    }

    /**
     * set action to execute on error
     *
     * @access  public
     * @param   string  $action  name of action
     */
    public function setOnError($action)
    {
        if (!is_string($action)) {
            throw new Error("INPUT_INVALID");
        }
        $this->configuration[PluginAnnotation::ONERROR] = array(
            PluginAnnotation::GO => $action
        );
    }

    /**
     * set auto-generated
     *
     * Set to bool(true) if the method was created automatically by the
     * CRUD-page generator.
     *
     * @access  public
     * @param   bool  $isAutoGenerated  true = yes, false = no
     */
    public function setAutoGenerated($isAutoGenerated = true)
    {
        assert('is_bool($isAutoGenerated); // Wrong argument type argument 1. Boolean expected');
        $this->_isAutoGenerated = (bool) $isAutoGenerated;
    }

    /**
     * is auto-generated method
     *
     * Return bool(true) if the method was created automatically by the
     * CRUD-page generator and bool(false) otherwise.
     *
     * @access  public
     * @return  bool
     */
    public function isAutoGenerated()
    {
        return $this->_isAutoGenerated === true;
    }

    /**
     * convert to string
     *
     * Outputs the method head, including doc-comment.
     *
     * @access  public
     * @return  string
     */
    public function toString()
    {
        $tab = "\n     * ";
        $string = "    /**" . $tab;
        // head line
        if ($this->getName()) {
            $string .= $this->getName();
        } else {
            $string .= $this->getMethodName();
        }
        $string .= $tab; // empty line after title
        // description
        if ($this->getText()) {
            $text = $this->getText();
            preg_replace('/^/m', $tab, $text);
            $string .= $text . $tab;
        }
        // annotations
        if ($this->getSubscribe()) {
            $string .= $tab . "@subscribe";
        } else {
            if ($this->getOverwrite()) {
                $string .= $tab . "@overwrite";
            }
            if ($this->getType()) {
                $string .= $tab . "@type       " . $this->getType();
            }
            if ($this->getTemplate()) {
                $string .= $tab . "@template   " . $this->getTemplate();
            }
            foreach ($this->getStyles() as $item)
            {
                $string .= $tab . "@style      " . $item;
            }
            foreach ($this->getScripts() as $item)
            {
                $string .= $tab . "@script     " . $item;
            }
            foreach ($this->getLanguages() as $item)
            {
                $string .= $tab . "@language   " . $item;
            }
            if ($this->getMenu()) {
                $item = $this->getMenu();
                $string .= $tab . "@menu       ";
                while (current($item) !== false)
                {
                    $string .= key($item) . ": " . current($item);
                    if (next($item) !== false) {
                        $string .= ", ";
                    }
                }
            }
            foreach ($this->getUserLevels() as $item)
            {
                $string .= $tab . "@user       ";
                while (current($item) !== false)
                {
                    $string .= key($item) . ": " . current($item);
                    if (next($item) !== false) {
                        $string .= ", ";
                    }
                }
            }
            if ($this->getOnError()) {
                $item = $this->getOnError();
                $string .= $tab . "@onerror    ";
                while (current($item) !== false)
                {
                    $string .= key($item) . ": " . current($item);
                    if (next($item) !== false) {
                        $string .= ", ";
                    }
                }
            }
            if ($this->getOnSuccess()) {
                $item = $this->getOnSuccess();
                $string .= $tab . "@onsuccess  ";
                while (current($item) !== false)
                {
                    $string .= key($item) . ": " . current($item);
                    if (next($item) !== false) {
                        $string .= ", ";
                    }
                }
            }
            if ($this->getSafeMode()) {
                $string .= $tab . "@safemode    " . $this->getSafeMode();
            }
        }
        $string .= $tab . "@access   public";
        foreach ($this->getParams() as $name => $type)
        {
            $string .= $tab . "@param    " . $type . "  \$" . $name . "  " . $name;
        }
        if ($this->getReturn()) {
            $string .= $tab . "@return   " . $this->getReturn();
        }
        $string .= "\n     */\n    public function " . $this->getMethodName() . "(";
        $params = $this->getParams();
        while (current($params) !== false)
        {
            if (key($params) === 'array') {
                $string .= "array ";
            }
            $string .= '$' . current($params);
            if (next($params) !== false) {
                $string .= ", ";
            }
        }
        $string .= ")";
        return $string;
    }
}

?>