marcelog / Ding

DI ( Dependency Injection: Setter, Constructor, Method), AOP ( Aspect Oriented Programming ), Events support, xml, yaml, and annotations (including some JSR 250 and JSR 330, like @Configuration and @Bean ala java configuration) , lightweight, simple, and quick MVC ( Model View Controller ), syslog, tcp client and server, with non blocking sockets, custom error, signal, and exception handling through events. Needs PHP 5.3, very similar to seasar, spring ( java ) . Can be deployed as a PHAR file.
http://marcelog.github.com/Ding
Apache License 2.0
121 stars 26 forks source link

multi urls in controller #117

Closed ValeryDubrava closed 12 years ago

ValeryDubrava commented 12 years ago

Add possibility to set several urls for controller The code below

<?php

/**
 * A mapper implementation for http requests.
 *
 * PHP Version 5
 *
 * @category   Ding
 * @package    Mvc
 * @subpackage Http
 * @author     Marcelo Gornstein <marcelog@gmail.com>
 * @license    http://marcelog.github.com/ Apache License 2.0
 * @version    SVN: $Id$
 * @link       http://marcelog.github.com/
 *
 * Copyright 2011 Marcelo Gornstein <marcelog@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

namespace Ding\MVC\Http;

use Ding\Container\Impl\ContainerImpl;
use Ding\MVC\Exception\MVCException;
use Ding\MVC\IMapper;
use Ding\MVC\Action;

/**
 * A mapper implementation for http requests.
 *
 * PHP Version 5
 *
 * @category   Ding
 * @package    Mvc
 * @subpackage Http
 * @author     Marcelo Gornstein <marcelog@gmail.com>
 * @license    http://marcelog.github.com/ Apache License 2.0
 * @version    SVN: $Id$
 * @link       http://marcelog.github.com/
 */
class HttpUrlMapper implements IMapper {

    /**
     * Cache for isDebugEnabled()
     * @var boolean
     */
    private $_loggerDebugEnabled;

    /**
     * log4php logger or our own.
     * @var Logger
     */
    private $_logger;

    /**
     * @var Controller[]
     */
    private $_map;

    /**
     * Used from the MVC driver to setup annotated controllers.
     * @var string[]
     */
    private static $_annotatedControllers = array();

    /**
     * The default controller name. Uses if request contains only '/' .
     * @var string
     */
    private static $_defaultController = "index";

    /**
     * The default action name. Used if requesst does not contain action and parameters.
     * @var string
     */
    private static $_defaultAction = "index";

    /**
     * Used from the MVC driver to add controllers found by annotations.
     *
     * @param string $url        Url mapped.
     * @param string $controller Name for the bean (autogenerated).
     *
     * @return void
     */
    public static function addAnnotatedController($url, $controller) {
        self::$_annotatedControllers[] = array($url, $controller);
    }

    /**
     * Sets the map for this mapper.
     *
     * @param array[] $map An array containing arrays defined like this:
     * [0] => IAction, [1] => IController
     *
     * (non-PHPdoc)
     * @see Ding\MVC.IMapper::setMap()
     *
     * @return void
     */
    public function setMap(array $map) {
        $this->_map = $map;
    }

    /**
     * This will map a full url, like /A/B/C to an HttpAction and will try to
     * find a controller that can handle it. This will isolate the baseUrl.
     *
     * @param Action $action Original action (coming from the frontcontroller,
     * the full url).
     *
     * @return array [0] => Controller [1] => Method to call (With
     * 'Action' appended to the end of the method name).
     */
    public function map(Action $action) {
        $url = $action->getId();
        // Add a slash to the beginning is none is found after removing the
        // base url.
        if ($url[0] != '/') {
            $url = '/' . $url;
        }
        // Do not take into account the arguments part of the url.
        $url = explode('?', $url);
        $url = $url[0];

        // parce url to controller, action and parameters
        $parts = explode('/', $url);
        array_shift($parts);
        $requestController = isset($parts[0]) ? array_shift($parts) : self::$_defaultController;
        $requestController = "/$requestController/";

        $requestAction = isset($parts[0]) ? array_shift($parts) : self::$_defaultAction;

        $params = $parts; // TODO: parse paramters like /controller/action/id/123/...

        if ($this->_loggerDebugEnabled) {
            $this->_logger->debug('Trying to match: ' . $requestController . $requestAction);
        }
        // Lookup a controller that can handle this url.
        $try = array_merge($this->_map, self::$_annotatedControllers);
        foreach ($try as $map) {
            $controller = $map[1];
            $urls = $map[0];
            if (!is_array($urls)) {
                $urls = array($urls);
            }
            // Val D.: there are many url per one controller
            foreach ($urls as $controllerUrl) {
                if ($controllerUrl[0] != '/') {
                    $controllerUrl = '/' . $controllerUrl;
                }
                $len = strlen($controllerUrl);
                if ($controllerUrl[$len - 1] != '/') {
                    $controllerUrl = $controllerUrl . '/';
                }

                if ($controllerUrl != $requestController) {
                    continue;
                }

                if (!is_object($controller)) {
                    if ($this->_loggerDebugEnabled) {
                        $this->_logger->debug(
                                'Found as annotated controller: ' . $controller
                        );
                    }
                    $container = ContainerImpl::getInstance();
                    $controller = $container->getBean($controller);
                }
                return array($controller, $requestAction . 'Action');
            }
        }
        return false;
    }

    /**
     * Constructor.
     *
     * @return void
     */
    public function __construct() {
        $this->_logger = \Logger::getLogger('Ding.MVC');
        $this->_map = array();
        $this->_loggerDebugEnabled = $this->_logger->isDebugEnabled();
    }

}
marcelog commented 12 years ago

Hey Valery! Thank you very much for your patch :) I'll review it, create the unit test(s), and let you know as soon as possible when I'm ready to commit it

ValeryDubrava commented 12 years ago

No problem. But it is not a patch, sorry. I use Ding as submodule in the Git, and it does not able to create patch for submodule =(

On Tue, Dec 6, 2011 at 2:42 PM, Marcelo Gornstein < reply@reply.github.com

wrote:

Hey Valery! Thank you very much for your patch :) I'll review it, create the unit test(s), and let you know as soon as possible when I'm ready to commit it


Reply to this email directly or view it on GitHub: https://github.com/marcelog/Ding/issues/117#issuecomment-3030708

marcelog commented 12 years ago

That's ok, no problem :)

marcelog commented 12 years ago

Valery: just commited your contribution. Thanks! :)

ValeryDubrava commented 12 years ago

Thank you for your time!

On Thu, Dec 8, 2011 at 10:35 PM, Marcelo Gornstein < reply@reply.github.com

wrote:

Valery: just commited your contribution. Thanks! :)


Reply to this email directly or view it on GitHub: https://github.com/marcelog/Ding/issues/117#issuecomment-3067580