Advertisement
nivaldo9

buenasdicas

Feb 26th, 2020
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.27 KB | None | 0 0
  1. <?php
  2. /**
  3. * General Template tags / View Helpers and utility methods.
  4. */
  5. class Bunyad_Theme_Helpers
  6. {
  7. /**
  8. * View Helper: Output mobile logo
  9. */
  10. public function mobile_logo()
  11. {
  12. if (!Bunyad::options()->mobile_logo_2x) {
  13. return;
  14. }
  15.  
  16. // Attachment id is saved in the option
  17. $id = Bunyad::options()->mobile_logo_2x;
  18. $logo = wp_get_attachment_image_src($id, 'full');
  19.  
  20. if (!$logo) {
  21. return;
  22. }
  23.  
  24. // Have the logo attachment - use half sizes for attributes since it's in 2x size
  25. if (is_array($logo)) {
  26. $url = $logo[0];
  27. $width = round($logo[1] / 2);
  28. $height = round($logo[2] / 2);
  29. }
  30.  
  31. ?>
  32.  
  33. <img class="mobile-logo" src="<?php echo esc_url($url); ?>" width="<?php echo esc_attr($width); ?>" height="<?php echo esc_attr($height); ?>"
  34. alt="<?php echo esc_attr(get_bloginfo('name', 'display')); ?>" />
  35.  
  36. <?php
  37. }
  38.  
  39. /**
  40. * Categories for meta
  41. *
  42. * @param boolean|null $all Display primary/one category or all categories.
  43. * @return string Rendered HTML.
  44. */
  45. public function get_meta_cats($all = null, $post_id = false)
  46. {
  47. // Object has category taxonomy? i.e., is it a post or a valid CPT?
  48. if (!is_object_in_taxonomy(get_post_type($post_id), 'category')) {
  49. return;
  50. }
  51.  
  52. $categories = apply_filters('the_category_list', get_the_category($post_id), $post_id);
  53. $output = [];
  54.  
  55. // Not showing all categories.
  56. if (!$all) {
  57. $category = $this->get_primary_cat();
  58.  
  59. $categories = [];
  60. if (is_object($category)) {
  61. $categories[] = $category;
  62. }
  63. }
  64.  
  65. foreach ($categories as $category) {
  66. $output[] = sprintf(
  67. '<a href="%1$s" class="category" rel="category">%2$s</a>',
  68. esc_url(get_category_link($category)),
  69. esc_html($category->name)
  70. );
  71. }
  72.  
  73. return join(' ', $output);
  74. }
  75.  
  76. public function meta_cats($all = null)
  77. {
  78. // Legacy: For sliders etc. that are still using this method directly.
  79. // Auto-decide if only primary should be displayed.
  80. if ($all === null) {
  81. $all = Bunyad::options()->post_meta_all_cats;
  82. }
  83.  
  84. echo $this->get_meta_cats($all); // Escaped output above.
  85. }
  86.  
  87. /**
  88. * Get primary category for a post.
  89. *
  90. * @param int $post_id
  91. * @return object|WP_Error|null
  92. */
  93. public function get_primary_cat($post_id = null)
  94. {
  95. // Primary category defined.
  96. if (($cat_label = Bunyad::posts()->meta('cat_label', $post_id))) {
  97. $category = get_category($cat_label);
  98. }
  99.  
  100. // This test is needed even if a primary cat is defined to test for its
  101. // existence (it might be deleted etc.)
  102. if (empty($category)) {
  103. $category = current(get_the_category($post_id));
  104. }
  105.  
  106. return $category;
  107. }
  108.  
  109. /**
  110. * Get the loop template with handling via a dynamic loop template
  111. * for special cases.
  112. *
  113. * @param string $id
  114. * @param array $data
  115. * @param array $options
  116. * @see Bunyad_Core::partial()
  117. */
  118. public function loop($id = '', $data = array(), $options = array())
  119. {
  120. if (empty($id)) {
  121. $id = 'loop';
  122. }
  123.  
  124. // Dynamic loop templates configuration
  125. $dynamic = array(
  126. 'loop-grid' => array('number' => 0),
  127. 'loop-grid-3' => array('number' => 0, 'grid_cols' => 3),
  128. 'loop-list' => array('number' => 0, 'type' => 'list'),
  129. 'loop-1st-large' => array('number' => 100),
  130. 'loop-1st-large-list' => array('type' => 'list', 'number' => 100),
  131. 'loop-1st-overlay' => array('large' => 'overlay', 'number' => 100),
  132. 'loop-1st-overlay-list' => array('large' => 'overlay', 'number' => 100, 'type' => 'list'),
  133. 'loop-1-2' => array(),
  134. 'loop-1-2-list' => array('type' => 'list'),
  135. 'loop-1-2-overlay' => array('large' => 'overlay'),
  136. 'loop-1-2-overlay-list' => array('large' => 'overlay', 'type' => 'list')
  137. );
  138.  
  139. // Is a dynamic template?
  140. if (array_key_exists($id, $dynamic)) {
  141.  
  142. if (!empty($options)) {
  143. $dynamic[$id] = array_merge($dynamic[$id], $options);
  144. }
  145.  
  146. // Loaded through load more? Ignore mixed/first large
  147. if (!empty($_GET['first_normal'])) {
  148. $dynamic[$id]['number'] = 0;
  149. }
  150.  
  151. // Render our dynamic loop
  152. return Bunyad::core()->partial(
  153. 'loop-dynamic',
  154. array_merge($dynamic[$id], $data, array('loop' => $id))
  155. );
  156. }
  157. else {
  158. $id = 'loop';
  159. }
  160.  
  161. Bunyad::core()->partial($id, $data);
  162. }
  163.  
  164. /**
  165. * Render and output breadcrumb trail with the markup.
  166. *
  167. * @param array $options
  168. * @return void
  169. */
  170. public function breadcrumbs($options = [])
  171. {
  172. // Check if Yoast SEO's Breadcrumbs are enabled.
  173. $is_yoast = false;
  174. if (class_exists('WPSEO_Options') && function_exists('yoast_breadcrumb')) {
  175. if (is_callable(['WPSEO_Options', 'get']) && WPSEO_Options::get('breadcrumbs-enable', false)) {
  176. $is_yoast = true;
  177. }
  178. }
  179.  
  180. // Neither theme nor Yoast's Breadcrumbs enabled.
  181. if (!$is_yoast && !Bunyad::options()->breadcrumbs_enable) {
  182. return;
  183. }
  184.  
  185. $options = array_replace([
  186. 'classes' => [],
  187. ], $options);
  188.  
  189. $wrap_classes = array_merge(
  190. ['breadcrumbs', 'ts-contain'],
  191. (array) $options['classes']
  192. );
  193.  
  194. $before = sprintf(
  195. '<nav class="%1$s" id="breadcrumb"><div class="inner wrap"%s>',
  196. join(' ', $wrap_classes),
  197. '%1$s' // To be replaced by render method.
  198. );
  199.  
  200. $after = '</div></nav>';
  201.  
  202. // Output Yoast Breadcrumbs.
  203. if ($is_yoast) {
  204. return yoast_breadcrumb($before, $after);
  205. }
  206.  
  207. // Find disabled locations from theme settings.
  208. // Note: Homepage is disabled by default by the Sphere breadcrumbs.
  209. $location_keys = [
  210. 'single', 'page', 'search', 'archive'
  211. ];
  212.  
  213. $disable_at = [];
  214. foreach ($location_keys as $key) {
  215. if (!Bunyad::options()->get('breadcrumbs_' . $key)) {
  216. $disable_at[] = $key;
  217. }
  218. }
  219.  
  220. /** @var \Sphere\Core\Breadcrumbs\Module $breadcrumbs */
  221. $breadcrumbs = \Sphere\Core\Plugin::get('breadcrumbs');
  222. if (!$breadcrumbs) {
  223. return;
  224. }
  225.  
  226. $breadcrumbs->render([
  227. 'primary_cat_callback' => [$this, 'get_primary_cat'],
  228.  
  229. // Spaces added left and right to be same as Yoast.
  230. 'delimiter' => ' <span class="delim"><i class="tsi tsi-angle-right"></i></span> ',
  231.  
  232. 'before' => $before,
  233. 'after' => $after,
  234. 'disable_at' => $disable_at,
  235. 'labels' => [
  236. 'home' => esc_html_x('Home', 'breadcrumbs', 'cheerup'),
  237. 'category' => esc_html_x('Category: "%s"', 'breadcrumbs','cheerup'),
  238. 'tax' => esc_html_x('Archive for "%s"', 'breadcrumbs','cheerup'),
  239. 'search' => esc_html_x('Search Results for "%s"', 'breadcrumbs','cheerup'),
  240. 'tag' => esc_html_x('Posts Tagged "%s"', 'breadcrumbs','cheerup'),
  241. '404' => esc_html_x('Error 404', 'breadcrumbs','cheerup'),
  242. 'author' => esc_html_x('Author: %s', 'breadcrumbs','cheerup'),
  243. 'paged' => esc_html_x(' (Page %d)', 'breadcrumbs','cheerup')
  244. ]
  245. ]);
  246. }
  247.  
  248. /**
  249. * Output meta partial based on theme settings
  250. *
  251. * @param string|null $type Meta type to use, mainly used as a setting prefix like 'grid'.
  252. * @param array $args Options to set/overwrite, see $options in method.
  253. * @return void
  254. */
  255. public function post_meta($type, $args = [])
  256. {
  257. $prefixes = [
  258. 'grid' => 'post_meta_grid',
  259. 'list' => 'post_meta_list',
  260. 'list-b' => 'post_meta_list',
  261. 'single' => 'post_meta_single',
  262. ];
  263.  
  264. // Default args/options - will be merged into $args later below.
  265. $options = [
  266. 'items_above' => Bunyad::options()->post_meta_above,
  267. 'items_below' => Bunyad::options()->post_meta_below,
  268. 'style' => Bunyad::options()->post_meta_style,
  269. 'align' => Bunyad::options()->post_meta_align,
  270. 'text_labels' => (array) Bunyad::options()->post_meta_labels,
  271. 'all_cats' => Bunyad::options()->post_meta_all_cats,
  272. 'modified_date' => Bunyad::options()->post_meta_modified_date,
  273.  
  274. // Whether to show overlay cat labels as inline - useful when can't overlay.
  275. 'cat_labels_inline' => false,
  276.  
  277. // Category labels remain legacy.
  278. 'cat_labels_overlay' => Bunyad::options()->meta_cat_labels,
  279. ];
  280.  
  281. /**
  282. * Remove default and null values from array.
  283. */
  284. $filter_defaults = function($options) {
  285. // Remove default/null values.
  286. foreach ($options as $key => $opt) {
  287. if ($opt === null || $opt === 'default') {
  288. unset($options[$key]);
  289. }
  290. }
  291.  
  292. return $options;
  293. };
  294.  
  295. // A known type and isn't set to use global options.
  296. if (isset($prefixes[$type]) && !Bunyad::options()->get($prefixes[$type] . '_global')) {
  297.  
  298. $key = $prefixes[$type];
  299.  
  300. $local_opts = [
  301. 'items_above' => Bunyad::options()->get($key . '_above'),
  302. 'items_below' => Bunyad::options()->get($key . '_below'),
  303. 'style' => Bunyad::options()->get($key . '_style')
  304. ];
  305.  
  306. $options = array_replace($options, $filter_defaults($local_opts));
  307. }
  308.  
  309. // Style overrides for selected style, such as a.
  310. if (isset($options['style'])) {
  311. $style_opts = [
  312. 'align' => Bunyad::options()->get('post_meta_' . $options['style'] . '_align'),
  313. 'divider' => Bunyad::options()->get('post_meta_' . $options['style'] . '_divider'),
  314. ];
  315.  
  316. $options = array_replace($options, $filter_defaults($style_opts));
  317. }
  318.  
  319. $args = array_replace($options, $args);
  320.  
  321. // If inline cat labels are forced and there are no items above.
  322. // This stays consistent with the legacy post-meta-c behavior.
  323. if ($args['cat_labels_inline'] && $args['cat_labels_overlay'] && empty($args['items_above'])) {
  324. $args['items_above'] = ['cat'];
  325. $args['cat_style'] = 'labels';
  326. }
  327.  
  328. // Single has separate setting for all categories.
  329. if (!empty($args['is_single'])) {
  330. $args['all_cats'] = Bunyad::options()->single_all_cats;
  331. }
  332.  
  333. // Divider are only supported on a few types even on post-meta-a.
  334. $support_divider = [
  335. 'grid',
  336. 'grid-b',
  337. 'large',
  338. 'large-c',
  339. 'large-b',
  340. 'list',
  341. 'list-b',
  342. 'single'
  343. ];
  344.  
  345. if (!in_array($type, $support_divider)) {
  346. $args['divider'] = false;
  347. }
  348.  
  349. // Remove forcefully disabled items.
  350. if (Bunyad::options()->post_meta_disabled) {
  351. $args['items_above'] = array_diff($args['items_above'], (array) Bunyad::options()->post_meta_disabled);
  352. $args['items_below'] = array_diff($args['items_below'], (array) Bunyad::options()->post_meta_disabled);
  353. }
  354.  
  355. echo $this->render_post_meta(
  356. apply_filters('bunyad_post_meta_args', $args, $type)
  357. );
  358. }
  359.  
  360. /**
  361. * Render the post meta.
  362. *
  363. * @param array $args
  364. * @return string
  365. */
  366. public function render_post_meta($args)
  367. {
  368. $args = array_replace([
  369. 'items_above' => [], //['cat', 'date'],
  370. 'items_below' => ['author', 'date', 'comments'],
  371.  
  372. 'show_title' => true,
  373. 'title_class' => 'post-title-alt',
  374. 'title_tag' => 'h2',
  375. 'is_single' => false,
  376.  
  377. // Show text labels like "In", "By"
  378. 'text_labels' => [],
  379. 'cat_style' => '',
  380. 'all_cats' => false,
  381. 'style' => 'b',
  382.  
  383. // Alignment defaults to inherit from parents.
  384. 'align' => '',
  385. 'add_class' => '',
  386. 'cat_labels' => false,
  387.  
  388. 'modified_date' => false,
  389. 'wrapper' => null,
  390. // 'divider' => false
  391. ], $args);
  392.  
  393. // Enable divider on style a by default, unless specified.
  394. if (!isset($args['divider'])) {
  395. $args['divider'] = $args['style'] == 'a' ? true : false;
  396. }
  397.  
  398. $style = str_replace('style-', '', $args['style']);
  399. $class = array_merge(
  400. [
  401. 'post-meta',
  402. 'post-meta-' . $style,
  403. ($args['align'] ? 'post-meta-' . $args['align'] : null),
  404. ($args['divider'] ? 'post-meta-divider' : null)
  405. ],
  406. (array) $args['add_class']
  407. );
  408.  
  409. /**
  410. * Start preparing the output.
  411. */
  412. $output = '';
  413.  
  414. // Meta items above title.
  415. $output .= $this->render_post_meta_items(
  416. $args['items_above'], ['meta-above'], $args
  417. );
  418.  
  419. // Post title and tag.
  420. if ($args['show_title']) {
  421.  
  422. $tag = $args['title_tag'];
  423.  
  424. if ($args['is_single']) {
  425. $tag = 'h1';
  426. $title = get_the_title();
  427. }
  428. else {
  429. $title = sprintf(
  430. '<a href="%1$s">%2$s</a>',
  431. esc_url(get_the_permalink()),
  432. get_the_title()
  433. );
  434. }
  435.  
  436. $output .= sprintf(
  437. '<%1$s class="is-title %2$s">%3$s</%1$s>',
  438. esc_attr($tag),
  439. esc_attr($args['title_class']),
  440. $title // Safe above.
  441. );
  442. }
  443.  
  444. // Meta items below title.
  445. $items_below = $this->render_post_meta_items(
  446. $args['items_below'], ['below meta-below'], $args
  447. );
  448.  
  449. $output .= $items_below;
  450.  
  451. // Add a class to denote items below exist.
  452. if ($items_below) {
  453. $class[] = 'has-below';
  454. }
  455.  
  456. // Default wrapper.
  457. if ($args['wrapper'] === null) {
  458. $args['wrapper'] = '<div %1$s>%2$s</div>';
  459. }
  460.  
  461. $output = sprintf(
  462. $args['wrapper'],
  463. Bunyad::markup()->attribs(
  464. 'post-meta-wrap',
  465. ['class' => $class],
  466. ['echo' => false]
  467. ),
  468. $output
  469. );
  470.  
  471. return $output;
  472. }
  473.  
  474. /**
  475. * Render post meta items.
  476. *
  477. * @param array $items An array of meta item name/ids.
  478. * @param array|string $classes A list of classes to add to wrapper.
  479. * @param array $args Extra options consumed by get_meta_items()
  480. * @return string
  481. */
  482. public function render_post_meta_items(array $items, $classes, $args = [])
  483. {
  484. $args = array_replace([
  485. 'cat_style' => '',
  486. 'all_cats' => false,
  487. 'text_labels' => [],
  488. 'modified_date' => false
  489. ], $args);
  490.  
  491. // It doesn't make sense to have two of same items in same line.
  492. $items = array_unique($items);
  493.  
  494. $rendered = [];
  495. foreach ($items as $item) {
  496. $rendered[] = $this->get_meta_item($item, $args);
  497. }
  498.  
  499. if (!$rendered) {
  500. return '';
  501. }
  502.  
  503. $the_items = join(
  504. // Spaces for backward compatibility.
  505. ' <span class="meta-sep"></span> ',
  506. $rendered
  507. );
  508.  
  509. $classes = join(' ', (array) $classes);
  510.  
  511. return sprintf(
  512. '<div class="%1$s">%2$s</div>',
  513. esc_attr($classes),
  514. $the_items
  515. );
  516. }
  517.  
  518. /**
  519. * Get a post a meta item's HTML.
  520. *
  521. * @param string $item
  522. * @param array $args
  523. *
  524. * @return string Rendered HTML.
  525. */
  526. public function get_meta_item($item, $args = [])
  527. {
  528. $args = array_replace([
  529. 'cat_style' => '',
  530. 'all_cats' => false,
  531. 'text_labels' => [],
  532. 'modified_date' => false
  533. ], $args);
  534.  
  535. $output = '';
  536.  
  537. /**
  538. * Determine the item to render and generate output.
  539. */
  540. switch ($item) {
  541.  
  542. // Meta item: Category/s
  543. case 'cat':
  544.  
  545. $cat_class = 'post-cat';
  546.  
  547. if (!empty($args['cat_style'])) {
  548.  
  549. // Map of cat styles and the relevant classes.
  550. $cat_styles = [
  551. 'text' => 'post-cat',
  552. 'labels' => 'cat-labels',
  553. ];
  554.  
  555. $cat_class = $cat_styles[ $args['cat_style'] ];
  556. }
  557.  
  558. // Add "In" if text labels enabled.
  559. $text = '';
  560. if (in_array('in', $args['text_labels'])) {
  561. $text = sprintf(
  562. '<span class="text-in">%s</span>',
  563. esc_html__('In', 'cheerup')
  564. );
  565. }
  566.  
  567. $output = sprintf(
  568. '<span class="%1$s">
  569. %2$s
  570. %3$s
  571. </span>
  572. ',
  573. esc_attr($cat_class),
  574. $text,
  575. $this->get_meta_cats($args['all_cats'])
  576. );
  577.  
  578. break;
  579.  
  580. // Meta item: Comments Count & Link
  581. case 'comments':
  582. $output = sprintf(
  583. '<span class="meta-item comments"><a href="%1$s">%2$s</a></span>',
  584. esc_url(get_comments_link()),
  585. esc_html(get_comments_number_text())
  586. );
  587.  
  588. break;
  589.  
  590. // Meta item: Date
  591. case 'date':
  592.  
  593. $date_w3c = $args['modified_date'] ? get_the_modified_date(DATE_W3C) : get_the_date(DATE_W3C);
  594. $date = $args['modified_date'] ? get_the_modified_date() : get_the_date();
  595.  
  596. $output = sprintf(
  597. '<a href="%1$s" class="meta-item date-link">
  598. <time class="post-date" datetime="%2$s">Published on %3$s | updated %4$s</time>
  599. </a>',
  600. esc_url(get_the_permalink()),
  601. esc_attr($date_w3c),
  602. esc_html($date),
  603. esch_html(get_the_modified_date())
  604. );
  605.  
  606. break;
  607.  
  608. // Meta item: Author
  609. case 'author':
  610.  
  611. // Add "By" if labels enabled.
  612. $label = '';
  613. if (in_array('by', $args['text_labels'])) {
  614. $label = sprintf(
  615. esc_html_x('%sBy%s', 'Post Meta', 'cheerup'),
  616. '<span class="by">',
  617. '</span> '
  618. );
  619. }
  620.  
  621. $author_link = $label . get_the_author_posts_link();
  622.  
  623. $output = sprintf(
  624. '<span class="meta-item post-author">%1$s</span>',
  625. $author_link
  626. );
  627.  
  628. break;
  629.  
  630. // Meta Item: Estimated Read Time
  631. case 'read_time':
  632.  
  633. $minutes = $this->get_read_time();
  634. $text = sprintf(
  635. _n('%d Min Read', '%d Mins Read', $minutes, 'cheerup'),
  636. $minutes
  637. );
  638.  
  639. $output = sprintf(
  640. '<span class="meta-item read-time">%1$s</span>',
  641. $text
  642. );
  643.  
  644. break;
  645. }
  646.  
  647. return $output;
  648. }
  649.  
  650. /**
  651. * Display category label overlay when conditions meet
  652. */
  653. public function meta_cat_label($options = array())
  654. {
  655. if (!Bunyad::options()->meta_cat_labels && empty($options['force'])) {
  656. return;
  657. }
  658.  
  659. $class = 'cat-label cf';
  660.  
  661. if (!empty($options['class'])) {
  662. $class .= ' ' . $options['class'];
  663. }
  664.  
  665. ?>
  666.  
  667. <span class="<?php echo esc_attr($class); ?>"><?php echo $this->meta_cats(); ?></span>
  668.  
  669. <?php
  670. }
  671.  
  672. /**
  673. * Reading time calculator for a post content.
  674. *
  675. * @param string $content Post Content
  676. * @return integer
  677. */
  678. public function get_read_time($content = '')
  679. {
  680. if (!$content) {
  681. $content = get_post_field('post_content');
  682. }
  683.  
  684. $wpm = apply_filters('bunyad_reading_time_wpm', 200);
  685.  
  686. // Strip HTML and count words for reading time. Built-in function not safe when
  687. // incorrect locale: str_word_count(wp_strip_all_tags($content))
  688. // Therefore, using a regex instead to split.
  689. $content = wp_strip_all_tags($content);
  690. $word_count = count(preg_split('/&nbsp;+|\s+/', $content));
  691. $minutes = ceil($word_count / $wpm);
  692.  
  693. return $minutes;
  694. }
  695.  
  696. /**
  697. * A wrapper for get_search_form to allow multiple styles
  698. *
  699. * @see get_search_form()
  700. *
  701. * @param string $style Type of search form
  702. * @param array $data Extra data to pass
  703. * @return string|void
  704. */
  705. public function search_form($style, $data = array(), $echo = true)
  706. {
  707. $previous = Bunyad::registry()->search_form_data;
  708.  
  709. // Extend data
  710. $data = array_merge(array(
  711. 'style' => $style,
  712. ), $data);
  713.  
  714. // Placeholder text decision
  715. if (!isset($data['text']) && $style == 'alt') {
  716. $data['text'] = esc_html_x('Search', 'search', 'cheerup');
  717. }
  718.  
  719. // Set the data and get the form
  720. Bunyad::registry()->search_form_data = $data;
  721. $form = get_search_form($echo);
  722.  
  723. // Restore to a global / previous style if any
  724. Bunyad::registry()->search_form_data = $previous ? $previous : '';
  725.  
  726. if (!$echo) {
  727. return $form;
  728. }
  729. }
  730.  
  731. /**
  732. * Get relative width for current block, based on parent column width in
  733. * relation to the whole container.
  734. *
  735. * @return float Column width in percent number, example 66
  736. */
  737. public function relative_width()
  738. {
  739. // Set current column width weight (width/100) - used to determine image sizing
  740. $col_relative_width = 1;
  741. if (isset(Bunyad::registry()->layout['col_relative_width'])) {
  742. $col_relative_width = Bunyad::registry()->layout['col_relative_width'];
  743. }
  744.  
  745. // Adjust relative width if there's a sidebar
  746. if (Bunyad::core()->get_sidebar() != 'none') {
  747. $col_relative_width = ($col_relative_width * (8/12));
  748. }
  749.  
  750. return $col_relative_width * 100;
  751. }
  752.  
  753. /**
  754. * Create multiple options based on provided replacements and a template array.
  755. *
  756. * @param array $templates
  757. * @param array $field_types
  758. * @param array $options
  759. * @param array $config
  760. * @return void
  761. */
  762. public function repeat_options($templates, $field_types, &$options, $config = [])
  763. {
  764. $config = array_replace([
  765. 'replace_in' => ['css']
  766. ], $config);
  767.  
  768. foreach ($field_types as $key => $type) {
  769. foreach ($templates as $id => $template) {
  770.  
  771. // Skip this specific field.
  772. if (isset($type['skip']) && in_array($template['name'], $type['skip'])) {
  773. continue;
  774. }
  775.  
  776. $to_add = array_replace_recursive($template, $type);
  777. $to_add['name'] = str_replace('{key}', $key, $to_add['name']);
  778.  
  779. // Overrides for specific keys.
  780. if (!empty($type['overrides']) && isset($type['overrides'][ $template['name'] ])) {
  781. $to_add = array_replace(
  782. $to_add,
  783. (array) $type['overrides'][ $template['name'] ]
  784. );
  785. }
  786.  
  787. // Override 'css' with data from 'fields_css'.
  788. if (!empty($type['fields_css'][$id])) {
  789. $to_add['css'] = $type['fields_css'][$id];
  790. }
  791.  
  792. foreach ($config['replace_in'] as $replace) {
  793. if (empty($to_add[ $replace ])) {
  794. continue;
  795. }
  796.  
  797. if (is_array($to_add[ $replace ])) {
  798.  
  799. /**
  800. * Recursively replace {key} in both keys and values.
  801. */
  802. $to_add[ $replace ] = $this->array_modify_recursive($to_add[ $replace ], function($new_key, $new_val) use($key) {
  803. $new_key = str_replace('{key}', $key, $new_key);
  804.  
  805. if (is_string($new_val)) {
  806. $new_val = str_replace('{key}', $key, $new_val);
  807. }
  808.  
  809. return [$new_key, $new_val];
  810. });
  811. }
  812. else {
  813. $to_add[ $replace ] = str_replace('{key}', $key, $to_add[ $replace ]);
  814. }
  815. }
  816.  
  817. unset(
  818. $to_add['fields_css'],
  819. $to_add['skip']
  820. );
  821.  
  822. $options[] = $to_add;
  823. }
  824. }
  825. }
  826.  
  827. /**
  828. * Get custom ratio if available for an option.
  829. *
  830. * @param string $key
  831. * @return null|string
  832. */
  833. public function get_ratio($key, $fallback = null)
  834. {
  835. $ratio = Bunyad::options()->get($key . '_custom', $key);
  836.  
  837. if (!$ratio && $fallback) {
  838. return $this->get_ratio($fallback);
  839. }
  840.  
  841. // This would happen if option is set to custom but no custom value
  842. // in custom ratio field.
  843. if ($ratio == 'custom') {
  844. return null;
  845. }
  846.  
  847. return $ratio;
  848. }
  849.  
  850.  
  851. /**
  852. * Remove prefix/suffix from set of keys, recursively.
  853. *
  854. * @param array $array
  855. * @param string $affix
  856. * @param boolean $is_prefix
  857. * @return array
  858. */
  859. public function deaffix_keys(array $array, $affix, $is_prefix = true, $args = [])
  860. {
  861. $args = array_replace([
  862. 'require_affix' => false
  863. ], $args);
  864.  
  865. $new_array = [];
  866.  
  867. foreach ($array as $key => $val) {
  868. if (is_array($val)) {
  869. $val = $this->deaffix_keys($val, $affix, $is_prefix);
  870. }
  871.  
  872. // Flag to denote if an affix was found and changes made.
  873. $affixed = false;
  874.  
  875. // Prefix
  876. if ($is_prefix && strpos($key, $affix) === 0) {
  877. $affixed = true;
  878. $key = substr($key, strlen($affix));
  879. }
  880. elseif (!$is_prefix) {
  881.  
  882. // Finding and removing a suffix.
  883. $offset = strlen($key) - strlen($affix);
  884. if (strpos($key, $affix, $offset) !== false) {
  885. $affixed = true;
  886. $key = substr($key, 0, -strlen($affix));
  887. }
  888. }
  889.  
  890. // Discard if affix is required.
  891. if ($args['require_affix'] && !$affixed) {
  892. continue;
  893. }
  894.  
  895. $new_array[$key] = $val;
  896. }
  897.  
  898. return $new_array;
  899. }
  900.  
  901. /**
  902. * Remove affix in keys of array and pick only the affixed keys.
  903. *
  904. * @see self::defaffix_keys
  905. * @return array
  906. */
  907. public function pick_deaffixed(array $array, $affix, $is_prefix = true)
  908. {
  909. return $this->deaffix_keys($array, $affix, $is_prefix, ['require_affix' => true]);
  910. }
  911.  
  912. /**
  913. * Modify both keys and values in a an array recursively, while preserving sort.
  914. *
  915. * @param array $array Original array.
  916. * @param callable $callback Callback function takes two params (key, value) and
  917. * returns the new [key, value] to as an array.
  918. *
  919. * @return array
  920. */
  921. public function array_modify_recursive(array $array, callable $callback)
  922. {
  923. $output = [];
  924.  
  925. foreach ($array as $key => $value) {
  926.  
  927. if (is_array($value)) {
  928. $value = $this->array_modify_recursive($value, $callback);
  929. }
  930.  
  931. $new_key = $key;
  932. $new_value = $value;
  933.  
  934. // Get output from callback and use as key/value.
  935. $replace = $callback($key, $value);
  936. if (is_array($replace)) {
  937. list($new_key, $new_value) = $replace;
  938. }
  939.  
  940. // If callback returns false, skip.
  941. if ($replace !== false) {
  942. $output[$new_key] = $new_value;
  943. }
  944. }
  945.  
  946. return $output;
  947. }
  948. }
  949.  
  950.  
  951. // init and make available in Bunyad::get('helpers')
  952. Bunyad::register('helpers', array(
  953. 'class' => 'Bunyad_Theme_Helpers',
  954. 'init' => true
  955. ));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement