web/lib/Zend/View/Helper/HeadLink.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_View
       
    17  * @subpackage Helper
       
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    19  * @version    $Id: HeadLink.php 23249 2010-10-26 12:46:47Z matthew $
       
    20  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    21  */
       
    22 
       
    23 /** Zend_View_Helper_Placeholder_Container_Standalone */
       
    24 require_once 'Zend/View/Helper/Placeholder/Container/Standalone.php';
       
    25 
       
    26 /**
       
    27  * Zend_Layout_View_Helper_HeadLink
       
    28  *
       
    29  * @see        http://www.w3.org/TR/xhtml1/dtds.html
       
    30  * @uses       Zend_View_Helper_Placeholder_Container_Standalone
       
    31  * @package    Zend_View
       
    32  * @subpackage Helper
       
    33  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    34  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    35  */
       
    36 class Zend_View_Helper_HeadLink extends Zend_View_Helper_Placeholder_Container_Standalone
       
    37 {
       
    38     /**
       
    39      * $_validAttributes
       
    40      *
       
    41      * @var array
       
    42      */
       
    43     protected $_itemKeys = array('charset', 'href', 'hreflang', 'id', 'media', 'rel', 'rev', 'type', 'title', 'extras');
       
    44 
       
    45     /**
       
    46      * @var string registry key
       
    47      */
       
    48     protected $_regKey = 'Zend_View_Helper_HeadLink';
       
    49 
       
    50     /**
       
    51      * Constructor
       
    52      *
       
    53      * Use PHP_EOL as separator
       
    54      *
       
    55      * @return void
       
    56      */
       
    57     public function __construct()
       
    58     {
       
    59         parent::__construct();
       
    60         $this->setSeparator(PHP_EOL);
       
    61     }
       
    62 
       
    63     /**
       
    64      * headLink() - View Helper Method
       
    65      *
       
    66      * Returns current object instance. Optionally, allows passing array of
       
    67      * values to build link.
       
    68      *
       
    69      * @return Zend_View_Helper_HeadLink
       
    70      */
       
    71     public function headLink(array $attributes = null, $placement = Zend_View_Helper_Placeholder_Container_Abstract::APPEND)
       
    72     {
       
    73         if (null !== $attributes) {
       
    74             $item = $this->createData($attributes);
       
    75             switch ($placement) {
       
    76                 case Zend_View_Helper_Placeholder_Container_Abstract::SET:
       
    77                     $this->set($item);
       
    78                     break;
       
    79                 case Zend_View_Helper_Placeholder_Container_Abstract::PREPEND:
       
    80                     $this->prepend($item);
       
    81                     break;
       
    82                 case Zend_View_Helper_Placeholder_Container_Abstract::APPEND:
       
    83                 default:
       
    84                     $this->append($item);
       
    85                     break;
       
    86             }
       
    87         }
       
    88         return $this;
       
    89     }
       
    90 
       
    91     /**
       
    92      * Overload method access
       
    93      *
       
    94      * Creates the following virtual methods:
       
    95      * - appendStylesheet($href, $media, $conditionalStylesheet, $extras)
       
    96      * - offsetSetStylesheet($index, $href, $media, $conditionalStylesheet, $extras)
       
    97      * - prependStylesheet($href, $media, $conditionalStylesheet, $extras)
       
    98      * - setStylesheet($href, $media, $conditionalStylesheet, $extras)
       
    99      * - appendAlternate($href, $type, $title, $extras)
       
   100      * - offsetSetAlternate($index, $href, $type, $title, $extras)
       
   101      * - prependAlternate($href, $type, $title, $extras)
       
   102      * - setAlternate($href, $type, $title, $extras)
       
   103      *
       
   104      * Items that may be added in the future:
       
   105      * - Navigation?  need to find docs on this
       
   106      *   - public function appendStart()
       
   107      *   - public function appendContents()
       
   108      *   - public function appendPrev()
       
   109      *   - public function appendNext()
       
   110      *   - public function appendIndex()
       
   111      *   - public function appendEnd()
       
   112      *   - public function appendGlossary()
       
   113      *   - public function appendAppendix()
       
   114      *   - public function appendHelp()
       
   115      *   - public function appendBookmark()
       
   116      * - Other?
       
   117      *   - public function appendCopyright()
       
   118      *   - public function appendChapter()
       
   119      *   - public function appendSection()
       
   120      *   - public function appendSubsection()
       
   121      *
       
   122      * @param mixed $method
       
   123      * @param mixed $args
       
   124      * @return void
       
   125      */
       
   126     public function __call($method, $args)
       
   127     {
       
   128         if (preg_match('/^(?P<action>set|(ap|pre)pend|offsetSet)(?P<type>Stylesheet|Alternate)$/', $method, $matches)) {
       
   129             $argc   = count($args);
       
   130             $action = $matches['action'];
       
   131             $type   = $matches['type'];
       
   132             $index  = null;
       
   133 
       
   134             if ('offsetSet' == $action) {
       
   135                 if (0 < $argc) {
       
   136                     $index = array_shift($args);
       
   137                     --$argc;
       
   138                 }
       
   139             }
       
   140 
       
   141             if (1 > $argc) {
       
   142                 require_once 'Zend/View/Exception.php';
       
   143                 $e =  new Zend_View_Exception(sprintf('%s requires at least one argument', $method));
       
   144                 $e->setView($this->view);
       
   145                 throw $e;
       
   146             }
       
   147 
       
   148             if (is_array($args[0])) {
       
   149                 $item = $this->createData($args[0]);
       
   150             } else {
       
   151                 $dataMethod = 'createData' . $type;
       
   152                 $item       = $this->$dataMethod($args);
       
   153             }
       
   154 
       
   155             if ($item) {
       
   156                 if ('offsetSet' == $action) {
       
   157                     $this->offsetSet($index, $item);
       
   158                 } else {
       
   159                     $this->$action($item);
       
   160                 }
       
   161             }
       
   162 
       
   163             return $this;
       
   164         }
       
   165 
       
   166         return parent::__call($method, $args);
       
   167     }
       
   168 
       
   169     /**
       
   170      * Check if value is valid
       
   171      *
       
   172      * @param  mixed $value
       
   173      * @return boolean
       
   174      */
       
   175     protected function _isValid($value)
       
   176     {
       
   177         if (!$value instanceof stdClass) {
       
   178             return false;
       
   179         }
       
   180 
       
   181         $vars         = get_object_vars($value);
       
   182         $keys         = array_keys($vars);
       
   183         $intersection = array_intersect($this->_itemKeys, $keys);
       
   184         if (empty($intersection)) {
       
   185             return false;
       
   186         }
       
   187 
       
   188         return true;
       
   189     }
       
   190 
       
   191     /**
       
   192      * append()
       
   193      *
       
   194      * @param  array $value
       
   195      * @return void
       
   196      */
       
   197     public function append($value)
       
   198     {
       
   199         if (!$this->_isValid($value)) {
       
   200             require_once 'Zend/View/Exception.php';
       
   201             $e = new Zend_View_Exception('append() expects a data token; please use one of the custom append*() methods');
       
   202             $e->setView($this->view);
       
   203             throw $e;
       
   204         }
       
   205 
       
   206         return $this->getContainer()->append($value);
       
   207     }
       
   208 
       
   209     /**
       
   210      * offsetSet()
       
   211      *
       
   212      * @param  string|int $index
       
   213      * @param  array $value
       
   214      * @return void
       
   215      */
       
   216     public function offsetSet($index, $value)
       
   217     {
       
   218         if (!$this->_isValid($value)) {
       
   219             require_once 'Zend/View/Exception.php';
       
   220             $e = new Zend_View_Exception('offsetSet() expects a data token; please use one of the custom offsetSet*() methods');
       
   221             $e->setView($this->view);
       
   222             throw $e;
       
   223         }
       
   224 
       
   225         return $this->getContainer()->offsetSet($index, $value);
       
   226     }
       
   227 
       
   228     /**
       
   229      * prepend()
       
   230      *
       
   231      * @param  array $value
       
   232      * @return Zend_Layout_ViewHelper_HeadLink
       
   233      */
       
   234     public function prepend($value)
       
   235     {
       
   236         if (!$this->_isValid($value)) {
       
   237             require_once 'Zend/View/Exception.php';
       
   238             $e = new Zend_View_Exception('prepend() expects a data token; please use one of the custom prepend*() methods');
       
   239             $e->setView($this->view);
       
   240             throw $e;
       
   241         }
       
   242 
       
   243         return $this->getContainer()->prepend($value);
       
   244     }
       
   245 
       
   246     /**
       
   247      * set()
       
   248      *
       
   249      * @param  array $value
       
   250      * @return Zend_Layout_ViewHelper_HeadLink
       
   251      */
       
   252     public function set($value)
       
   253     {
       
   254         if (!$this->_isValid($value)) {
       
   255             require_once 'Zend/View/Exception.php';
       
   256             $e = new Zend_View_Exception('set() expects a data token; please use one of the custom set*() methods');
       
   257             $e->setView($this->view);
       
   258             throw $e;
       
   259         }
       
   260 
       
   261         return $this->getContainer()->set($value);
       
   262     }
       
   263 
       
   264 
       
   265     /**
       
   266      * Create HTML link element from data item
       
   267      *
       
   268      * @param  stdClass $item
       
   269      * @return string
       
   270      */
       
   271     public function itemToString(stdClass $item)
       
   272     {
       
   273         $attributes = (array) $item;
       
   274         $link       = '<link ';
       
   275 
       
   276         foreach ($this->_itemKeys as $itemKey) {
       
   277             if (isset($attributes[$itemKey])) {
       
   278                 if(is_array($attributes[$itemKey])) {
       
   279                     foreach($attributes[$itemKey] as $key => $value) {
       
   280                         $link .= sprintf('%s="%s" ', $key, ($this->_autoEscape) ? $this->_escape($value) : $value);
       
   281                     }
       
   282                 } else {
       
   283                     $link .= sprintf('%s="%s" ', $itemKey, ($this->_autoEscape) ? $this->_escape($attributes[$itemKey]) : $attributes[$itemKey]);
       
   284                 }
       
   285             }
       
   286         }
       
   287 
       
   288         if ($this->view instanceof Zend_View_Abstract) {
       
   289             $link .= ($this->view->doctype()->isXhtml()) ? '/>' : '>';
       
   290         } else {
       
   291             $link .= '/>';
       
   292         }
       
   293 
       
   294         if (($link == '<link />') || ($link == '<link >')) {
       
   295             return '';
       
   296         }
       
   297 
       
   298         if (isset($attributes['conditionalStylesheet'])
       
   299             && !empty($attributes['conditionalStylesheet'])
       
   300             && is_string($attributes['conditionalStylesheet']))
       
   301         {
       
   302             $link = '<!--[if ' . $attributes['conditionalStylesheet'] . ']> ' . $link . '<![endif]-->';
       
   303         }
       
   304 
       
   305         return $link;
       
   306     }
       
   307 
       
   308     /**
       
   309      * Render link elements as string
       
   310      *
       
   311      * @param  string|int $indent
       
   312      * @return string
       
   313      */
       
   314     public function toString($indent = null)
       
   315     {
       
   316         $indent = (null !== $indent)
       
   317                 ? $this->getWhitespace($indent)
       
   318                 : $this->getIndent();
       
   319 
       
   320         $items = array();
       
   321         $this->getContainer()->ksort();
       
   322         foreach ($this as $item) {
       
   323             $items[] = $this->itemToString($item);
       
   324         }
       
   325 
       
   326         return $indent . implode($this->_escape($this->getSeparator()) . $indent, $items);
       
   327     }
       
   328 
       
   329     /**
       
   330      * Create data item for stack
       
   331      *
       
   332      * @param  array $attributes
       
   333      * @return stdClass
       
   334      */
       
   335     public function createData(array $attributes)
       
   336     {
       
   337         $data = (object) $attributes;
       
   338         return $data;
       
   339     }
       
   340 
       
   341     /**
       
   342      * Create item for stylesheet link item
       
   343      *
       
   344      * @param  array $args
       
   345      * @return stdClass|false Returns fals if stylesheet is a duplicate
       
   346      */
       
   347     public function createDataStylesheet(array $args)
       
   348     {
       
   349         $rel                   = 'stylesheet';
       
   350         $type                  = 'text/css';
       
   351         $media                 = 'screen';
       
   352         $conditionalStylesheet = false;
       
   353         $href                  = array_shift($args);
       
   354 
       
   355         if ($this->_isDuplicateStylesheet($href)) {
       
   356             return false;
       
   357         }
       
   358 
       
   359         if (0 < count($args)) {
       
   360             $media = array_shift($args);
       
   361             if(is_array($media)) {
       
   362                 $media = implode(',', $media);
       
   363             } else {
       
   364                 $media = (string) $media;
       
   365             }
       
   366         }
       
   367         if (0 < count($args)) {
       
   368             $conditionalStylesheet = array_shift($args);
       
   369             if(!empty($conditionalStylesheet) && is_string($conditionalStylesheet)) {
       
   370                 $conditionalStylesheet = (string) $conditionalStylesheet;
       
   371             } else {
       
   372                 $conditionalStylesheet = null;
       
   373             }
       
   374         }
       
   375 
       
   376         if(0 < count($args) && is_array($args[0])) {
       
   377             $extras = array_shift($args);
       
   378             $extras = (array) $extras;
       
   379         }
       
   380 
       
   381         $attributes = compact('rel', 'type', 'href', 'media', 'conditionalStylesheet', 'extras');
       
   382         return $this->createData($attributes);
       
   383     }
       
   384 
       
   385     /**
       
   386      * Is the linked stylesheet a duplicate?
       
   387      *
       
   388      * @param  string $uri
       
   389      * @return bool
       
   390      */
       
   391     protected function _isDuplicateStylesheet($uri)
       
   392     {
       
   393         foreach ($this->getContainer() as $item) {
       
   394             if (($item->rel == 'stylesheet') && ($item->href == $uri)) {
       
   395                 return true;
       
   396             }
       
   397         }
       
   398         return false;
       
   399     }
       
   400 
       
   401     /**
       
   402      * Create item for alternate link item
       
   403      *
       
   404      * @param  array $args
       
   405      * @return stdClass
       
   406      */
       
   407     public function createDataAlternate(array $args)
       
   408     {
       
   409         if (3 > count($args)) {
       
   410             require_once 'Zend/View/Exception.php';
       
   411             $e = new Zend_View_Exception(sprintf('Alternate tags require 3 arguments; %s provided', count($args)));
       
   412             $e->setView($this->view);
       
   413             throw $e;
       
   414         }
       
   415 
       
   416         $rel   = 'alternate';
       
   417         $href  = array_shift($args);
       
   418         $type  = array_shift($args);
       
   419         $title = array_shift($args);
       
   420 
       
   421         if(0 < count($args) && is_array($args[0])) {
       
   422             $extras = array_shift($args);
       
   423             $extras = (array) $extras;
       
   424 
       
   425             if(isset($extras['media']) && is_array($extras['media'])) {
       
   426                 $extras['media'] = implode(',', $extras['media']);
       
   427             }
       
   428         }
       
   429 
       
   430         $href  = (string) $href;
       
   431         $type  = (string) $type;
       
   432         $title = (string) $title;
       
   433 
       
   434         $attributes = compact('rel', 'href', 'type', 'title', 'extras');
       
   435         return $this->createData($attributes);
       
   436     }
       
   437 }