1<?php
2/**
3 * Horde Routes package
4 *
5 * This package is heavily inspired by the Python "Routes" library
6 * by Ben Bangert (http://routes.groovie.org).  Routes is based
7 * largely on ideas from Ruby on Rails (http://www.rubyonrails.org).
8 *
9 * @author  Maintainable Software, LLC. (http://www.maintainable.com)
10 * @author  Mike Naberezny (mike@maintainable.com)
11 * @license http://www.horde.org/licenses/bsd BSD
12 * @package Routes
13 */
14
15/**
16 * Pretty-print a listing of routes connected to a mapper.
17 *
18 * @package Routes
19 */
20class Horde_Routes_Printer
21{
22    /**
23     * @var Horde_Routes_Mapper
24     */
25    protected $_mapper;
26
27    /**
28     * Constructor.
29     *
30     * @param  Horde_Routes_Mapper  $mapper  Mapper to analyze for printing
31     */
32    public function __construct($mapper)
33    {
34        $this->_mapper = $mapper;
35    }
36
37    /**
38     * Pretty-print a listing of the routes connected to the mapper.
39     *
40     * @param  stream|null  $stream  Output stream for printing (optional)
41     * @param  string|null  $eol     Line ending (optional)
42     * @return void
43     */
44    public function printRoutes($stream = null, $eol = PHP_EOL)
45    {
46        $routes = $this->getRoutes();
47        if (empty($routes)) { return; }
48
49        if ($stream === null) {
50            $stream = fopen('php://output', 'a');
51        }
52
53        // find the max $widths to size the output columns {'name'=>40, 'method'=>6, ...}
54        $widths = array();
55        foreach (array_keys($routes[0]) as $key) {
56          $width = 0;
57          foreach($routes as $r) {
58            $l = strlen($r[$key]);
59            if ($l > $width) { $width = $l; }
60          }
61          $widths[$key] = $width;
62        }
63
64        // print the output
65        foreach ($routes as $r) {
66          fwrite($stream, str_pad($r['name'],   $widths['name'],   ' ', STR_PAD_LEFT)  . ' ');
67          fwrite($stream, str_pad($r['method'], $widths['method'], ' ', STR_PAD_RIGHT) . ' ');
68          fwrite($stream, str_pad($r['path'],   $widths['path'],   ' ', STR_PAD_RIGHT) . ' ');
69          fwrite($stream, $r['hardcodes'] . $eol);
70        }
71    }
72
73    /**
74     * Analyze the mapper and return an array of data about the
75     * routes connected to the mapper.
76     *
77     * @return array
78     */
79    public function getRoutes()
80    {
81        /**
82         * Traverse all routes connected to the mapper in match order,
83         * and assemble an array of $routes used to build the output
84         */
85        $routes = array();
86        foreach ($this->_mapper->matchList as $route) {
87          // name of this route, or empty string if anonymous
88          $routeName = '';
89          foreach ($this->_mapper->routeNames as $name => $namedRoute) {
90              if ($route === $namedRoute) { $routeName = $name; break; }
91          }
92
93          // request_method types recognized by this route, or empty string for any
94          $methods = array('');
95          if (isset($route->conditions['method']) && is_array($route->conditions['method']) ) {
96            $methods = $route->conditions['method'];
97          }
98
99          // hardcoded defaults that can't be overriden by the request path as {:key=>"value"}
100          $hardcodes = array();
101          foreach ($route->hardCoded as $key) {
102            $value = isset($route->defaults[$key]) ? $route->defaults[$key] : 'NULL';
103            $dump = ":{$key}=>\"{$value}\"";
104            ($key == 'controller') ? array_unshift($hardcodes, $dump) : $hardcodes[] = $dump;
105          }
106          $hardcodes = empty($hardcodes) ? '' : '{'. implode(', ', $hardcodes) .'}';
107
108          // route data for output
109          foreach ($methods as $method) {
110            $routes[] = array('name'      => $routeName,
111                              'method'    => $method,
112                              'path'      => '/' . $route->routePath,
113                              'hardcodes' => $hardcodes);
114          }
115        }
116
117        return $routes;
118    }
119
120}
121