{"action":"created","comment":{"url":"https://api.github.com/repos/ci-bonfire/Sprint/pulls/comments/27738276","id":27738276,"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);\n+\t\t$view_lang_idom = str_replace(FCPATH .'themes/', FCPATH .'themes/'. CURRENT_LANGUAGE .'/', $view);\n+\n+\t\tif(defined('CURRENT_LANGUAGE') && file_exists($theme_lang_idom .\"{$view}.php\"))\n+\t\t{\n+\t\t\t$output = $this->ci->load->view_path( $theme_lang_idom . $view, $data, TRUE );\n+\t\t}\n+\t\t\n+\t\telseif (file_exists($theme .\"{$view}.php\"))\n+        {\n+            $output = $this->ci->load->view_path( $theme . $view, $data, TRUE );\n+        }\n+\t\t\n+\t\telseif(defined('CURRENT_LANGUAGE') && realpath($view_lang_idom .\".php\"))\n+\t\t{\n+\t\t\t$output = $this->ci->load->view_path( $view_lang_idom, $data, TRUE );\n+\t\t}\n+\t\t\n+        // Next, if it's a real file with path, then load it\n+        elseif ( realpath( $view . '.php' ) )\n+        {\n+            $output = $this->ci->load->view_path( $view, $data, TRUE );","path":"myth/Themers/LocalizedViewThemer.php","position":1151,"original_position":1151,"commit_id":"0b509e3ce24e01811b6ee5640f718e7331ffc950","original_commit_id":"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},"body":"What about this part?","created_at":"2015-04-03T16:22:43Z","updated_at":"2015-04-03T16:22:43Z","html_url":"https://github.com/ci-bonfire/Sprint/pull/80#discussion_r27738276","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/27738276"},"html":{"href":"https://github.com/ci-bonfire/Sprint/pull/80#discussion_r27738276"},"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-03T16:22:44Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1ad208b1f70004f01d165e9d112912b67282c06d","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-03T15:11:35Z","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"}}}}