Source for file utils.php

Documentation is available at utils.php

  1. <?php
  2. /**
  3.  * @package     FrameworkOnFramework
  4.  * @subpackage  template
  5.  * @copyright   Copyright (C) 2010 - 2012 Akeeba Ltd. All rights reserved.
  6.  * @license     GNU General Public License version 2 or later; see LICENSE.txt
  7.  */
  8. // Protect from unauthorized access
  9. defined('_JEXEC'or die;
  10.  
  11. /**
  12.  * A utility class to load view templates, media files and modules.
  13.  *
  14.  * @package  FrameworkOnFramework
  15.  * @since    1.0
  16.  */
  17. {
  18.     /**
  19.      * Add a CSS file to the page generated by the CMS
  20.      *
  21.      * @param   string  $path  A fancy path definition understood by parsePath
  22.      *
  23.      * @see FOFTemplateUtils::parsePath
  24.      *
  25.      * @return  void 
  26.      */
  27.     public static function addCSS($path)
  28.     {
  29.         $document FOFPlatform::getInstance()->getDocument();
  30.  
  31.         if ($document instanceof JDocument)
  32.         {
  33.             if (method_exists($document'addStyleSheet'))
  34.             {
  35.                 $url self::parsePath($path);
  36.                 $document->addStyleSheet($url);
  37.             }
  38.         }
  39.     }
  40.  
  41.     /**
  42.      * Add a JS script file to the page generated by the CMS.
  43.      *
  44.      * There are three combinations of defer and async (see http://www.w3schools.com/tags/att_script_defer.asp):
  45.      * * $defer false, $async true: The script is executed asynchronously with the rest of the page
  46.      *   (the script will be executed while the page continues the parsing)
  47.      * * $defer true, $async false: The script is executed when the page has finished parsing.
  48.      * * $defer false, $async false. (default) The script is loaded and executed immediately. When it finishes
  49.      *   loading the browser continues parsing the rest of the page.
  50.      *
  51.      * When you are using $defer = true there is no guarantee about the load order of the scripts. Whichever
  52.      * script loads first will be executed first. The order they appear on the page is completely irrelevant.
  53.      *
  54.      * @param   string   $path   A fancy path definition understood by parsePath
  55.      * @param   boolean  $defer  Adds the defer attribute, meaning that your script
  56.      *                            will only load after the page has finished parsing.
  57.      * @param   boolean  $async  Adds the async attribute, meaning that your script
  58.      *                            will be executed while the resto of the page
  59.      *                            continues parsing.
  60.      *
  61.      * @see FOFTemplateUtils::parsePath
  62.      *
  63.      * @return  void 
  64.      */
  65.     public static function addJS($path$defer false$async false)
  66.     {
  67.         $document FOFPlatform::getInstance()->getDocument();
  68.  
  69.         if ($document instanceof JDocument)
  70.         {
  71.             if (method_exists($document'addScript'))
  72.             {
  73.                 $url self::parsePath($path);
  74.                 $document->addScript($url"text/javascript"$defer$async);
  75.             }
  76.         }
  77.     }
  78.  
  79.     /**
  80.      * Compile a LESS file into CSS and add it to the page generated by the CMS.
  81.      * This method has integrated cache support. The compiled LESS files will be
  82.      * written to the media/lib_fof/compiled directory of your site. If the file
  83.      * cannot be written we will use the $altPath, if specified
  84.      *
  85.      * @param   string   $path        A fancy path definition understood by parsePath pointing to the source LESS file
  86.      * @param   string   $altPath     A fancy path definition understood by parsePath pointing to a precompiled CSS file,
  87.      *                                 used when we can't write the generated file to the output directory
  88.      * @param   boolean  $returnPath  Return the URL of the generated CSS file but do not include it. If it can't be
  89.      *                                 generated, false is returned and the alt files are not included
  90.      *
  91.      * @see FOFTemplateUtils::parsePath
  92.      *
  93.      * @since 2.0
  94.      *
  95.      * @return  mixed  True = successfully included generated CSS, False = the alternate CSS file was used, null = the source file does not exist
  96.      */
  97.     public static function addLESS($path$altPath null$returnPath false)
  98.     {
  99.         // Does the cache directory exists and is writeable
  100.         static $sanityCheck null;
  101.  
  102.         // Get the local LESS file
  103.         $localFile self::parsePath($pathtrue);
  104.  
  105.         JLoader::import('joomla.filesystem.folder');
  106.  
  107.         if (is_null($sanityCheck))
  108.         {
  109.             // Make sure the cache directory exists
  110.             if (!is_dir(JPATH_SITE '/media/lib_fof/compiled/'))
  111.             {
  112.                 $sanityCheck JFolder::create(JPATH_SITE '/media/lib_fof/compiled/');
  113.             }
  114.             else
  115.             {
  116.                 $sanityCheck true;
  117.             }
  118.         }
  119.  
  120.         // No point continuing if the source file is not there or we can't write to the cache
  121.  
  122.         if (!$sanityCheck || !is_file($localFile))
  123.         {
  124.             if (!$returnPath)
  125.             {
  126.                 if (is_string($altPath))
  127.                 {
  128.                     self::addCSS($altPath);
  129.                 }
  130.                 elseif (is_array($altPath))
  131.                 {
  132.                     foreach ($altPath as $anAltPath)
  133.                     {
  134.                         self::addCSS($anAltPath);
  135.                     }
  136.                 }
  137.             }
  138.  
  139.             return false;
  140.         }
  141.  
  142.         // Get the source file's unique ID
  143.         $id md5(filemtime($localFilefilectime($localFile$localFile);
  144.  
  145.         // Get the cached file path
  146.         $cachedPath JPATH_SITE '/media/lib_fof/compiled/' $id '.css';
  147.  
  148.         // Get the LESS compiler
  149.         $lessCompiler new FOFLess;
  150.         $lessCompiler->formatterName 'compressed';
  151.  
  152.         // Should I add an alternative import path?
  153.         $altFiles self::getAltPaths($path);
  154.  
  155.         if (isset($altFiles['alternate']))
  156.         {
  157.             $currentLocation realpath(dirname($localFile));
  158.             $normalLocation realpath(dirname($altFiles['normal']));
  159.             $alternateLocation realpath(dirname($altFiles['alternate']));
  160.  
  161.             if ($currentLocation == $normalLocation)
  162.             {
  163.                 $lessCompiler->importDir array($alternateLocation$currentLocation);
  164.             }
  165.             else
  166.             {
  167.                 $lessCompiler->importDir array($currentLocation$normalLocation);
  168.             }
  169.         }
  170.  
  171.         // Compile the LESS file
  172.         $lessCompiler->checkedCompile($localFile$cachedPath);
  173.  
  174.         // Add the compiled CSS to the page
  175.         $base_url rtrim(JUri::base()'/');
  176.  
  177.         if (substr($base_url-14== '/administrator')
  178.         {
  179.             $base_url substr($base_url0-14);
  180.         }
  181.  
  182.         $url $base_url '/media/lib_fof/compiled/' $id '.css';
  183.  
  184.         if ($returnPath)
  185.         {
  186.             return $url;
  187.         }
  188.         else
  189.         {
  190.             $document FOFPlatform::getInstance()->getDocument();
  191.  
  192.             if ($document instanceof JDocument)
  193.             {
  194.                 if (method_exists($document'addStyleSheet'))
  195.                 {
  196.                     $document->addStyleSheet($url);
  197.                 }
  198.             }
  199.             return true;
  200.         }
  201.     }
  202.  
  203.     /**
  204.      * Creates a SEF compatible sort header. Standard Joomla function will add a href="#" tag, so with SEF
  205.      * enabled, the browser will follow the fake link instead of processing the onSubmit event; so we
  206.      * need a fix.
  207.      *
  208.      * @param   string   $text   Header text
  209.      * @param   string   $field  Field used for sorting
  210.      * @param   JObject  $list   Object holding the direction and the ordering field
  211.      *
  212.      * @return  string  HTML code for sorting
  213.      */
  214.     public static function sefSort($text$field$list)
  215.     {
  216.         $sort JHTML::_('grid.sort'JText::_(strtoupper($text)) '&nbsp;'$field$list->order_Dir$list->order);
  217.  
  218.         return str_replace('href="#"''href="javascript:void(0);"'$sort);
  219.     }
  220.  
  221.     /**
  222.      * Parse a fancy path definition into a path relative to the site's root,
  223.      * respecting template overrides, suitable for inclusion of media files.
  224.      * For example, media://com_foobar/css/test.css is parsed into
  225.      * media/com_foobar/css/test.css if no override is found, or
  226.      * templates/mytemplate/media/com_foobar/css/test.css if the current
  227.      * template is called mytemplate and there's a media override for it.
  228.      *
  229.      * The valid protocols are:
  230.      * media://        The media directory or a media override
  231.      * admin://        Path relative to administrator directory (no overrides)
  232.      * site://        Path relative to site's root (no overrides)
  233.      *
  234.      * @param   string   $path       Fancy path
  235.      * @param   boolean  $localFile  When true, it returns the local path, not the URL
  236.      *
  237.      * @return  string  Parsed path
  238.      */
  239.     public static function parsePath($path$localFile false)
  240.     {
  241.         if ($localFile)
  242.         {
  243.             $url rtrim(JPATH_ROOTDIRECTORY_SEPARATOR'/';
  244.         }
  245.         else
  246.         {
  247.             $url JURI::root();
  248.         }
  249.  
  250.         $altPaths self::getAltPaths($path);
  251.         $filePath $altPaths['normal'];
  252.  
  253.         // If JDEBUG is enabled, prefer that path, else prefer an alternate path if present
  254.         if (defined('JDEBUG'&& JDEBUG && isset($altPaths['debug']))
  255.         {
  256.             if (file_exists(JPATH_SITE '/' $altPaths['debug']))
  257.             {
  258.                 $filePath $altPaths['debug'];
  259.             }
  260.         }
  261.         elseif (isset($altPaths['alternate']))
  262.         {
  263.             if (file_exists(JPATH_SITE '/' $altPaths['alternate']))
  264.             {
  265.                 $filePath $altPaths['alternate'];
  266.             }
  267.         }
  268.  
  269.         $url .= $filePath;
  270.  
  271.         return $url;
  272.     }
  273.  
  274.     /**
  275.      * Parse a fancy path definition into a path relative to the site's root.
  276.      * It returns both the normal and alternative (template media override) path.
  277.      * For example, media://com_foobar/css/test.css is parsed into
  278.      * array(
  279.      *   'normal' => 'media/com_foobar/css/test.css',
  280.      *   'alternate' => 'templates/mytemplate/media/com_foobar/css//test.css'
  281.      * );
  282.      *
  283.      * The valid protocols are:
  284.      * media://        The media directory or a media override
  285.      * admin://        Path relative to administrator directory (no alternate)
  286.      * site://        Path relative to site's root (no alternate)
  287.      *
  288.      * @param   string  $path  Fancy path
  289.      *
  290.      * @return  array  Array of normal and alternate parsed path
  291.      */
  292.     public static function getAltPaths($path)
  293.     {
  294.         $protoAndPath explode('://'$path2);
  295.  
  296.         if (count($protoAndPath2)
  297.         {
  298.             $protocol 'media';
  299.         }
  300.         else
  301.         {
  302.             $protocol $protoAndPath[0];
  303.             $path $protoAndPath[1];
  304.         }
  305.  
  306.         $path ltrim($path'/' DIRECTORY_SEPARATOR);
  307.  
  308.         switch ($protocol)
  309.         {
  310.             case 'media':
  311.                 // Do we have a media override in the template?
  312.                 $pathAndParams explode('?'$path2);
  313.  
  314.                 $ret array(
  315.                     'normal'     => 'media/' $pathAndParams[0],
  316.                     'alternate'     => FOFPlatform::getInstance()->getTemplateOverridePath('media:/' $pathAndParams[0]false),
  317.                 );
  318.                 break;
  319.  
  320.             case 'admin':
  321.                 $ret array(
  322.                     'normal' => 'administrator/' $path
  323.                 );
  324.                 break;
  325.  
  326.             default:
  327.             case 'site':
  328.                 $ret array(
  329.                     'normal' => $path
  330.                 );
  331.                 break;
  332.         }
  333.  
  334.         // For CSS and JS files, add a debug path if the supplied file is compressed
  335.         JLoader::import('joomla.filesystem.file');
  336.         $ext JFile::getExt($ret['normal']);
  337.  
  338.         if (in_array($extarray('css''js')))
  339.         {
  340.             $file basename(JFile::stripExt($ret['normal']));
  341.  
  342.             /*
  343.              * Detect if we received a file in the format name.min.ext
  344.              * If so, strip the .min part out, otherwise append -uncompressed
  345.              */
  346.  
  347.             if (strlen($file&& strrpos($file'.min''-4'))
  348.             {
  349.                 $position strrpos($file'.min''-4');
  350.                 $filename str_replace('.min''.'$file$position);
  351.             }
  352.             else
  353.             {
  354.                 $filename $file '-uncompressed.' $ext;
  355.             }
  356.  
  357.             // Clone the $ret array so we can manipulate the 'normal' path a bit
  358.             $temp = (array) (clone (object) $ret);
  359.             $normalPath explode('/'$temp['normal']);
  360.             array_pop($normalPath);
  361.             $normalPath[$filename;
  362.             $ret['debug'implode('/'$normalPath);
  363.         }
  364.  
  365.         return $ret;
  366.     }
  367.  
  368.     /**
  369.      * Returns the contents of a module position
  370.      *
  371.      * @param   string  $position  The position name, e.g. "position-1"
  372.      * @param   int     $style     Rendering style; please refer to Joomla!'s code for more information
  373.      *
  374.      * @return  string  The contents of the module position
  375.      */
  376.     public static function loadPosition($position$style = -2)
  377.     {
  378.         $document FOFPlatform::getInstance()->getDocument();
  379.  
  380.         if (!($document instanceof JDocument))
  381.         {
  382.             return '';
  383.         }
  384.  
  385.         if (!method_exists($document'loadRenderer'))
  386.         {
  387.             return '';
  388.         }
  389.  
  390.         $document JFactory::getDocument();
  391.  
  392.         try
  393.         {
  394.             $renderer $document->loadRenderer('module');
  395.         }
  396.         catch (Exception $exc)
  397.         {
  398.             return '';
  399.         }
  400.  
  401.         $params array('style' => $style);
  402.  
  403.         $contents '';
  404.  
  405.         foreach (JModuleHelper::getModules($positionas $mod)
  406.         {
  407.             $contents .= $renderer->render($mod$params);
  408.         }
  409.  
  410.         return $contents;
  411.     }
  412.  
  413.     /**
  414.      * Merges the current url with new or changed parameters.
  415.      *
  416.      * This method merges the route string with the url parameters defined
  417.      * in current url. The parameters defined in current url, but not given
  418.      * in route string, will automatically reused in the resulting url.
  419.      * But only these following parameters will be reused:
  420.      *
  421.      * option, view, layout, format
  422.      *
  423.      * Example:
  424.      *
  425.      * Assuming that current url is:
  426.      * http://fobar.com/index.php?option=com_foo&view=cpanel
  427.      *
  428.      * <code>
  429.      * <?php echo FOFTemplateutils::route('view=categories&layout=tree'); ?>
  430.      * </code>
  431.      *
  432.      * Result:
  433.      * http://fobar.com/index.php?option=com_foo&view=categories&layout=tree
  434.      *
  435.      * @param   string  $route  The parameters string
  436.      *
  437.      * @return  string  The human readable, complete url
  438.      */
  439.     public static function route($route '')
  440.     {
  441.         $route trim($route);
  442.  
  443.         // Special cases
  444.  
  445.         if ($route == 'index.php' || $route == 'index.php?')
  446.         {
  447.             $result $route;
  448.         }
  449.         elseif (substr($route01== '&')
  450.         {
  451.             $url JURI::getInstance();
  452.             $vars array();
  453.             parse_str($route$vars);
  454.  
  455.             $url->setQuery(array_merge($url->getQuery(true)$vars));
  456.  
  457.             $result 'index.php?' $url->getQuery();
  458.         }
  459.         else
  460.         {
  461.             $url JURI::getInstance();
  462.             $props $url->getQuery(true);
  463.  
  464.             // Strip 'index.php?'
  465.             if (substr($route010== 'index.php?')
  466.             {
  467.                 $route substr($route10);
  468.             }
  469.  
  470.             // Parse route
  471.             $parts array();
  472.             parse_str($route$parts);
  473.             $result array();
  474.  
  475.             // Check to see if there is component information in the route if not add it
  476.  
  477.             if (!isset($parts['option']&& isset($props['option']))
  478.             {
  479.                 $result['option=' $props['option'];
  480.             }
  481.  
  482.             // Add the layout information to the route only if it's not 'default'
  483.  
  484.             if (!isset($parts['view']&& isset($props['view']))
  485.             {
  486.                 $result['view=' $props['view'];
  487.  
  488.                 if (!isset($parts['layout']&& isset($props['layout']))
  489.                 {
  490.                     $result['layout=' $props['layout'];
  491.                 }
  492.             }
  493.  
  494.             // Add the format information to the URL only if it's not 'html'
  495.  
  496.             if (!isset($parts['format']&& isset($props['format']&& $props['format'!= 'html')
  497.             {
  498.                 $result['format=' $props['format'];
  499.             }
  500.  
  501.             // Reconstruct the route
  502.  
  503.             if (!empty($route))
  504.             {
  505.                 $result[$route;
  506.             }
  507.  
  508.             $result 'index.php?' implode('&'$result);
  509.         }
  510.  
  511.         return JRoute::_($result);
  512.     }
  513. }

Documentation generated on Tue, 19 Nov 2013 15:16:44 +0100 by phpDocumentor 1.4.3