/app/helper/class-ms-helper-html.php

  1. <?php 
  2. /** 
  3. * Helper class for rendering HTML components. 
  4. * 
  5. * Methods for creating form INPUT components. 
  6. * Method for creating vertical tabbed navigation. 
  7. * 
  8. * @todo Create add methods to parent class or remove 'extends MS_Helper' to use standalone. 
  9. * 
  10. * @since 1.0.0 
  11. * 
  12. * @return object 
  13. */ 
  14. class MS_Helper_Html extends MS_Helper { 
  15.  
  16. /** Constants for default HTML input elements. */ 
  17. const INPUT_TYPE_HIDDEN = 'hidden'; 
  18. const INPUT_TYPE_TEXT_AREA = 'textarea'; 
  19. const INPUT_TYPE_SELECT = 'select'; 
  20. const INPUT_TYPE_RADIO = 'radio'; 
  21. const INPUT_TYPE_SUBMIT = 'submit'; 
  22. const INPUT_TYPE_BUTTON = 'button'; 
  23. const INPUT_TYPE_CHECKBOX = 'checkbox'; 
  24. const INPUT_TYPE_IMAGE = 'image'; 
  25. // Different input types 
  26. const INPUT_TYPE_TEXT = 'text'; 
  27. const INPUT_TYPE_PASSWORD = 'password'; 
  28. const INPUT_TYPE_NUMBER = 'number'; 
  29. const INPUT_TYPE_EMAIL = 'email'; 
  30. const INPUT_TYPE_URL = 'url'; 
  31. const INPUT_TYPE_TIME = 'time'; 
  32. const INPUT_TYPE_SEARCH = 'search'; 
  33. const INPUT_TYPE_FILE = 'file'; 
  34.  
  35. /** Constants for advanced HTML input elements. */ 
  36. const INPUT_TYPE_WP_EDITOR = 'wp_editor'; 
  37. const INPUT_TYPE_DATEPICKER = 'datepicker'; 
  38. const INPUT_TYPE_RADIO_SLIDER = 'radio_slider'; 
  39. const INPUT_TYPE_TAG_SELECT = 'tag_select'; 
  40. const INPUT_TYPE_WP_PAGES = 'wp_pages'; 
  41.  
  42. /** Constants for default HTML elements. */ 
  43. const TYPE_HTML_LINK = 'html_link'; 
  44. const TYPE_HTML_SEPARATOR = 'html_separator'; 
  45. const TYPE_HTML_TEXT = 'html_text'; 
  46. const TYPE_HTML_TABLE = 'html_table'; 
  47.  
  48. /** 
  49. * Method for creating HTML elements/fields. 
  50. * 
  51. * Pass in array with field arguments. See $defaults for argmuments. 
  52. * Use constants to specify field type. e.g. MS_Helper_Html::INPUT_TYPE_TEXT 
  53. * 
  54. * @since 1.0.0 
  55. * 
  56. * @return void|string If $return param is false the HTML will be echo'ed,  
  57. * otherwise returned as string 
  58. */ 
  59. public static function html_element( $field_args, $return = false ) { 
  60. return lib3()->html->element( $field_args, $return ); 
  61.  
  62.  
  63. /** 
  64. * Echo the header part of a settings form, including the title and 
  65. * description. 
  66. * 
  67. * @since 1.0.0 
  68. * 
  69. * @param array $args Title, description and breadcrumb infos. 
  70. */ 
  71. public static function settings_header( $args = null ) { 
  72. $defaults = array( 
  73. 'title' => '',  
  74. 'title_icon_class' => '',  
  75. 'desc' => '',  
  76. 'bread_crumbs' => null,  
  77. ); 
  78. $args = wp_parse_args( $args, $defaults ); 
  79. $args = apply_filters( 'ms_helper_html_settings_header_args', $args ); 
  80. extract( $args ); 
  81.  
  82. if ( ! is_array( $desc ) ) { 
  83. $desc = array( $desc ); 
  84.  
  85. MS_Helper_Html::bread_crumbs( $bread_crumbs ); 
  86. ?> 
  87. <h2 class="ms-settings-title"> 
  88. <?php if ( ! empty( $title_icon_class ) ) : ?> 
  89. <i class="<?php echo esc_attr( $title_icon_class ); ?>"></i> 
  90. <?php endif; ?> 
  91. <?php printf( $title ); ?> 
  92. </h2> 
  93. <div class="ms-settings-desc-wrapper"> 
  94. <?php foreach ( $desc as $description ) : ?> 
  95. <div class="ms-settings-desc ms-description"> 
  96. <?php printf( $description ); ?> 
  97. </div> 
  98. <?php endforeach; ?> 
  99. </div> 
  100. <?php 
  101.  
  102. /** 
  103. * Echo the footer section of a settings form. 
  104. * 
  105. * @since 1.0.0 
  106. * 
  107. * @param null|array $fields List of fields to display in the footer. 
  108. * @param bool|array $submit_info What kind of submit button to add. 
  109. */ 
  110. public static function settings_footer( $fields = null, $submit_info = null ) { 
  111. // Default Submit-Button is "Next >>" 
  112. if ( true === $submit_info ) { 
  113. $submit_info = array( 
  114. 'id' => 'next',  
  115. 'value' => __( 'Next', 'membership2' ),  
  116. 'action' => 'next',  
  117. ); 
  118.  
  119. if ( empty( $fields ) ) { 
  120. $fields = array(); 
  121.  
  122. if ( $submit_info ) { 
  123. $submit_fields = array( 
  124. 'next' => array( 
  125. 'id' => @$submit_info['id'],  
  126. 'type' => MS_Helper_Html::INPUT_TYPE_SUBMIT,  
  127. 'value' => @$submit_info['value'],  
  128. ),  
  129. 'action' => array( 
  130. 'id' => 'action',  
  131. 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN,  
  132. 'value' => @$submit_info['action'],  
  133. ),  
  134. '_wpnonce' => array( 
  135. 'id' => '_wpnonce',  
  136. 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN,  
  137. 'value' => wp_create_nonce( @$submit_info['action'] ),  
  138. ),  
  139. ); 
  140.  
  141. foreach ( $submit_fields as $key => $field ) { 
  142. if ( ! isset( $fields[ $key ] ) ) { 
  143. $fields[ $key ] = $field; 
  144.  
  145. $args = array( 
  146. 'saving_text' => __( 'Saving changes...', 'membership2' ),  
  147. 'saved_text' => __( 'All changes saved.', 'membership2' ),  
  148. 'error_text' => __( 'Could not save changes.', 'membership2' ),  
  149. 'fields' => $fields,  
  150. ); 
  151. $args = apply_filters( 'ms_helper_html_settings_footer_args', $args ); 
  152. $fields = $args['fields']; 
  153. unset( $args['fields'] ); 
  154.  
  155. ?> 
  156. <div class="ms-settings-footer"> 
  157. <form method="post" action=""> 
  158. <?php 
  159. foreach ( $fields as $field ) { 
  160. MS_Helper_Html::html_element( $field ); 
  161. self::save_text( $args ); 
  162. ?> 
  163. </form> 
  164. </div> 
  165. </div> 
  166. <?php 
  167.  
  168. public static function settings_tab_header( $args = null ) { 
  169. $defaults = array( 
  170. 'title' => '',  
  171. 'desc' => array(),  
  172. 'class' => '',  
  173. ); 
  174.  
  175. $args = wp_parse_args( $args, $defaults ); 
  176. $args = apply_filters( 'ms_helper_html_settings_header_args', $args ); 
  177. extract( $args ); 
  178.  
  179. if ( ! is_array( $desc ) ) { 
  180. $desc = array( $desc ); 
  181. foreach ( $desc as $id => $text ) { 
  182. if ( empty( $text ) ) { unset( $desc[$id] ); } 
  183.  
  184. ?> 
  185. <div class="ms-settings-wrapper <?php echo esc_attr( $class ); ?>"> 
  186. <?php if ( ! empty( $title ) || ! empty( $desc ) ) : ?> 
  187. <div class="ms-header"> 
  188. <?php if ( ! empty( $title ) ) : ?> 
  189. <div class="ms-settings-tab-title"> 
  190. <h3><?php printf( $title ); ?></h3> 
  191. </div> 
  192. <?php endif; ?> 
  193.  
  194. <?php if ( ! empty( $desc ) ) : ?> 
  195. <div class="ms-settings-description"> 
  196. <?php foreach ( $desc as $description ): ?> 
  197. <div class="ms-description"> 
  198. <?php echo '' . $description; ?> 
  199. </div> 
  200. <?php endforeach; ?> 
  201. </div> 
  202. <?php endif; ?> 
  203.  
  204. <?php self::html_separator(); ?> 
  205. </div> 
  206. <?php endif; ?> 
  207. <?php 
  208.  
  209. /** 
  210. * Echo a single content box including the header and footer of the box. 
  211. * The fields-list will be used to render the box body. 
  212. * 
  213. * @since 1.0.0 
  214. * 
  215. * @param array $fields_in List of fields to render 
  216. * @param string $title Box title 
  217. * @param string $description Description to display 
  218. * @param string $state Toggle-state of the box: static/open/closed 
  219. */ 
  220. public static function settings_box( $fields_in, $title = '', $description = '', $state = 'static', $class = '' ) { 
  221. // If its a fields array, great, if not, make a fields array. 
  222. $fields = $fields_in; 
  223. if ( ! is_array( $fields_in ) ) { 
  224. $fields = array(); 
  225. $fields[] = $fields_in; 
  226.  
  227. self::settings_box_header( $title, $description, $state, $class ); 
  228. foreach ( $fields as $field ) { 
  229. MS_Helper_Html::html_element( $field ); 
  230. self::save_text(); 
  231. self::settings_box_footer(); 
  232.  
  233. /** 
  234. * Echo the header of a content box. That box has a similar layout to a 
  235. * normal WordPress meta-box. 
  236. * The box has a title and description and can optionally be collapsible. 
  237. * 
  238. * @since 1.0.0 
  239. * @param string $title Box title displayed in the top 
  240. * @param string $description Description to display 
  241. * @param string $state Toggle-state of the box: static/open/closed 
  242. */ 
  243. public static function settings_box_header( $title = '', $description = '', $state = 'static', $class = '' ) { 
  244. do_action( 'ms_helper_settings_box_header_init', $title, $description, $state ); 
  245.  
  246. $handle = ''; 
  247. if ( 'static' !== $state ) { 
  248. $state = ('closed' === $state ? 'closed' : 'open'); 
  249. $handle = sprintf( 
  250. '<div class="handlediv" title="%s"></div>',  
  251. __( 'Click to toggle' ) // Intentionally no text-domain, so we use WordPress default translation. 
  252. ); 
  253. $box_class = $state; 
  254. if ( ! strlen( $title ) && ! strlen( $description ) ) { 
  255. $box_class .= ' nohead'; 
  256.  
  257. ?> 
  258. <div class="ms-settings-box-wrapper <?php echo esc_attr( $class ); ?>"> 
  259. <div class="ms-settings-box <?php echo esc_attr( $box_class ); ?>"> 
  260. <div class="ms-header"> 
  261. <?php printf( $handle ); ?> 
  262. <?php if ( ! empty( $title ) ) : ?> 
  263. <h3><?php printf( $title ); ?></h3> 
  264. <?php endif; ?> 
  265. <?php if ( ! empty( $description ) ) : ?> 
  266. <span class="ms-settings-description ms-description"><?php echo '' . $description; ?></span> 
  267. <?php endif; ?> 
  268. </div> 
  269. <div class="inside"> 
  270. <?php 
  271. do_action( 'ms_helper_settings_box_header_end', $title, $description, $state ); 
  272.  
  273. /** 
  274. * Echo the footer of a content box. 
  275. * 
  276. * @since 1.0.0 
  277. */ 
  278. public static function settings_box_footer() { 
  279. do_action( 'ms_helper_settings_box_footer_init' ); 
  280. ?> 
  281. </div> <!-- .inside --> 
  282. </div> <!-- .ms-settings-box --> 
  283. </div> <!-- .ms-settings-box-wrapper --> 
  284. <?php 
  285. do_action( 'ms_helper_settings_box_footer_end' ); 
  286.  
  287. /** 
  288. * Method for creating submit button. 
  289. * 
  290. * Pass in array with field arguments. See $defaults for argmuments. 
  291. * 
  292. * @since 1.0.0 
  293. * 
  294. * @return void But does output HTML. 
  295. */ 
  296. public static function html_submit( $args = array(), $return = false ) { 
  297. $defaults = array( 
  298. 'id' => 'submit',  
  299. 'value' => __( 'Save Changes', 'membership2' ),  
  300. 'class' => 'button button-primary',  
  301. ); 
  302. wp_parse_args( $args, $defaults ); 
  303.  
  304. $args['type'] = self::INPUT_TYPE_SUBMIT; 
  305.  
  306. if ( $return ) { 
  307. return self::html_element( $args, true ); 
  308. } else { 
  309. self::html_element( $args ); 
  310.  
  311. /** 
  312. * Method for creating html link. 
  313. * 
  314. * Pass in array with link arguments. See $defaults for arguments. 
  315. * 
  316. * @since 1.0.0 
  317. * 
  318. * @return string But does output HTML. 
  319. */ 
  320. public static function html_link( $args = array(), $return = false ) { 
  321. $defaults = array( 
  322. 'id' => '',  
  323. 'title' => '',  
  324. 'value' => '',  
  325. 'class' => '',  
  326. 'url' => '',  
  327. ); 
  328. wp_parse_args( $args, $defaults ); 
  329.  
  330. $args['type'] = self::TYPE_HTML_LINK; 
  331.  
  332. if ( $return ) { 
  333. return self::html_element( $args, true ); 
  334. } else { 
  335. self::html_element( $args ); 
  336.  
  337. /** 
  338. * Method for outputting vertical tabs. 
  339. * 
  340. * Returns the active tab key. Vertical tabs need to be wrapped in additional code. 
  341. * 
  342. * @since 1.0.0 
  343. * 
  344. * @param array $tabs 
  345. * @param string $active_tab 
  346. * @param array $persistent 
  347. * @return string Active tab. 
  348. */ 
  349. public static function html_admin_vertical_tabs( $tabs, $active_tab = null, $persistent = array( 'edit' ) ) { 
  350. reset( $tabs ); 
  351. $first_key = key( $tabs ); 
  352.  
  353. // Setup navigation tabs. 
  354. if ( empty( $active_tab ) ) { 
  355. $active_tab = ! empty( $_GET['tab'] ) ? $_GET['tab'] : $first_key; 
  356.  
  357. if ( ! array_key_exists( $active_tab, $tabs ) ) { 
  358. $active_tab = $first_key; 
  359.  
  360. // Render tabbed interface. 
  361. ?> 
  362. <div class="ms-tab-container"> 
  363. <ul id="sortable-units" class="ms-tabs" style=""> 
  364. <?php foreach ( $tabs as $tab_name => $tab ) : 
  365. $tab_class = $tab_name == $active_tab ? 'active' : ''; 
  366. $title = esc_html( $tab['title'] ); 
  367. $url = $tab['url']; 
  368. $attributes = array(); 
  369.  
  370. foreach ( $persistent as $param ) { 
  371. lib3()->array->equip_request( $param ); 
  372. $value = $_REQUEST[ $param ]; 
  373. $url = esc_url_raw( 
  374. add_query_arg( $param, $value, $url ) 
  375. ); 
  376.  
  377. $attributes[] = 'class="ms-tab-link"'; 
  378. $attributes[] = 'href="' . esc_url( $url ) .'"'; 
  379. if ( isset( $tab['target'] ) ) { 
  380. $attributes[] = 'target="' . esc_attr( $tab['target'] ) .'"'; 
  381. if ( '_blank' == $tab['target'] ) { 
  382. $title .= ' <i class="wpmui-fa wpmui-fa-external-link-square"></i>'; 
  383. ?> 
  384. <li class="ms-tab <?php echo esc_attr( $tab_class ); ?>"> 
  385. <a <?php echo implode( ' ', $attributes ); ?>> 
  386. <?php echo $title; ?> 
  387. </a> 
  388. </li> 
  389. <?php endforeach; ?> 
  390. </ul> 
  391. </div> 
  392. <?php 
  393.  
  394. // Return current active tab. 
  395. return $active_tab; 
  396.  
  397. /** 
  398. * Method for outputting tooltips. 
  399. * 
  400. * @since 1.0.0 
  401. * 
  402. * @return string But does output HTML. 
  403. */ 
  404. public static function tooltip( $tip = '', $return = false ) { 
  405. if ( empty( $tip ) ) { 
  406. return; 
  407.  
  408. if ( $return ) { ob_start(); } 
  409. ?> 
  410. <div class="wpmui-tooltip-wrapper"> 
  411. <div class="wpmui-tooltip-info"><i class="wpmui-fa wpmui-fa-info-circle"></i></div> 
  412. <div class="wpmui-tooltip"> 
  413. <div class="wpmui-tooltip-button">×</div> 
  414. <div class="wpmui-tooltip-content"> 
  415. <?php printf( $tip ); ?> 
  416. </div> 
  417. </div> 
  418. </div> 
  419. <?php 
  420. if ( $return ) { return ob_get_clean(); } 
  421.  
  422. /** 
  423. * Echo HTML separator element. 
  424. * Vertical separators will be on the right side of the parent element. 
  425. * 
  426. * @since 1.0.0 
  427. * 
  428. * @param string $type Either 'horizontal' or 'vertical' 
  429. */ 
  430. public static function html_separator( $type = 'horizontal' ) { 
  431. lib3()->html->element( 
  432. array( 
  433. 'type' => self::TYPE_HTML_SEPARATOR,  
  434. 'value' => $type,  
  435. ); 
  436.  
  437. /** 
  438. * Echo HTML structure for save-text and animation. 
  439. * 
  440. * @since 1.0.0 
  441. * 
  442. * @param array $texts Optionally override the default save-texts. 
  443. * @param bool $return If set to true the HTML code will be returned. 
  444. * @param bool $animation If an animation should be displayed while saving. 
  445. */ 
  446. public static function save_text( $texts = array(), $animation = false, $return = false ) { 
  447. $defaults = array( 
  448. 'saving_text' => __( 'Saving changes...', 'membership2' ),  
  449. 'saved_text' => __( 'All changes saved.', 'membership2' ),  
  450. 'error_text' => __( 'Could not save changes.', 'membership2' ),  
  451. ); 
  452. extract( wp_parse_args( $texts, $defaults ) ); 
  453.  
  454. if ( $return ) { 
  455. $command = 'sprintf'; 
  456. } else { 
  457. $command = 'printf'; 
  458.  
  459. if ( $animation ) { 
  460. $saving_text = '<div class="loading-animation"></div> ' . $saved_text; 
  461.  
  462. return $command( 
  463. '<span class="ms-save-text-wrapper"> 
  464. <span class="ms-saving-text">%1$s</span> 
  465. <span class="ms-saved-text">%2$s</span> 
  466. <span class="ms-error-text">%3$s<span class="err-code"></span></span> 
  467. </span>',  
  468. $saving_text,  
  469. $saved_text,  
  470. $error_text 
  471. ); 
  472.  
  473. /** 
  474. * Used by the overview views to display a list of available content items. 
  475. * The items are typically formatted like a taglist via CSS. 
  476. * 
  477. * @since 1.0.0 
  478. * 
  479. * @param WP_Post $item The item to display. 
  480. * @param string $tag The tag will be wrapped inside this HTML tag. 
  481. */ 
  482. public static function content_tag( $item, $tag = 'li' ) { 
  483. $label = property_exists( $item, 'post_title' ) ? $item->post_title : $item->name; 
  484.  
  485. if ( ! empty( $item->id ) && is_a( $item, 'WP_Post' ) ) { 
  486. printf( 
  487. '<%1$s class="ms-content-tag"><a href="%3$s">%2$s</a></%1$s>',  
  488. esc_attr( $tag ),  
  489. esc_html( $label ),  
  490. get_edit_post_link( $item->id ) 
  491. ); 
  492. else { 
  493. printf( 
  494. '<%1$s class="ms-content-tag"><span>%2$s</span></%1$s>',  
  495. esc_attr( $tag ),  
  496. esc_html( $label ) 
  497. ); 
  498.  
  499. /** 
  500. * Return bread crumb navigation HTML code. 
  501. * 
  502. * @since 1.0.0 
  503. * @param array $bread_crumbs 
  504. * @return string 
  505. */ 
  506. public static function bread_crumbs( $bread_crumbs ) { 
  507. $crumbs = array(); 
  508. $html = ''; 
  509.  
  510. if ( is_array( $bread_crumbs ) ) { 
  511. foreach ( $bread_crumbs as $key => $bread_crumb ) { 
  512. if ( ! empty( $bread_crumb['url'] ) ) { 
  513. $crumbs[] = sprintf( 
  514. '<span class="ms-bread-crumb-%s"><a href="%s">%s</a></span>',  
  515. esc_attr( $key ),  
  516. $bread_crumb['url'],  
  517. $bread_crumb['title'] 
  518. ); 
  519. elseif ( ! empty( $bread_crumb['title'] ) ) { 
  520. $crumbs[] = sprintf( 
  521. '<span class="ms-bread-crumb-%s">%s</span>',  
  522. esc_attr( $key ),  
  523. $bread_crumb['title'] 
  524. ); 
  525.  
  526. if ( count( $crumbs ) > 0 ) { 
  527. $html = '<div class="ms-bread-crumb">'; 
  528. $html .= implode( '<span class="ms-bread-crumb-sep"> » </span>', $crumbs ); 
  529. $html .= '</div>'; 
  530. $html = apply_filters( 'ms_helper_html_bread_crumbs', $html ); 
  531.  
  532. printf( $html ); 
  533.  
  534. /** 
  535. * Return HTML code that displays a human readable Period representation. 
  536. * 
  537. * @since 1.0.0 
  538. * @param array $period 
  539. * @param string $class 
  540. * @return string 
  541. */ 
  542. public static function period_desc( $period, $class = '' ) { 
  543. $html = sprintf( 
  544. '<span class="ms-period-desc %s"> <span class="ms-period-unit">%s</span> <span class="ms-period-type">%s</span></span>',  
  545. esc_attr( $class ),  
  546. $period['period_unit'],  
  547. $period['period_type'] 
  548. ); 
  549.  
  550. return apply_filters( 'ms_helper_html_period_desc', $html ); 
  551.  
  552. /** 
  553. * Removes lines breaks and tralining/leading whitespace. 
  554. * 
  555. * Use this function: $code = apply_filters( 'ms_compact_code', $code ); 
  556. * 
  557. * Intention of this function is to make HTML code compatible with certain 
  558. * Themes that would add <br> tags at every newline, even when the newline 
  559. * was inside an HTML tag. 
  560. * 
  561. * e.g. <div class="myclass" 
  562. * id="myid"> 
  563. * 
  564. * was replaced by <div class="myclass" <br> 
  565. * id="myid"> 
  566. * 
  567. * @since 1.0.1.0 
  568. * @param string $html HTML code. 
  569. * @return string Compressed HTML code. 
  570. */ 
  571. public static function compact_code( $html ) { 
  572. $html = str_replace( array( "\r\n", "\r" ), "\n", $html ); 
  573. $lines = explode( "\n", $html ); 
  574. $new_lines = array(); 
  575.  
  576. foreach ( $lines as $i => $line ) { 
  577. $line = trim( $line ); 
  578. if ( ! empty( $line ) ) { 
  579. $new_lines[] = $line; 
  580. $html = implode( ' ', $new_lines ); 
  581.  
  582. return $html; 
  583.  
.