WPDK  1.5.0
WordPress Development Kit
 All Data Structures Files Functions Variables Pages
wpdk-html-tag.php
Go to the documentation of this file.
1 <?php
13 class WPDKHTMLTag extends WPDKObject {
14 
22  public $__version = '1.1.1';
23 
35  // Global attributes
36 
37  public $accesskey = '';
38  public $class = array();
39 
47  public $content = '';
49  public $contextmenu;
50 
58  public $data = array();
59  public $dir;
60  public $draggable;
61  public $dropzone;
62  public $hidden;
63  public $id;
64  public $lang;
65  public $onclick;
66  public $spellcheck;
67  public $style;
68  public $tabindex;
69 
77  public $tagName;
78 
79  /* Global events */
80  public $title;
81 
89  protected $attributes = array();
90 
98  protected $close;
99 
107  protected $open;
108 
116  private $_globalAttributes;
117 
125  public function __construct( $tag_name )
126  {
127  // Store this tag name
128  $this->tagName = $tag_name;
129 
130  // The global attributes below can be used on any HTML element
131  $this->_globalAttributes = array(
132  'accesskey',
133  'class',
134  'contenteditable', // HTML 5
135  'contextmenu', // HTML 5
136  'dir',
137  'draggable', // HTML 5
138  'dropzone', // HTML 5
139  'hidden', // HTML 5
140  'id',
141  'lang',
142  'spellcheck', // HTML 5
143  'style',
144  'tabindex',
145  'title',
146  'onclick'
147  );
148  }
149 
158  public function addData( $name, $value )
159  {
160  if ( !empty( $name ) ) {
161  $this->data[$name] = $value;
162  }
163  }
164 
173  public function addClass( $class )
174  {
175  if ( !empty( $class ) ) {
176  $this->class[$class] = $class;
177  }
178  }
179 
185  public function display()
186  {
187  echo $this->html();
188  }
189 
197  public function html() {
198  ob_start();
199 
200  // Open the tag
201  echo $this->open;
202 
203  // Cycle for tag specify attributes
204  foreach ( $this->attributes as $attr ) {
205  if ( isset( $this->$attr ) && !is_null( $this->$attr ) ) {
206  printf( ' %s="%s"', $attr, htmlspecialchars( stripslashes( $this->$attr ) ) );
207  }
208  }
209 
210  // Cycle for global common attributes
211  foreach ( $this->_globalAttributes as $attr ) {
212  if ( isset( $this->$attr ) && !is_null( $this->$attr ) ) {
213  if ( 'class' == $attr ) {
214  $classes = self::classInline( $this->$attr );
215  if( !empty( $classes ) ) {
216  printf( ' class="%s"', $classes );
217  }
218  }
219  else {
220  printf( ' %s="%s"', $attr, htmlspecialchars( stripslashes( $this->$attr ) ) );
221  }
222  }
223  }
224 
225  // Generic data attribute
226  $data = self::dataInline( $this->data );
227  if ( !empty( $data ) ) {
228  printf( ' %s', $data );
229  }
230 
231  // Content, only for enclousure TAG
232  if ( '/>' !== $this->close ) {
233 
234  // Close the first part tag
235  echo '>';
236 
237  // Before content
238  $this->beforeContent();
239 
240  // Content
241  $this->draw();
242 
243  // After content
244  $this->afterContent();
245 
246  // Close
247  echo $this->close;
248  }
249 
250  // Close
251  else {
252  echo $this->close;
253  echo $this->content;
254  }
255 
256  $content = ob_get_contents();
257  ob_end_clean();
258 
259  return $content;
260  }
261 
267  protected function beforeContent()
268  {
269  /* to override if needed */
270  }
271 
279  public function draw()
280  {
281  echo $this->content;
282  }
283 
289  protected function afterContent()
290  {
291  /* to override if needed */
292  }
293 
301  public function setPropertiesByArray( $properties = array() ) {
302  if ( !empty( $properties ) ) {
303  foreach ( $properties as $key => $value ) {
304  if ( in_array( $key, $this->attributes ) || in_array( $key, $this->_globalAttributes ) ) {
305  $this->$key = $value;
306  }
307  }
308  }
309  }
310 
311  // -------------------------------------------------------------------------------------------------------------------
312  // SANITIZE
313  // -------------------------------------------------------------------------------------------------------------------
314 
327  public static function sanitizeAttributes( $attributes )
328  {
329  $stack = array();
330  if ( is_string( $attributes ) && !empty( $attributes ) ) {
331  $single_attrobutes = explode( ' ', $attributes );
332  foreach ( $single_attrobutes as $attribute ) {
333  $parts = explode( '=', $attribute );
334  $stack[$parts[0]] = trim( $parts[1], "\"''" );
335  }
336  }
337 
338  if ( is_array( $attributes ) ) {
339  return $attributes;
340  }
341 
342  return $stack;
343  }
344 
357  public static function sanitizeData( $attributes )
358  {
359  $stack = array();
360  if ( is_string( $attributes ) && !empty( $attributes ) ) {
361  $single_attrobutes = explode( ' ', $attributes );
362  foreach ( $single_attrobutes as $attribute ) {
363  $parts = explode( '=', $attribute );
364  $key = $parts[0];
365  if ( 'data-' == substr( $key, 0, 5 ) ) {
366  $key = substr( $key, 5 );
367  }
368  $stack[$key] = trim( $parts[1], "\"''" );
369  }
370  }
371 
372  if ( is_array( $attributes ) ) {
373  foreach ( $attributes as $key => $value ) {
374  if ( 'data-' == substr( $key, 0, 5 ) ) {
375  $key = substr( $key, 5 );
376  }
377  $stack[$key] = trim( $value, "\"''" );
378  }
379  }
380 
381  return $stack;
382  }
383 
403  public static function sanitizeClasses( $classes )
404  {
405  if( empty( $classes) || is_null( $classes ) ) {
406  return array();
407  }
408 
409  // Convert the string classes in array
410  if ( is_string( $classes ) ) {
411  $classes = explode( ' ', $classes );
412  }
413 
414  $classes = array_filter( array_unique( $classes, SORT_STRING ) );
415 
416  return array_combine( $classes, $classes );
417  }
418 
438  public static function sanitizeStyles( $styles )
439  {
440  if ( empty( $styles ) || is_null( $styles ) ) {
441  return array();
442  }
443 
444  // Convert the string styles in array
445  if ( is_string( $styles ) ) {
446  $entries = explode( ';', $styles );
447  $styles = array();
448  foreach ( $entries as $entry ) {
449  list( $key, $value ) = explode( ':', $entry, 2 );
450  $styles[$key] = trim( $value );
451  }
452  }
453 
454  return array_unique( $styles, SORT_STRING );
455  }
456 
457  // -------------------------------------------------------------------------------------------------------------------
458  // INLINE
459  // -------------------------------------------------------------------------------------------------------------------
460 
478  public static function attributeInline( $attributes, $additional_attributes = false )
479  {
480 
481  $attributes = self::sanitizeAttributes( $attributes );
482 
483  if ( !empty( $additional_attributes ) ) {
484  $additional_attributes = self::sanitizeAttributes( $additional_attributes );
485  $attributes = array_merge( $attributes, $additional_attributes );
486  }
487  $stack = array();
488  foreach ( $attributes as $key => $value ) {
489  $stack[] = sprintf( '%s="%s"', $key, htmlspecialchars( stripslashes( $value ) ) );
490  }
491  return join( ' ', $stack );
492  }
493 
511  public static function dataInline( $data, $additional_data = false )
512  {
513  $data = self::sanitizeData( $data );
514 
515  if ( !empty( $additional_data ) ) {
516  $additional_data = self::sanitizeData( $additional_data );
517  $data = array_merge( $data, $additional_data );
518  }
519  $stack = array();
520  foreach ( $data as $key => $value ) {
521  $stack[] = sprintf( 'data-%s="%s"', $key, htmlspecialchars( stripslashes( $value ) ) );
522  }
523  return join( ' ', $stack );
524  }
525 
546  public static function classInline( $classes, $additional_classes = false )
547  {
548  $classes = self::sanitizeClasses( $classes );
549 
550  if ( !empty( $additional_classes ) ) {
551  $additional_classes = self::sanitizeClasses( $additional_classes );
552  if ( !empty( $additional_classes ) ) {
553  $classes = array_merge( $classes, $additional_classes );
554  }
555  }
556 
557  $keys = array_keys( $classes );
558 
559  return join( ' ', $keys );
560  }
561 
583  public static function styleInline( $styles, $additional_styles = false )
584  {
585  $styles = self::sanitizeStyles( $styles );
586 
587  if ( !empty( $additional_styles ) ) {
588  $additional_styles = self::sanitizeStyles( $additional_styles );
589  if ( !empty( $additional_styles ) ) {
590  $styles = array_merge( $styles, $additional_styles );
591  }
592  }
593 
594  $result = array();
595  foreach ( $styles as $key => $value ) {
596  $result[] = $key . ':' . $value;
597  }
598 
599  return rtrim( implode( ';', $result ), ';' );
600 
601  }
602 
603  // -------------------------------------------------------------------------------------------------------------------
604  // UTILITIES
605  // -------------------------------------------------------------------------------------------------------------------
606 
619  public static function mergeClasses( $class, $class2 = null, $_ = null )
620  {
621  $class = self::sanitizeClasses( $class );
622 
623  if ( func_num_args() < 2 ) {
624  return $class;
625  }
626 
627  for ( $i = 1; $i < func_num_args(); $i++ ) {
628  $arg = func_get_arg( $i );
629  if ( !is_null( $arg ) ) {
630  $s = self::sanitizeClasses( $arg );
631  $class = array_merge( $class, $s );
632  }
633  }
634  return self::sanitizeClasses( $class );
635  }
636 
637 }
638 
649 
650  // HTML 4.1 tags
651  const A = 'a';
652  const BUTTON = 'button';
653  const FIELDSET = 'fieldset';
654  const FORM = 'form';
655  const IMG = 'img';
656  const INPUT = 'input';
657  const LABEL = 'label';
658  const LEGEND = 'legend';
659  const SELECT = 'select';
660  const SPAN = 'span';
661  const TEXTAREA = 'textarea';
662 }
663 
674 
675  // Input types
676  const BUTTON = 'button';
677  const CHECKBOX = 'checkbox';
678  const COLOR = 'color';
679  const DATE = 'date';
680  const DATETIME = 'datetime';
681  const DATETIME_LOCAL = 'datetime-local';
682  const EMAIL = 'email';
683  const FILE = 'file';
684  const HIDDEN = 'hidden';
685  const IMAGE = 'image';
686  const MONTH = 'month';
687  const NUMBER = 'number';
688  const PASSWORD = 'password';
689  const RADIO = 'radio';
690  const RANGE = 'range';
691  const RESET = 'reset';
692  const SEARCH = 'search';
693  const SUBMIT = 'submit';
694  const TEL = 'tel';
695  const TEXT = 'text';
696  const TIME = 'time';
697  const URL = 'url';
698  const WEEK = 'week';
699 }
700 
712 class WPDKHTMLTagA extends WPDKHTMLTag {
713 
721  public $charset;
729  public $coords;
737  public $href;
745  public $hreflang;
753  public $media;
761  public $name;
771  public $rel;
779  public $rev;
787  public $shape;
795  public $target;
803  public $type;
804 
813  public function __construct( $content = '', $href = '' ) {
814 
815  // Create an WPDKHTMLTag instance
816  parent::__construct( WPDKHTMLTagName::A );
817 
818  // The content
819  $this->content = $content;
820 
821  // The href. Late binding
822  $this->href = $href;
823 
824  // Setting
825  $this->open = '<a';
826  $this->close = '</a>';
827  $this->attributes = array(
828  'charset',
829  'coords',
830  'href',
831  'hreflang',
832  'media',
833  // HTML 5
834  'name',
835  'rel',
836  'rev',
837  'shape',
838  'target',
839  'type'
840  // HTML 5
841  );
842  }
843 
844 }
845 
858 
859  /* Interface. */
860 
869  public $autofocus;
870 
876  public $disabled;
884  public $form;
893  public $formaction;
902  public $formenctype;
911  public $formmethod;
928  public $formtarget;
929 
937  public $name;
938 
946  public $type;
947 
955  public $value;
956 
964  public function __construct( $content = '' )
965  {
966 
967  // Create an WPDKHTMLTag instance
968  parent::__construct( WPDKHTMLTagName::BUTTON );
969 
970  // The content
971  $this->content = $content;
972 
973  // Setting
974  $this->open = '<button';
975  $this->close = '</button>';
976  $this->attributes = array(
977  'autofocus',
978  'disabled',
979  'form',
980  'formaction',
981  'formenctype',
982  'formmethod',
983  'formnovalidate',
984  'formtarget',
985  'name',
986  'type',
987  'value'
988  );
989  }
990 
991 }
992 
1006 
1007  /* Interface. */
1008 
1016  public $disabled;
1024  public $form;
1033  public $legend;
1041  public $name;
1042 
1051  public function __construct( $content = '', $legend = '' ) {
1052 
1053  /* Create an WPDKHTMLTag instance. */
1054  parent::__construct( WPDKHTMLTagName::FIELDSET );
1055 
1056  /* The content. */
1057  $this->content = $content;
1058 
1059  /* Legend. */
1060  if ( !empty( $legend ) ) {
1061  $this->legend = new WPDKHTMLTagLegend( $legend );
1062  }
1063 
1064  /* Setting. */
1065  $this->open = '<fieldset';
1066  $this->close = '</fieldset>';
1067  $this->attributes = array(
1068  'disabled',
1069  'form',
1070  'name'
1071  );
1072  }
1073 
1074  // -------------------------------------------------------------------------------------------------------------------
1075  // Over-riding
1076  // -------------------------------------------------------------------------------------------------------------------
1077 
1078  public function beforeContent()
1079  {
1080  if ( !empty( $this->legend ) ) {
1081  $this->legend->display();
1082  }
1083  }
1084 
1085 }
1086 
1099 
1108  public $accept;
1109 
1118 
1126  public $action;
1127 
1136 
1145  public $enctype;
1146 
1154  public $method;
1155 
1163  public $name;
1164 
1172  public $novalidate;
1173 
1182  public $target;
1183 
1193  public function __construct( $content = '' )
1194  {
1195  // Create an WPDKHTMLTag instance
1196  parent::__construct( WPDKHTMLTagName::FORM );
1197 
1198  // The content
1199  $this->content = $content;
1200 
1201  // Setting
1202  $this->open = '<form';
1203  $this->close = '</form>';
1204  $this->attributes = array(
1205  'accept',
1206  'accept-charset',
1207  'action',
1208  'autocomplete',
1209  'enctype',
1210  'method',
1211  'name',
1212  'novalidate',
1213  'target'
1214  );
1215  }
1216 }
1217 
1218 
1232 
1233  /* Interface. */
1234 
1240  public $alt;
1241 
1249 
1255  public $height;
1256 
1262  public $ismap;
1263 
1269  public $src;
1270 
1276  public $usemap;
1277 
1283  public $width;
1284 
1297  public function __construct( $src = '', $alt = '', $width = '', $height = '' )
1298  {
1299  /* Create an WPDKHTMLTag instance. */
1300  parent::__construct( WPDKHTMLTagName::IMG );
1301 
1302  $this->src = $src;
1303  $this->alt = $alt;
1304  $this->width = $width;
1305  $this->height = $height;
1306 
1307  /* Setting. */
1308  $this->open = '<img';
1309  $this->close = '/>';
1310  $this->attributes = array(
1311  'alt',
1312  'crossorigin',
1313  'height',
1314  'ismap',
1315  'src',
1316  'usemap',
1317  'width',
1318  );
1319  }
1320 
1321 }
1322 
1323 
1336 
1337  /* Interface. */
1338 
1346  public $accept;
1358  public $align;
1366  public $alt;
1383  public $autofocus;
1392  public $checked;
1400  public $disabled;
1408  public $form;
1417  public $formaction;
1435  public $formmethod;
1450  public $formtarget;
1458  public $height;
1465  public $list;
1473  public $max;
1481  public $maxlength;
1489  public $min;
1497  public $multiple;
1505  public $name;
1513  public $pattern;
1529  public $readonly;
1537  public $required;
1545  public $size;
1553  public $src;
1561  public $step;
1569  public $type;
1577  public $value;
1585  public $width;
1586 
1596  public function __construct( $content = '', $name = '', $id = '' ) {
1597 
1598  // Create an WPDKHTMLTag instance
1599  parent::__construct( WPDKHTMLTagName::INPUT );
1600 
1601  // The content
1602  $this->content = $content;
1603 
1604  // Set name
1605  if ( !empty( $name ) ) {
1606  $this->name = $name;
1607  }
1608 
1609  // To default, if $name exists and $id not exists, then $id = $name
1610  if ( !empty( $name ) && empty( $id ) ) {
1611 
1612  // Check if field is an array
1613  if ( '[]' == substr( $name, -2 ) ) {
1614 
1615  // Sanitize id
1616  $this->id = substr( $name, 0, strlen( $name ) - 2 );
1617  }
1618 
1619  else {
1620  $this->id = $name;
1621  }
1622  }
1623 
1624  // This is the case where $name = '' and $id != ''
1625  elseif ( !empty( $id ) ) {
1626  $this->id = $id;
1627  }
1628 
1629  // Setting
1630  $this->open = '<input';
1631  $this->close = '/>';
1632  $this->attributes = array(
1633  'accept',
1634  'align',
1635  'alt',
1636  'autocomplete',
1637  'autofocus',
1638  'checked',
1639  'disabled',
1640  'form',
1641  'formaction',
1642  'formenctype',
1643  'formmethod',
1644  'formnovalidate',
1645  'formtarget',
1646  'height',
1647  'list',
1648  'max',
1649  'maxlength',
1650  'min',
1651  'multiple',
1652  'name',
1653  'pattern',
1654  'placeholder',
1655  'readonly',
1656  'required',
1657  'size',
1658  'src',
1659  'step',
1660  'type',
1661  'value',
1662  'width'
1663  );
1664  }
1665 
1666 }
1667 
1681 
1682  /* Interface. */
1683 
1691  public $for;
1699  public $form;
1700 
1708  public function __construct( $content = '' ) {
1709 
1710  /* Create an WPDKHTMLTag instance. */
1711  parent::__construct( WPDKHTMLTagName::LABEL );
1712 
1713  /* The content. */
1714  $this->content = $content;
1715 
1716  /* Setting. */
1717  $this->open = '<label';
1718  $this->close = '</label>';
1719  $this->attributes = array(
1720  'for',
1721  'form'
1722  );
1723  }
1724 
1725 }
1726 
1739 
1740  /* Interface. */
1741 
1751  public $align;
1752 
1760  function __construct( $content = '' ) {
1761 
1762  /* Create an WPDKHTMLTag instance. */
1763  parent::__construct( WPDKHTMLTagName::LEGEND );
1764 
1765  /* The content. */
1766  $this->content = $content;
1767 
1768  /* Setting. */
1769  $this->open = '<legend';
1770  $this->close = '</legend>';
1771  $this->attributes = array(
1772  'align',
1773  );
1774  }
1775 
1776 }
1777 
1790 
1791  /* Interface. */
1792 
1793  public $autofocus;
1794  public $disabled;
1795  public $form;
1796  public $multiple;
1797  public $name;
1798  public $size;
1799  public $value;
1800 
1809  public $_first_item = '';
1810 
1811  private $_options;
1812 
1825  public function __construct( $options = array(), $name = '', $id = '' )
1826  {
1827 
1828  /* Create an WPDKHTMLTag instance. */
1829  parent::__construct( WPDKHTMLTagName::SELECT );
1830 
1831  /* Store the options for draw later. */
1832  $this->_options = $options;
1833 
1834  /* Set name. */
1835  if ( !empty( $name ) ) {
1836  $this->name = $name;
1837  }
1838 
1839  /* To default, if $name exists and $id not exists, then $id = $name. */
1840  if ( !empty( $name ) && empty( $id ) ) {
1841  /* Check if field is an array. */
1842  if ( '[]' == substr( $name, -2 ) ) {
1843  /* Sanitize id. */
1844  $this->id = substr( $name, 0, strlen( $name ) - 2 );
1845  }
1846 
1847  else {
1848  $this->id = $name;
1849  }
1850  }
1851  /* This is the case where $name = '' and $id != '' */
1852  elseif ( !empty( $id ) ) {
1853  $this->id = $id;
1854  }
1855 
1856  /* Setting. */
1857  $this->open = '<select';
1858  $this->close = '</select>';
1859  $this->attributes = array(
1860  'autofocus',
1861  'disabled',
1862  'form',
1863  'multiple',
1864  'name',
1865  'size'
1866  );
1867  }
1868 
1874  public function draw()
1875  {
1876  $options = array();
1877  if ( is_callable( $this->_options ) ) {
1878  $options = call_user_func( $this->_options, $this );
1879  }
1880  elseif ( is_array( $this->_options ) ) {
1881  $options = $this->_options;
1882  }
1883  $this->content = $this->options( $options );
1884  parent::draw();
1885  }
1886 
1896  public function options( $options )
1897  {
1898  ob_start();
1899  $this->_options( $options );
1900  $content = ob_get_contents();
1901  ob_end_clean();
1902  return $content;
1903  }
1904 
1913  private function _options( $options )
1914  {
1915  if ( !empty( $this->_first_item ) ) : ?>
1916  <option value=""
1917  disabled="disabled"
1918  selected="selected"
1919  style="display:none"><?php echo $this->_first_item ?></option>
1920  <?php endif;
1921 
1922  foreach ( $options as $key => $option ) : ?>
1923  <?php if ( is_array( $option ) ) : ?>
1924  <optgroup class="wpdk-form-optiongroup" label="<?php echo $key ?>">
1925  <?php $this->_options( $option ); ?>
1926  </optgroup>
1927  <?php else : ?>
1928  <option class="wpdk-form-option" <?php if ( !empty( $this->value ) ) echo WPDKHTMLTagSelect::selected( $this->value, $key ) ?>
1929  value="<?php echo $key ?>"><?php echo $option ?></option>
1930  <?php endif; ?>
1931  <?php endforeach;
1932  }
1933 
1956  public static function selected( $haystack, $current )
1957  {
1958  if ( is_array( $haystack ) && in_array( $current, $haystack ) ) {
1959  $current = $haystack = 1;
1960  }
1961  return selected( $haystack, $current, false );
1962  }
1963 
1964 }
1965 
1978 
1979  /* Interface. */
1980 
1988  public function __construct( $content = '' ) {
1989 
1990  /* Create an WPDKHTMLTag instance. */
1991  parent::__construct( WPDKHTMLTagName::SPAN );
1992 
1993  /* The content. */
1994  $this->content = $content;
1995 
1996  /* Setting. */
1997  $this->open = '<span';
1998  $this->close = '</span>';
1999  $this->attributes = array();
2000  }
2001 
2002 }
2003 
2016 
2017  /* Interface. */
2018 
2026  public $autofocus;
2034  public $cols;
2042  public $disabled;
2050  public $form;
2058  public $maxlength;
2066  public $name;
2082  public $readonly;
2090  public $required;
2098  public $rows;
2107  public $wrap;
2108 
2120  public function __construct( $content = '', $name = '', $id = '' ) {
2121 
2122  /* Create an WPDKHTMLTag instance. */
2123  parent::__construct( WPDKHTMLTagName::TEXTAREA );
2124 
2125  /* The content. */
2126  $this->content = $content;
2127 
2128  /* Set name. */
2129  if ( !empty( $name ) ) {
2130  $this->name = $name;
2131  }
2132 
2133  /* To default, if $name exists and $id not exists, then $id = $name. */
2134  if ( !empty( $name ) && empty( $id ) ) {
2135  /* Check if field is an array. */
2136  if ( '[]' == substr( $name, -2 ) ) {
2137  /* Sanitize id. */
2138  $this->id = substr( $name, 0, strlen( $name ) - 2 );
2139  }
2140 
2141  else {
2142  $this->id = $name;
2143  }
2144  }
2145  /* This is the case where $name = '' and $id != '' */
2146  elseif ( !empty( $id ) ) {
2147  $this->id = $id;
2148  }
2149 
2150  /* Setting. */
2151  $this->open = '<textarea';
2152  $this->close = '</textarea>';
2153  $this->attributes = array(
2154  'autofocus',
2155  'cols',
2156  'disabled',
2157  'form',
2158  'maxlength',
2159  'name',
2160  'placeholder',
2161  'readonly',
2162  'required',
2163  'rows',
2164  'wrap'
2165  );
2166  }
2167 
2168 }