{"action":"created","comment":{"url":"https://api.github.com/repos/ci-bonfire/Sprint/pulls/comments/27729939","id":27729939,"diff_hunk":"@@ -0,0 +1,1165 @@\n+<?php namespace Myth\\Themers;\n+/**\n+ * Sprint\n+ *\n+ * A set of power tools to enhance the CodeIgniter framework and provide consistent workflow.\n+ *\n+ * Permission is hereby granted, free of charge, to any person obtaining a copy\n+ * of this software and associated documentation files (the \"Software\"), to deal\n+ * in the Software without restriction, including without limitation the rights\n+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n+ * copies of the Software, and to permit persons to whom the Software is\n+ * furnished to do so, subject to the following conditions:\n+ *\n+ * The above copyright notice and this permission notice shall be included in\n+ * all copies or substantial portions of the Software.\n+ *\n+ * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n+ * THE SOFTWARE.\n+ *\n+ * @package     Sprint\n+ * @author      Lonnie Ezell\n+ * @copyright   Copyright 2014-2015, New Myth Media, LLC (http://newmythmedia.com)\n+ * @license     http://opensource.org/licenses/MIT  (MIT)\n+ * @link        http://sprintphp.com\n+ * @since       Version 1.0\n+ */\n+\n+use Myth\\Modules as Modules;\n+use Myth\\Themers\\ThemerInterface;\n+\n+class ViewThemer implements ThemerInterface\n+{\n+\n+    protected $theme = '';\n+\n+    protected $default_theme = null;\n+\n+\tprotected $active_theme = null;\n+\n+    protected $layout = 'index';\n+\n+    protected $view = '';\n+\n+    protected $vars = [];\n+\n+    protected $folders = [];\n+\n+    protected $variants = [];\n+\n+    protected $current_variant = '';\n+\n+\tprotected $parse_views = false;\n+\n+    protected $ci;\n+\n+    //--------------------------------------------------------------------\n+\n+    public function __construct($ci)\n+    {\n+        $this->ci = $ci;\n+\n+\t    $this->parse_views = config_item('theme.parse_views');\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * The main entryway into rendering a view. This is called from the\n+     * controller and is generally the last method called.\n+     *\n+     * @param string $layout        If provided, will override the default layout.\n+     * @param int    $cache_time    The number of seconds to cache the output for.\n+     * @return mixed\n+     */\n+    public function render($layout = null)\n+    {\n+        // Make the template engine available within the views.\n+        $this->vars['themer'] = $this;\n+\n+        // Render our current view content\n+        $this->vars['view_content'] = $this->content();\n+\n+        $theme = empty($this->theme) ? $this->default_theme : $this->theme;\n+\n+        if (! isset($this->folders[$theme])) {\n+            throw new \\LogicException( sprintf( lang('theme.bad_folder'), $theme ) );\n+        }\n+\n+\t    $this->active_theme = $theme;\n+\n+        // Make the path available within views.\n+        $this->vars['theme_path'] = $this->folders[$theme];\n+\n+        return $this->display($this->folders[$theme] . '/' . $this->layout);\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+\t/**\n+\t * Used within the template layout file to render the current content.\n+\t * This content is typically used to display the current view.\n+\t *\n+\t * @param int $cache_time\n+\t *\n+\t * @return mixed\n+\t */\n+    public function content()\n+    {\n+        // Calc our view name based on current method/controller\n+        $dir = $this->ci->router->fetch_directory();\n+\n+        foreach (Modules::$locations as $key => $offset) {\n+\n+            if (stripos($dir, 'module') !== false) {\n+//                $dir = str_replace($offset, '', $dir);\n+                $dir = str_replace('controllers/', '', $dir);\n+            }\n+        }\n+\n+        if (substr($dir, -strlen($this->ci->router->fetch_module() .'/')) == $this->ci->router->fetch_module() . '/') {\n+            $dir = '';\n+        }\n+\n+        $view = ! empty($this->view) ? $this->view :\n+            $dir . $this->ci->router->fetch_class() . '/' . $this->ci->router->fetch_method();\n+\n+        return $this->display($view);\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Loads a view file. Useful to control caching. Intended for use\n+     * from within view files.\n+     *\n+     * You can specify that a view should belong to a theme by prefixing\n+     * the name of the theme and a colon to the view name. For example,\n+     * \"admin:header\" would try to display the \"header.php\" file within\n+     * the \"admin\" theme.\n+     *\n+     * If a variant has been specified, it will be added to the end\n+     * of the view name before looking for the file.\n+     *\n+     * @param string $view\n+     * @param array  $data\n+     * @param int    $cache_time Number of minutes to cache the page for\n+     * @param string $cache_name A custom name for the cached file.\n+     * @return mixed\n+     */\n+    public function display($view, $data = array(), $cache_time = 0, $cache_name=null)\n+    {\n+\t    if (empty($cache_name))\n+\t    {\n+\t\t    $cache_name = 'theme_view_' . $view . '_' . $this->ci->router->fetch_class() . '_' . $this->ci->router->fetch_method();\n+\t\t    $cache_name = str_replace( '/', '_', $cache_name );\n+\t    }\n+\n+\t    if ($cache_time == 0 || ! $output = $this->ci->cache->get($cache_name))\n+\t    {\n+\t\t    $theme        = NULL;\n+\t\t    $variant_view = NULL;\n+\n+\t\t    // Pull out the theme from the view, if given.\n+\t\t    if ( strpos( $view, ':' ) !== FALSE )\n+\t\t    {\n+\t\t\t    list( $theme, $view ) = explode( ':', $view );\n+\n+\t\t\t    $theme = str_replace('{theme}', $this->active_theme, $theme);\n+\t\t    }\n+\n+\t\t    if ( ! empty( $theme ) && isset( $this->folders[ $theme ] ) )\n+\t\t    {\n+\t\t\t    $view = rtrim( $this->folders[ $theme ], '/' ) . '/' . $view;\n+\t\t    }\n+\n+\t\t    if (! is_array($data))\n+\t\t    {\n+\t\t\t    $data = [];\n+\t\t    }\n+\n+\t\t    $data = array_merge( $this->vars, $data );\n+\n+\t\t    // if using a variant, add it to the view name.\n+\t\t    if ( ! empty( $this->current_variant ) )\n+\t\t    {\n+\t\t\t    $variant_view = $view . $this->variants[ $this->current_variant ];\n+\n+\t\t\t    $output = $this->loadView($variant_view, $data);\n+\t\t    }\n+\n+\t\t    // If that didn't find anything, then try it without a variant\n+\t\t    if ( empty( $output ) )\n+\t\t    {\n+\t\t\t    $output = $this->loadView($view, $data);\n+\t\t    }\n+\n+\t\t    // Cache it\n+\t\t    if ((int)$cache_time > 0)\n+\t\t    {\n+\t\t\t    $this->ci->cache->save($cache_name, $output, (int)$cache_time * 60);\n+\t\t    }\n+\t    }\n+\n+\t    // Parse views?\n+\t    if ($this->parse_views)\n+\t    {\n+\t\t    $this->ci->load->library('parser');\n+\n+\t\t    // Any class objects will cause failure\n+\t\t    // so get rid of those bad boys....\n+\t\t    unset($data['uikit'], $data['themer']);\n+\n+\t\t    $output = $this->ci->parser->parse_string($output, $data, true);\n+\t    }\n+\n+        return $output;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Runs a callback method and returns the contents to the view.\n+     *\n+     * @param $command\n+     * @param int $cache_time\n+     * @param string $cache_name    // Number of MINUTES to cache output\n+     * @return mixed|void\n+     */\n+    public function call($command, $cache_time=0, $cache_name=null)\n+    {\n+\t    if (empty($cache_name))\n+\t    {\n+\t\t    $cache_name = 'theme_call_' . md5( $command );\n+\t    }\n+\n+        if (! $output = $this->ci->cache->get($cache_name)) {\n+            $parts = explode(' ', $command);\n+\n+            list($class, $method) = explode(':', array_shift($parts));\n+\n+            // Prepare our parameter list to send to the callback\n+            // by splitting $parts on equal signs.\n+            $params = array();\n+\n+            foreach ($parts as $part) {\n+                $p = explode('=', $part);\n+\n+                if (empty($p[0]) || empty($p[1]))\n+                {\n+                    continue;\n+                }\n+\n+                $params[ $p[0] ] = $p[1];\n+            }\n+\n+            // Let PHP try to autoload it through any available autoloaders\n+            // (including Composer and user's custom autoloaders). If we\n+            // don't find it, then assume it's a CI library that we can reach.\n+            if (class_exists($class)) {\n+                $class = new $class();\n+            } else {\n+                $this->ci->load->library($class);\n+                $class =& $this->ci->$class;\n+            }\n+\n+            if (! method_exists($class, $method)) {\n+                throw new \\RuntimeException( sprintf( lang('themer.bad_callback'), $class, $method ) );\n+            }\n+\n+            // Call the class with our parameters\n+            $output = $class->{$method}($params);\n+\n+            // Cache it\n+            if ((int)$cache_time > 0)\n+            {\n+                $this->ci->cache->save($cache_name, $output, (int)$cache_time * 60);\n+            }\n+        }\n+\n+        return $output;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Sets the active theme to use. This theme should be\n+     * relative to one of the 'theme_paths' folders.\n+     *\n+     * @param $theme\n+     */\n+    public function setTheme($theme)\n+    {\n+        $this->theme = $theme;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Returns the current theme.\n+     *\n+     * @return mixed|string\n+     */\n+    public function theme()\n+    {\n+        return $this->theme;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Sets the default theme to use if another isn't specified.\n+     *\n+     * @param $theme\n+     * @return mixed|void\n+     */\n+    public function setDefaultTheme($theme)\n+    {\n+        $this->default_theme = $theme;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+\n+    /**\n+     * Sets the current view file to render.\n+     *\n+     * @param $file\n+     * @return mixed\n+     */\n+    public function setView($file)\n+    {\n+        $this->view = $file;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Returns the current view.\n+     *\n+     * @return mixed|string\n+     */\n+    public function view()\n+    {\n+        return $this->view;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Sets the current layout to be used. MUST be the name of one of\n+     * the layout files within the current theme. Case-sensitive.\n+     *\n+     * @param $file\n+     * @return mixed\n+     */\n+    public function setLayout($file)\n+    {\n+        if (empty($file)) return;\n+\n+        $this->layout = $file;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Returns the current layout.\n+     *\n+     * @return mixed|string\n+     */\n+    public function layout()\n+    {\n+        return $this->layout;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Stores one or more pieces of data to be passed to the views when\n+     * they are rendered out.\n+     *\n+     * If both $key and $value are ! empty, then it will treat it as a\n+     * key/value pair. If $key is an array of key/value pairs, then $value\n+     * is ignored and each element of the array are made available to the\n+     * view as if it was a single $key/$value pair.\n+     *\n+     * @param string|array $key\n+     * @param mixed $value\n+     * @return $this\n+     */\n+    public function set($key, $value = null)\n+    {\n+        if (is_array($key)) {\n+            $this->vars = array_merge($this->vars, $key);\n+            return;\n+        }\n+\n+        $this->vars[$key] = $value;\n+\n+        return $this;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Returns a value that has been previously set().\n+     *\n+     * @param $key\n+     * @return mixed\n+     */\n+    public function get($key)\n+    {\n+        return isset($this->vars[$key]) ? $this->vars[$key] : null;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Determines whether or not the view should be parsed with the\n+     * CodeIgniter's parser.\n+     *\n+     * @param bool $parse\n+     * @return mixed\n+     */\n+    public function parseViews($parse = false)\n+    {\n+\t    $this->parse_views = $parse;\n+\n+        return $this;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Theme paths allow you to have multiple locations for themes to be\n+     * stored. This might be used for separating themes for different sub-\n+     * applications, or a core theme and user-submitted themes.\n+     *\n+     * @param $alias The name the theme can be referenced by\n+     * @param $path  A new path where themes can be found.\n+     *\n+     * @return mixed\n+     */\n+    public function addThemePath($alias, $path)\n+    {\n+        $this->folders[$alias] = $path;\n+\n+        return $this;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Removes a single theme path.\n+     *\n+     * @param $alias\n+     * @return $this\n+     */\n+    public function removeThemePath($alias)\n+    {\n+        unset($this->folders[$alias]);\n+\n+        return $this;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Returns the path to the active/default theme's folder.\n+     *\n+     * @return string|null\n+     */\n+    public function getThemePath()\n+    {\n+        $theme = empty($this->theme) ? $this->default_theme : $this->theme;\n+\n+        if (! isset($this->folders[ $theme ]))\n+        {\n+            return null;\n+        }\n+\n+        return $this->folders[$theme];\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+\n+\n+    //--------------------------------------------------------------------\n+    // Variants\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Sets the variant used when creating view names. These variants can\n+     * be anything, but by default are used to render specific templates\n+     * for desktop, tablet, and phone. The name of the variant is added\n+     * to the view name, joined by a \"+\" symbol.\n+     *\n+     * Example:\n+     *      $this->setVariant('phone');\n+     *      $this->display('header');\n+     *\n+     *      Tries to display \"views/header+phone.php\"\n+     *\n+     * @param $variant\n+     * @return $this\n+     */\n+    public function setVariant($variant)\n+    {\n+        if (isset($this->variants[$variant])) {\n+            $this->current_variant = $variant;\n+        }\n+\n+        return $this;\n+    }\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Adds a new variant to the system.\n+     *\n+     * @param $name\n+     * @param $postfix\n+     * @return $this|mixed\n+     */\n+    public function addVariant($name, $postfix)\n+    {\n+        $this->variants[$name] = $postfix;\n+\n+        return $this;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Removes a variant from the system.\n+     *\n+     * @param $name\n+     * @return $this|mixed\n+     */\n+    public function removeVariant($name)\n+    {\n+        if (isset($this->variants[$name])) {\n+            unset($this->variants[$name]);\n+        }\n+\n+        return $this;\n+    }\n+\n+    //--------------------------------------------------------------------\n+    // Private Methods\n+    //--------------------------------------------------------------------\n+\n+    <?php namespace Myth\\Themers;\n+/**\n+ * Sprint\n+ *\n+ * A set of power tools to enhance the CodeIgniter framework and provide consistent workflow.\n+ *\n+ * Permission is hereby granted, free of charge, to any person obtaining a copy\n+ * of this software and associated documentation files (the \"Software\"), to deal\n+ * in the Software without restriction, including without limitation the rights\n+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n+ * copies of the Software, and to permit persons to whom the Software is\n+ * furnished to do so, subject to the following conditions:\n+ *\n+ * The above copyright notice and this permission notice shall be included in\n+ * all copies or substantial portions of the Software.\n+ *\n+ * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n+ * THE SOFTWARE.\n+ *\n+ * @package     Sprint\n+ * @author      Lonnie Ezell\n+ * @copyright   Copyright 2014-2015, New Myth Media, LLC (http://newmythmedia.com)\n+ * @license     http://opensource.org/licenses/MIT  (MIT)\n+ * @link        http://sprintphp.com\n+ * @since       Version 1.0\n+ */\n+\n+use Myth\\Modules as Modules;\n+use Myth\\Themers\\ThemerInterface;\n+\n+class LocalizedViewThemer implements ThemerInterface\n+{\n+\n+    protected $theme = '';\n+\n+    protected $default_theme = null;\n+\n+\tprotected $active_theme = null;\n+\n+    protected $layout = 'index';\n+\n+    protected $view = '';\n+\n+    protected $vars = [];\n+\n+    protected $folders = [];\n+\n+    protected $variants = [];\n+\n+    protected $current_variant = '';\n+\n+\tprotected $parse_views = false;\n+\n+    protected $ci;\n+\n+    //--------------------------------------------------------------------\n+\n+    public function __construct($ci)\n+    {\n+        $this->ci = $ci;\n+\n+\t    $this->parse_views = config_item('theme.parse_views');\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * The main entryway into rendering a view. This is called from the\n+     * controller and is generally the last method called.\n+     *\n+     * @param string $layout        If provided, will override the default layout.\n+     * @param int    $cache_time    The number of seconds to cache the output for.\n+     * @return mixed\n+     */\n+    public function render($layout = null)\n+    {\n+        // Make the template engine available within the views.\n+        $this->vars['themer'] = $this;\n+\n+        // Render our current view content\n+        $this->vars['view_content'] = $this->content();\n+\n+        $theme = empty($this->theme) ? $this->default_theme : $this->theme;\n+\n+        if (! isset($this->folders[$theme])) {\n+            throw new \\LogicException( sprintf( lang('theme.bad_folder'), $theme ) );\n+        }\n+\n+\t    $this->active_theme = $theme;\n+\n+        // Make the path available within views.\n+        $this->vars['theme_path'] = $this->folders[$theme];\n+\n+        return $this->display($this->folders[$theme] . '/' . $this->layout);\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+\t/**\n+\t * Used within the template layout file to render the current content.\n+\t * This content is typically used to display the current view.\n+\t *\n+\t * @param int $cache_time\n+\t *\n+\t * @return mixed\n+\t */\n+    public function content()\n+    {\n+        // Calc our view name based on current method/controller\n+        $dir = $this->ci->router->fetch_directory();\n+\n+        foreach (Modules::$locations as $key => $offset) {\n+\n+            if (stripos($dir, 'module') !== false) {\n+//                $dir = str_replace($offset, '', $dir);\n+                $dir = str_replace('controllers/', '', $dir);\n+            }\n+        }\n+\n+        if (substr($dir, -strlen($this->ci->router->fetch_module() .'/')) == $this->ci->router->fetch_module() . '/') {\n+            $dir = '';\n+        }\n+\n+        $view = ! empty($this->view) ? $this->view :\n+            $dir . $this->ci->router->fetch_class() . '/' . $this->ci->router->fetch_method();\n+\n+        return $this->display($view);\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Loads a view file. Useful to control caching. Intended for use\n+     * from within view files.\n+     *\n+     * You can specify that a view should belong to a theme by prefixing\n+     * the name of the theme and a colon to the view name. For example,\n+     * \"admin:header\" would try to display the \"header.php\" file within\n+     * the \"admin\" theme.\n+     *\n+     * If a variant has been specified, it will be added to the end\n+     * of the view name before looking for the file.\n+     *\n+     * @param string $view\n+     * @param array  $data\n+     * @param int    $cache_time Number of minutes to cache the page for\n+     * @param string $cache_name A custom name for the cached file.\n+     * @return mixed\n+     */\n+    public function display($view, $data = array(), $cache_time = 0, $cache_name=null)\n+    {\n+\t    if (empty($cache_name))\n+\t    {\n+\t\t    $cache_name = 'theme_view_' . $view . '_' . $this->ci->router->fetch_class() . '_' . $this->ci->router->fetch_method();\n+\t\t    $cache_name = str_replace( '/', '_', $cache_name );\n+\t    }\n+\n+\t    if ($cache_time == 0 || ! $output = $this->ci->cache->get($cache_name))\n+\t    {\n+\t\t    $theme        = NULL;\n+\t\t    $variant_view = NULL;\n+\n+\t\t    // Pull out the theme from the view, if given.\n+\t\t    if ( strpos( $view, ':' ) !== FALSE )\n+\t\t    {\n+\t\t\t    list( $theme, $view ) = explode( ':', $view );\n+\n+\t\t\t    $theme = str_replace('{theme}', $this->active_theme, $theme);\n+\t\t    }\n+\n+\t\t    if ( ! empty( $theme ) && isset( $this->folders[ $theme ] ) )\n+\t\t    {\n+\t\t\t    $view = rtrim( $this->folders[ $theme ], '/' ) . '/' . $view;\n+\t\t    }\n+\n+\t\t    if (! is_array($data))\n+\t\t    {\n+\t\t\t    $data = [];\n+\t\t    }\n+\n+\t\t    $data = array_merge( $this->vars, $data );\n+\n+\t\t    // if using a variant, add it to the view name.\n+\t\t    if ( ! empty( $this->current_variant ) )\n+\t\t    {\n+\t\t\t    $variant_view = $view . $this->variants[ $this->current_variant ];\n+\n+\t\t\t    $output = $this->loadView($variant_view, $data);\n+\t\t    }\n+\n+\t\t    // If that didn't find anything, then try it without a variant\n+\t\t    if ( empty( $output ) )\n+\t\t    {\n+\t\t\t    $output = $this->loadView($view, $data);\n+\t\t    }\n+\n+\t\t    // Cache it\n+\t\t    if ((int)$cache_time > 0)\n+\t\t    {\n+\t\t\t    $this->ci->cache->save($cache_name, $output, (int)$cache_time * 60);\n+\t\t    }\n+\t    }\n+\n+\t    // Parse views?\n+\t    if ($this->parse_views)\n+\t    {\n+\t\t    $this->ci->load->library('parser');\n+\n+\t\t    // Any class objects will cause failure\n+\t\t    // so get rid of those bad boys....\n+\t\t    unset($data['uikit'], $data['themer']);\n+\n+\t\t    $output = $this->ci->parser->parse_string($output, $data, true);\n+\t    }\n+\n+        return $output;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Runs a callback method and returns the contents to the view.\n+     *\n+     * @param $command\n+     * @param int $cache_time\n+     * @param string $cache_name    // Number of MINUTES to cache output\n+     * @return mixed|void\n+     */\n+    public function call($command, $cache_time=0, $cache_name=null)\n+    {\n+\t    if (empty($cache_name))\n+\t    {\n+\t\t    $cache_name = 'theme_call_' . md5( $command );\n+\t    }\n+\n+        if (! $output = $this->ci->cache->get($cache_name)) {\n+            $parts = explode(' ', $command);\n+\n+            list($class, $method) = explode(':', array_shift($parts));\n+\n+            // Prepare our parameter list to send to the callback\n+            // by splitting $parts on equal signs.\n+            $params = array();\n+\n+            foreach ($parts as $part) {\n+                $p = explode('=', $part);\n+\n+                if (empty($p[0]) || empty($p[1]))\n+                {\n+                    continue;\n+                }\n+\n+                $params[ $p[0] ] = $p[1];\n+            }\n+\n+            // Let PHP try to autoload it through any available autoloaders\n+            // (including Composer and user's custom autoloaders). If we\n+            // don't find it, then assume it's a CI library that we can reach.\n+            if (class_exists($class)) {\n+                $class = new $class();\n+            } else {\n+                $this->ci->load->library($class);\n+                $class =& $this->ci->$class;\n+            }\n+\n+            if (! method_exists($class, $method)) {\n+                throw new \\RuntimeException( sprintf( lang('themer.bad_callback'), $class, $method ) );\n+            }\n+\n+            // Call the class with our parameters\n+            $output = $class->{$method}($params);\n+\n+            // Cache it\n+            if ((int)$cache_time > 0)\n+            {\n+                $this->ci->cache->save($cache_name, $output, (int)$cache_time * 60);\n+            }\n+        }\n+\n+        return $output;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Sets the active theme to use. This theme should be\n+     * relative to one of the 'theme_paths' folders.\n+     *\n+     * @param $theme\n+     */\n+    public function setTheme($theme)\n+    {\n+        $this->theme = $theme;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Returns the current theme.\n+     *\n+     * @return mixed|string\n+     */\n+    public function theme()\n+    {\n+        return $this->theme;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Sets the default theme to use if another isn't specified.\n+     *\n+     * @param $theme\n+     * @return mixed|void\n+     */\n+    public function setDefaultTheme($theme)\n+    {\n+        $this->default_theme = $theme;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+\n+    /**\n+     * Sets the current view file to render.\n+     *\n+     * @param $file\n+     * @return mixed\n+     */\n+    public function setView($file)\n+    {\n+        $this->view = $file;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Returns the current view.\n+     *\n+     * @return mixed|string\n+     */\n+    public function view()\n+    {\n+        return $this->view;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Sets the current layout to be used. MUST be the name of one of\n+     * the layout files within the current theme. Case-sensitive.\n+     *\n+     * @param $file\n+     * @return mixed\n+     */\n+    public function setLayout($file)\n+    {\n+        if (empty($file)) return;\n+\n+        $this->layout = $file;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Returns the current layout.\n+     *\n+     * @return mixed|string\n+     */\n+    public function layout()\n+    {\n+        return $this->layout;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Stores one or more pieces of data to be passed to the views when\n+     * they are rendered out.\n+     *\n+     * If both $key and $value are ! empty, then it will treat it as a\n+     * key/value pair. If $key is an array of key/value pairs, then $value\n+     * is ignored and each element of the array are made available to the\n+     * view as if it was a single $key/$value pair.\n+     *\n+     * @param string|array $key\n+     * @param mixed $value\n+     * @return $this\n+     */\n+    public function set($key, $value = null)\n+    {\n+        if (is_array($key)) {\n+            $this->vars = array_merge($this->vars, $key);\n+            return;\n+        }\n+\n+        $this->vars[$key] = $value;\n+\n+        return $this;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Returns a value that has been previously set().\n+     *\n+     * @param $key\n+     * @return mixed\n+     */\n+    public function get($key)\n+    {\n+        return isset($this->vars[$key]) ? $this->vars[$key] : null;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Determines whether or not the view should be parsed with the\n+     * CodeIgniter's parser.\n+     *\n+     * @param bool $parse\n+     * @return mixed\n+     */\n+    public function parseViews($parse = false)\n+    {\n+\t    $this->parse_views = $parse;\n+\n+        return $this;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Theme paths allow you to have multiple locations for themes to be\n+     * stored. This might be used for separating themes for different sub-\n+     * applications, or a core theme and user-submitted themes.\n+     *\n+     * @param $alias The name the theme can be referenced by\n+     * @param $path  A new path where themes can be found.\n+     *\n+     * @return mixed\n+     */\n+    public function addThemePath($alias, $path)\n+    {\n+        $this->folders[$alias] = $path;\n+\n+        return $this;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Removes a single theme path.\n+     *\n+     * @param $alias\n+     * @return $this\n+     */\n+    public function removeThemePath($alias)\n+    {\n+        unset($this->folders[$alias]);\n+\n+        return $this;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Returns the path to the active/default theme's folder.\n+     *\n+     * @return string|null\n+     */\n+    public function getThemePath()\n+    {\n+        $theme = empty($this->theme) ? $this->default_theme : $this->theme;\n+\n+        if (! isset($this->folders[ $theme ]))\n+        {\n+            return null;\n+        }\n+\n+        return $this->folders[$theme];\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+\n+\n+    //--------------------------------------------------------------------\n+    // Variants\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Sets the variant used when creating view names. These variants can\n+     * be anything, but by default are used to render specific templates\n+     * for desktop, tablet, and phone. The name of the variant is added\n+     * to the view name, joined by a \"+\" symbol.\n+     *\n+     * Example:\n+     *      $this->setVariant('phone');\n+     *      $this->display('header');\n+     *\n+     *      Tries to display \"views/header+phone.php\"\n+     *\n+     * @param $variant\n+     * @return $this\n+     */\n+    public function setVariant($variant)\n+    {\n+        if (isset($this->variants[$variant])) {\n+            $this->current_variant = $variant;\n+        }\n+\n+        return $this;\n+    }\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Adds a new variant to the system.\n+     *\n+     * @param $name\n+     * @param $postfix\n+     * @return $this|mixed\n+     */\n+    public function addVariant($name, $postfix)\n+    {\n+        $this->variants[$name] = $postfix;\n+\n+        return $this;\n+    }\n+\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Removes a variant from the system.\n+     *\n+     * @param $name\n+     * @return $this|mixed\n+     */\n+    public function removeVariant($name)\n+    {\n+        if (isset($this->variants[$name])) {\n+            unset($this->variants[$name]);\n+        }\n+\n+        return $this;\n+    }\n+\n+    //--------------------------------------------------------------------\n+    // Private Methods\n+    //--------------------------------------------------------------------\n+\n+    /**\n+     * Handles the actual loading of a view file, and checks for any\n+     * overrides in themes, etc.\n+     *\n+     * @param $view\n+     * @param $data\n+     *\n+     * @return string\n+     */\n+    private function loadView($view, $data)\n+    {\n+        // First - does it exist in the current theme?\n+        $theme = ! empty($this->active_theme) ? $this->active_theme : $this->default_theme;\n+        $theme = ! empty($this->folders[$theme]) ? $this->folders[$theme] : $theme;\n+        $theme = rtrim($theme, '/ ') .'/';\n+\t\t\n+\t\t// Set localization idioms\n+\t\t$theme_lang_idom = str_replace(FCPATH .'themes/', FCPATH .'themes/'. CURRENT_LANGUAGE .'/', $theme);","path":"myth/Themers/LocalizedViewThemer.php","position":1130,"original_position":1130,"commit_id":"0b509e3ce24e01811b6ee5640f718e7331ffc950","original_commit_id":"0b509e3ce24e01811b6ee5640f718e7331ffc950","user":{"login":"lonnieezell","id":51931,"avatar_url":"https://avatars.githubusercontent.com/u/51931?v=3","gravatar_id":"","url":"https://api.github.com/users/lonnieezell","html_url":"https://github.com/lonnieezell","followers_url":"https://api.github.com/users/lonnieezell/followers","following_url":"https://api.github.com/users/lonnieezell/following{/other_user}","gists_url":"https://api.github.com/users/lonnieezell/gists{/gist_id}","starred_url":"https://api.github.com/users/lonnieezell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lonnieezell/subscriptions","organizations_url":"https://api.github.com/users/lonnieezell/orgs","repos_url":"https://api.github.com/users/lonnieezell/repos","events_url":"https://api.github.com/users/lonnieezell/events{/privacy}","received_events_url":"https://api.github.com/users/lonnieezell/received_events","type":"User","site_admin":false},"body":"You cannot rely on FCPATH being an accurate part of the path. The user could specify the theme folder to be anywhere on the system. Checking for 'themes/' should be reliable, but even then, not necessarily. The simplest thing to do is to just tack on the idiom to the theme. We want the 'turkish' language folders to be inside of the theme, anyway. ","created_at":"2015-04-03T13:50:08Z","updated_at":"2015-04-03T13:50:08Z","html_url":"https://github.com/ci-bonfire/Sprint/pull/80#discussion_r27729939","pull_request_url":"https://api.github.com/repos/ci-bonfire/Sprint/pulls/80","_links":{"self":{"href":"https://api.github.com/repos/ci-bonfire/Sprint/pulls/comments/27729939"},"html":{"href":"https://github.com/ci-bonfire/Sprint/pull/80#discussion_r27729939"},"pull_request":{"href":"https://api.github.com/repos/ci-bonfire/Sprint/pulls/80"}}},"pull_request":{"url":"https://api.github.com/repos/ci-bonfire/Sprint/pulls/80","id":32587322,"html_url":"https://github.com/ci-bonfire/Sprint/pull/80","diff_url":"https://github.com/ci-bonfire/Sprint/pull/80.diff","patch_url":"https://github.com/ci-bonfire/Sprint/pull/80.patch","issue_url":"https://api.github.com/repos/ci-bonfire/Sprint/issues/80","number":80,"state":"open","locked":false,"title":"LocalizedViewThemer proposal.","user":{"login":"IrcDirk","id":1030023,"avatar_url":"https://avatars.githubusercontent.com/u/1030023?v=3","gravatar_id":"","url":"https://api.github.com/users/IrcDirk","html_url":"https://github.com/IrcDirk","followers_url":"https://api.github.com/users/IrcDirk/followers","following_url":"https://api.github.com/users/IrcDirk/following{/other_user}","gists_url":"https://api.github.com/users/IrcDirk/gists{/gist_id}","starred_url":"https://api.github.com/users/IrcDirk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IrcDirk/subscriptions","organizations_url":"https://api.github.com/users/IrcDirk/orgs","repos_url":"https://api.github.com/users/IrcDirk/repos","events_url":"https://api.github.com/users/IrcDirk/events{/privacy}","received_events_url":"https://api.github.com/users/IrcDirk/received_events","type":"User","site_admin":false},"body":"If `views/{idiom}/home/index` doesnt exists trows error, but should show `view/home/index`. Thats the last `if` in `loadView` function.","created_at":"2015-04-03T12:59:12Z","updated_at":"2015-04-03T13:50:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":"53ad39b8aef1729a2d161c501495810192eb15e8","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/ci-bonfire/Sprint/pulls/80/commits","review_comments_url":"https://api.github.com/repos/ci-bonfire/Sprint/pulls/80/comments","review_comment_url":"https://api.github.com/repos/ci-bonfire/Sprint/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ci-bonfire/Sprint/issues/80/comments","statuses_url":"https://api.github.com/repos/ci-bonfire/Sprint/statuses/0b509e3ce24e01811b6ee5640f718e7331ffc950","head":{"label":"IrcDirk:i18n","ref":"i18n","sha":"0b509e3ce24e01811b6ee5640f718e7331ffc950","user":{"login":"IrcDirk","id":1030023,"avatar_url":"https://avatars.githubusercontent.com/u/1030023?v=3","gravatar_id":"","url":"https://api.github.com/users/IrcDirk","html_url":"https://github.com/IrcDirk","followers_url":"https://api.github.com/users/IrcDirk/followers","following_url":"https://api.github.com/users/IrcDirk/following{/other_user}","gists_url":"https://api.github.com/users/IrcDirk/gists{/gist_id}","starred_url":"https://api.github.com/users/IrcDirk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IrcDirk/subscriptions","organizations_url":"https://api.github.com/users/IrcDirk/orgs","repos_url":"https://api.github.com/users/IrcDirk/repos","events_url":"https://api.github.com/users/IrcDirk/events{/privacy}","received_events_url":"https://api.github.com/users/IrcDirk/received_events","type":"User","site_admin":false},"repo":{"id":32949981,"name":"Sprint","full_name":"IrcDirk/Sprint","owner":{"login":"IrcDirk","id":1030023,"avatar_url":"https://avatars.githubusercontent.com/u/1030023?v=3","gravatar_id":"","url":"https://api.github.com/users/IrcDirk","html_url":"https://github.com/IrcDirk","followers_url":"https://api.github.com/users/IrcDirk/followers","following_url":"https://api.github.com/users/IrcDirk/following{/other_user}","gists_url":"https://api.github.com/users/IrcDirk/gists{/gist_id}","starred_url":"https://api.github.com/users/IrcDirk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IrcDirk/subscriptions","organizations_url":"https://api.github.com/users/IrcDirk/orgs","repos_url":"https://api.github.com/users/IrcDirk/repos","events_url":"https://api.github.com/users/IrcDirk/events{/privacy}","received_events_url":"https://api.github.com/users/IrcDirk/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/IrcDirk/Sprint","description":"A lightweight, modern addition to CodeIgniter 3. The heart of Bonfire Next.","fork":true,"url":"https://api.github.com/repos/IrcDirk/Sprint","forks_url":"https://api.github.com/repos/IrcDirk/Sprint/forks","keys_url":"https://api.github.com/repos/IrcDirk/Sprint/keys{/key_id}","collaborators_url":"https://api.github.com/repos/IrcDirk/Sprint/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/IrcDirk/Sprint/teams","hooks_url":"https://api.github.com/repos/IrcDirk/Sprint/hooks","issue_events_url":"https://api.github.com/repos/IrcDirk/Sprint/issues/events{/number}","events_url":"https://api.github.com/repos/IrcDirk/Sprint/events","assignees_url":"https://api.github.com/repos/IrcDirk/Sprint/assignees{/user}","branches_url":"https://api.github.com/repos/IrcDirk/Sprint/branches{/branch}","tags_url":"https://api.github.com/repos/IrcDirk/Sprint/tags","blobs_url":"https://api.github.com/repos/IrcDirk/Sprint/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/IrcDirk/Sprint/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/IrcDirk/Sprint/git/refs{/sha}","trees_url":"https://api.github.com/repos/IrcDirk/Sprint/git/trees{/sha}","statuses_url":"https://api.github.com/repos/IrcDirk/Sprint/statuses/{sha}","languages_url":"https://api.github.com/repos/IrcDirk/Sprint/languages","stargazers_url":"https://api.github.com/repos/IrcDirk/Sprint/stargazers","contributors_url":"https://api.github.com/repos/IrcDirk/Sprint/contributors","subscribers_url":"https://api.github.com/repos/IrcDirk/Sprint/subscribers","subscription_url":"https://api.github.com/repos/IrcDirk/Sprint/subscription","commits_url":"https://api.github.com/repos/IrcDirk/Sprint/commits{/sha}","git_commits_url":"https://api.github.com/repos/IrcDirk/Sprint/git/commits{/sha}","comments_url":"https://api.github.com/repos/IrcDirk/Sprint/comments{/number}","issue_comment_url":"https://api.github.com/repos/IrcDirk/Sprint/issues/comments{/number}","contents_url":"https://api.github.com/repos/IrcDirk/Sprint/contents/{+path}","compare_url":"https://api.github.com/repos/IrcDirk/Sprint/compare/{base}...{head}","merges_url":"https://api.github.com/repos/IrcDirk/Sprint/merges","archive_url":"https://api.github.com/repos/IrcDirk/Sprint/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/IrcDirk/Sprint/downloads","issues_url":"https://api.github.com/repos/IrcDirk/Sprint/issues{/number}","pulls_url":"https://api.github.com/repos/IrcDirk/Sprint/pulls{/number}","milestones_url":"https://api.github.com/repos/IrcDirk/Sprint/milestones{/number}","notifications_url":"https://api.github.com/repos/IrcDirk/Sprint/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/IrcDirk/Sprint/labels{/name}","releases_url":"https://api.github.com/repos/IrcDirk/Sprint/releases{/id}","created_at":"2015-03-26T20:24:10Z","updated_at":"2015-04-03T12:56:49Z","pushed_at":"2015-04-03T12:56:49Z","git_url":"git://github.com/IrcDirk/Sprint.git","ssh_url":"git@github.com:IrcDirk/Sprint.git","clone_url":"https://github.com/IrcDirk/Sprint.git","svn_url":"https://github.com/IrcDirk/Sprint","homepage":null,"size":7785,"stargazers_count":0,"watchers_count":0,"language":"PHP","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"i18n"}},"base":{"label":"ci-bonfire:i18n","ref":"i18n","sha":"d6bab1447a0984764e32134abeea67cc49a5c730","user":{"login":"ci-bonfire","id":697249,"avatar_url":"https://avatars.githubusercontent.com/u/697249?v=3","gravatar_id":"","url":"https://api.github.com/users/ci-bonfire","html_url":"https://github.com/ci-bonfire","followers_url":"https://api.github.com/users/ci-bonfire/followers","following_url":"https://api.github.com/users/ci-bonfire/following{/other_user}","gists_url":"https://api.github.com/users/ci-bonfire/gists{/gist_id}","starred_url":"https://api.github.com/users/ci-bonfire/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ci-bonfire/subscriptions","organizations_url":"https://api.github.com/users/ci-bonfire/orgs","repos_url":"https://api.github.com/users/ci-bonfire/repos","events_url":"https://api.github.com/users/ci-bonfire/events{/privacy}","received_events_url":"https://api.github.com/users/ci-bonfire/received_events","type":"Organization","site_admin":false},"repo":{"id":24104160,"name":"Sprint","full_name":"ci-bonfire/Sprint","owner":{"login":"ci-bonfire","id":697249,"avatar_url":"https://avatars.githubusercontent.com/u/697249?v=3","gravatar_id":"","url":"https://api.github.com/users/ci-bonfire","html_url":"https://github.com/ci-bonfire","followers_url":"https://api.github.com/users/ci-bonfire/followers","following_url":"https://api.github.com/users/ci-bonfire/following{/other_user}","gists_url":"https://api.github.com/users/ci-bonfire/gists{/gist_id}","starred_url":"https://api.github.com/users/ci-bonfire/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ci-bonfire/subscriptions","organizations_url":"https://api.github.com/users/ci-bonfire/orgs","repos_url":"https://api.github.com/users/ci-bonfire/repos","events_url":"https://api.github.com/users/ci-bonfire/events{/privacy}","received_events_url":"https://api.github.com/users/ci-bonfire/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ci-bonfire/Sprint","description":"A lightweight, modern addition to CodeIgniter 3. The heart of Bonfire Next.","fork":false,"url":"https://api.github.com/repos/ci-bonfire/Sprint","forks_url":"https://api.github.com/repos/ci-bonfire/Sprint/forks","keys_url":"https://api.github.com/repos/ci-bonfire/Sprint/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ci-bonfire/Sprint/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ci-bonfire/Sprint/teams","hooks_url":"https://api.github.com/repos/ci-bonfire/Sprint/hooks","issue_events_url":"https://api.github.com/repos/ci-bonfire/Sprint/issues/events{/number}","events_url":"https://api.github.com/repos/ci-bonfire/Sprint/events","assignees_url":"https://api.github.com/repos/ci-bonfire/Sprint/assignees{/user}","branches_url":"https://api.github.com/repos/ci-bonfire/Sprint/branches{/branch}","tags_url":"https://api.github.com/repos/ci-bonfire/Sprint/tags","blobs_url":"https://api.github.com/repos/ci-bonfire/Sprint/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ci-bonfire/Sprint/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ci-bonfire/Sprint/git/refs{/sha}","trees_url":"https://api.github.com/repos/ci-bonfire/Sprint/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ci-bonfire/Sprint/statuses/{sha}","languages_url":"https://api.github.com/repos/ci-bonfire/Sprint/languages","stargazers_url":"https://api.github.com/repos/ci-bonfire/Sprint/stargazers","contributors_url":"https://api.github.com/repos/ci-bonfire/Sprint/contributors","subscribers_url":"https://api.github.com/repos/ci-bonfire/Sprint/subscribers","subscription_url":"https://api.github.com/repos/ci-bonfire/Sprint/subscription","commits_url":"https://api.github.com/repos/ci-bonfire/Sprint/commits{/sha}","git_commits_url":"https://api.github.com/repos/ci-bonfire/Sprint/git/commits{/sha}","comments_url":"https://api.github.com/repos/ci-bonfire/Sprint/comments{/number}","issue_comment_url":"https://api.github.com/repos/ci-bonfire/Sprint/issues/comments{/number}","contents_url":"https://api.github.com/repos/ci-bonfire/Sprint/contents/{+path}","compare_url":"https://api.github.com/repos/ci-bonfire/Sprint/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ci-bonfire/Sprint/merges","archive_url":"https://api.github.com/repos/ci-bonfire/Sprint/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ci-bonfire/Sprint/downloads","issues_url":"https://api.github.com/repos/ci-bonfire/Sprint/issues{/number}","pulls_url":"https://api.github.com/repos/ci-bonfire/Sprint/pulls{/number}","milestones_url":"https://api.github.com/repos/ci-bonfire/Sprint/milestones{/number}","notifications_url":"https://api.github.com/repos/ci-bonfire/Sprint/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ci-bonfire/Sprint/labels{/name}","releases_url":"https://api.github.com/repos/ci-bonfire/Sprint/releases{/id}","created_at":"2014-09-16T14:57:41Z","updated_at":"2015-04-01T13:49:52Z","pushed_at":"2015-04-03T12:59:12Z","git_url":"git://github.com/ci-bonfire/Sprint.git","ssh_url":"git@github.com:ci-bonfire/Sprint.git","clone_url":"https://github.com/ci-bonfire/Sprint.git","svn_url":"https://github.com/ci-bonfire/Sprint","homepage":null,"size":9491,"stargazers_count":37,"watchers_count":37,"language":"PHP","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":12,"mirror_url":null,"open_issues_count":8,"forks":12,"open_issues":8,"watchers":37,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/ci-bonfire/Sprint/pulls/80"},"html":{"href":"https://github.com/ci-bonfire/Sprint/pull/80"},"issue":{"href":"https://api.github.com/repos/ci-bonfire/Sprint/issues/80"},"comments":{"href":"https://api.github.com/repos/ci-bonfire/Sprint/issues/80/comments"},"review_comments":{"href":"https://api.github.com/repos/ci-bonfire/Sprint/pulls/80/comments"},"review_comment":{"href":"https://api.github.com/repos/ci-bonfire/Sprint/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ci-bonfire/Sprint/pulls/80/commits"},"statuses":{"href":"https://api.github.com/repos/ci-bonfire/Sprint/statuses/0b509e3ce24e01811b6ee5640f718e7331ffc950"}}}}