Version Description
Changes for Theme Developers
- You can now change the query parameters that are used when getting a posts terms through $post->terms()
. #1802
- New attributes for responsive images post.thumbnail.srcset
and post.thumbnail.sizes
#1819 (thanks @maxxwv)
Fixes and improvements
- Using WordPress's wp_check_filetype_and_ext
for the mime_type mess #1843 (thanks @gchtr)
- Fixed how some previewed data (when looking at an unsaved post from the admin) is handled so that parenting relationships match what happens when published #1752
- Timber\Menu now respects modifications sent through WP's wp_nav_menu_objects
filter #1814 (thanks @pascalknecht)
Download this release
Release Info
Developer | jarednova |
Plugin | Timber |
Version | 1.8.2 |
Comparing to | |
See all releases |
Code changes from version 1.8.1 to 1.8.2
- lib/Image.php +41 -0
- lib/ImageHelper.php +24 -31
- lib/Loader.php +1 -1
- lib/Menu.php +32 -0
- lib/Post.php +164 -66
- lib/Timber.php +1 -1
- readme.txt +14 -2
- timber-starter-theme/index.php +1 -1
- timber.php +1 -1
- vendor/autoload.php +1 -1
- vendor/composer/autoload_real.php +3 -3
lib/Image.php
CHANGED
@@ -452,6 +452,44 @@ class Image extends Post implements CoreInterface {
|
|
452 |
return $src;
|
453 |
}
|
454 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
455 |
/**
|
456 |
* @internal
|
457 |
* @return bool true if media is an image
|
@@ -480,6 +518,7 @@ class Image extends Post implements CoreInterface {
|
|
480 |
|
481 |
/**
|
482 |
* @deprecated 0.21.9 use TimberImage::src
|
|
|
483 |
* @internal
|
484 |
* @param string $size
|
485 |
* @return bool|string
|
@@ -492,6 +531,7 @@ class Image extends Post implements CoreInterface {
|
|
492 |
|
493 |
/**
|
494 |
* @deprecated since 0.21.9 use src() instead
|
|
|
495 |
* @return string
|
496 |
*/
|
497 |
public function url( $size = '' ) {
|
@@ -502,6 +542,7 @@ class Image extends Post implements CoreInterface {
|
|
502 |
|
503 |
/**
|
504 |
* @deprecated since 0.21.9 use src() instead
|
|
|
505 |
* @return string
|
506 |
*/
|
507 |
public function get_url( $size = '' ) {
|
452 |
return $src;
|
453 |
}
|
454 |
|
455 |
+
/**
|
456 |
+
* @param string $size a size known to WordPress (like "medium")
|
457 |
+
* @api
|
458 |
+
* @example
|
459 |
+
* ```twig
|
460 |
+
* <h1>{{ post.title }}</h1>
|
461 |
+
* <img src="{{ post.thumbnail.src }}" srcset="{{ post.thumnbail.srcset }}" />
|
462 |
+
* ```
|
463 |
+
* ```html
|
464 |
+
* <img src="http://example.org/wp-content/uploads/2018/10/pic.jpg" srcset="http://example.org/wp-content/uploads/2018/10/pic.jpg 1024w, http://example.org/wp-content/uploads/2018/10/pic-600x338.jpg 600w, http://example.org/wp-content/uploads/2018/10/pic-300x169.jpg 300w" />
|
465 |
+
* ```
|
466 |
+
* @return bool|string
|
467 |
+
*/
|
468 |
+
public function srcset( $size = "full" ) {
|
469 |
+
if( $this->is_image() ){
|
470 |
+
return wp_get_attachment_image_srcset($this->ID, $size);
|
471 |
+
}
|
472 |
+
}
|
473 |
+
|
474 |
+
/**
|
475 |
+
* @param string $size a size known to WordPress (like "medium")
|
476 |
+
* @api
|
477 |
+
* @example
|
478 |
+
* ```twig
|
479 |
+
* <h1>{{ post.title }}</h1>
|
480 |
+
* <img src="{{ post.thumbnail.src }}" srcset="{{ post.thumnbail.srcset }}" sizes="{{ post.thumbnail.sizes }}" />
|
481 |
+
* ```
|
482 |
+
* ```html
|
483 |
+
* <img src="http://example.org/wp-content/uploads/2018/10/pic.jpg" srcset="http://example.org/wp-content/uploads/2018/10/pic.jpg 1024w, http://example.org/wp-content/uploads/2018/10/pic-600x338.jpg 600w, http://example.org/wp-content/uploads/2018/10/pic-300x169.jpg 300w sizes="(max-width: 1024px) 100vw, 102" />
|
484 |
+
* ```
|
485 |
+
* @return bool|string
|
486 |
+
*/
|
487 |
+
public function img_sizes( $size = "full" ) {
|
488 |
+
if( $this->is_image() ){
|
489 |
+
return wp_get_attachment_image_sizes($this->ID, $size);
|
490 |
+
}
|
491 |
+
}
|
492 |
+
|
493 |
/**
|
494 |
* @internal
|
495 |
* @return bool true if media is an image
|
518 |
|
519 |
/**
|
520 |
* @deprecated 0.21.9 use TimberImage::src
|
521 |
+
* @codeCoverageIgnore
|
522 |
* @internal
|
523 |
* @param string $size
|
524 |
* @return bool|string
|
531 |
|
532 |
/**
|
533 |
* @deprecated since 0.21.9 use src() instead
|
534 |
+
* @codeCoverageIgnore
|
535 |
* @return string
|
536 |
*/
|
537 |
public function url( $size = '' ) {
|
542 |
|
543 |
/**
|
544 |
* @deprecated since 0.21.9 use src() instead
|
545 |
+
* @codeCoverageIgnore
|
546 |
* @return string
|
547 |
*/
|
548 |
public function get_url( $size = '' ) {
|
lib/ImageHelper.php
CHANGED
@@ -141,41 +141,34 @@ class ImageHelper {
|
|
141 |
fclose($fh);
|
142 |
return $count > 1;
|
143 |
}
|
144 |
-
|
145 |
-
/**
|
146 |
-
*
|
147 |
-
* Checks if file is an SVG
|
148 |
-
* @param string $file_path file path.
|
149 |
-
* @return boolean true if svg, false if not svg or file doesn't exist.
|
150 |
-
*/
|
151 |
-
public static function is_svg( $file_path ) {
|
152 |
-
$ret = false;
|
153 |
-
if ( isset($file_path) && '' !== $file_path && file_exists($file_path) ) {
|
154 |
-
$mime = self::_mime_content_type($file_path);
|
155 |
-
$ret = in_array($mime, ['image/svg+xml', 'text/html', 'text/plain', 'image/svg']);
|
156 |
-
}
|
157 |
-
return $ret;
|
158 |
-
}
|
159 |
|
160 |
/**
|
161 |
-
*
|
162 |
-
*
|
163 |
-
*
|
164 |
-
* @
|
165 |
-
* @param string $filename to test.
|
166 |
-
* @return string|boolean mime type if found (eg. `image/svg` or `text/plain`) false if not
|
167 |
*/
|
168 |
-
static function
|
169 |
-
if (
|
170 |
-
return
|
171 |
}
|
172 |
-
$result = new \finfo();
|
173 |
-
|
174 |
-
if ( file_exists( $filename ) === true ) {
|
175 |
-
return $result->file( $filename, FILEINFO_MIME_TYPE );
|
176 |
-
}
|
177 |
|
178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
}
|
180 |
|
181 |
/**
|
@@ -209,7 +202,7 @@ class ImageHelper {
|
|
209 |
/**
|
210 |
* Generates a new image by converting the source into WEBP
|
211 |
*
|
212 |
-
* @param string $src a url or path to the image (http://example.org/wp-content/uploads/2014/image.jpg)
|
213 |
* or (/wp-content/uploads/2014/image.jpg)
|
214 |
* @param int $quality ranges from 0 (worst quality, smaller file) to 100 (best quality, biggest file)
|
215 |
* @param bool $force
|
141 |
fclose($fh);
|
142 |
return $count > 1;
|
143 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
144 |
|
145 |
/**
|
146 |
+
* Checks if file is an SVG.
|
147 |
+
*
|
148 |
+
* @param string $file_path File path to check.
|
149 |
+
* @return bool True if SVG, false if not SVG or file doesn't exist.
|
|
|
|
|
150 |
*/
|
151 |
+
public static function is_svg( $file_path ) {
|
152 |
+
if ( ! isset( $file_path ) || '' === $file_path || ! file_exists( $file_path ) ) {
|
153 |
+
return false;
|
154 |
}
|
|
|
|
|
|
|
|
|
|
|
155 |
|
156 |
+
/**
|
157 |
+
* Try reading mime type.
|
158 |
+
*
|
159 |
+
* SVG images are not allowed by default in WordPress, so we have to pass a default mime
|
160 |
+
* type for SVG images.
|
161 |
+
*/
|
162 |
+
$mime = wp_check_filetype_and_ext( $file_path, basename( $file_path ), array(
|
163 |
+
'svg' => 'image/svg+xml',
|
164 |
+
) );
|
165 |
+
|
166 |
+
return in_array( $mime['type'], array(
|
167 |
+
'image/svg+xml',
|
168 |
+
'text/html',
|
169 |
+
'text/plain',
|
170 |
+
'image/svg',
|
171 |
+
) );
|
172 |
}
|
173 |
|
174 |
/**
|
202 |
/**
|
203 |
* Generates a new image by converting the source into WEBP
|
204 |
*
|
205 |
+
* @param string $src a url or path to the image (http://example.org/wp-content/uploads/2014/image.jpg)
|
206 |
* or (/wp-content/uploads/2014/image.jpg)
|
207 |
* @param int $quality ranges from 0 (worst quality, smaller file) to 100 (best quality, biggest file)
|
208 |
* @param bool $force
|
lib/Loader.php
CHANGED
@@ -151,7 +151,7 @@ class Loader {
|
|
151 |
$loader = $this->get_loader();
|
152 |
$params = array('debug' => WP_DEBUG, 'autoescape' => false);
|
153 |
if ( isset(Timber::$autoescape) ) {
|
154 |
-
$params['autoescape'] = Timber::$autoescape;
|
155 |
}
|
156 |
if ( Timber::$cache === true ) {
|
157 |
Timber::$twig_cache = true;
|
151 |
$loader = $this->get_loader();
|
152 |
$params = array('debug' => WP_DEBUG, 'autoescape' => false);
|
153 |
if ( isset(Timber::$autoescape) ) {
|
154 |
+
$params['autoescape'] = Timber::$autoescape === true ? 'html' : Timber::$autoescape;
|
155 |
}
|
156 |
if ( Timber::$cache === true ) {
|
157 |
Timber::$twig_cache = true;
|
lib/Menu.php
CHANGED
@@ -100,6 +100,38 @@ class Menu extends Core {
|
|
100 |
if ( $menu ) {
|
101 |
_wp_menu_item_classes_by_context($menu);
|
102 |
if ( is_array($menu) ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
$menu = self::order_children($menu);
|
104 |
$menu = self::strip_to_depth_limit($menu);
|
105 |
}
|
100 |
if ( $menu ) {
|
101 |
_wp_menu_item_classes_by_context($menu);
|
102 |
if ( is_array($menu) ) {
|
103 |
+
/**
|
104 |
+
* Default arguments from wp_nav_menu() function.
|
105 |
+
*
|
106 |
+
* @see wp_nav_menu()
|
107 |
+
*/
|
108 |
+
$default_args = array(
|
109 |
+
'menu' => '',
|
110 |
+
'container' => 'div',
|
111 |
+
'container_class' => '',
|
112 |
+
'container_id' => '',
|
113 |
+
'menu_class' => 'menu',
|
114 |
+
'menu_id' => '',
|
115 |
+
'echo' => true,
|
116 |
+
'fallback_cb' => 'wp_page_menu',
|
117 |
+
'before' => '',
|
118 |
+
'after' => '',
|
119 |
+
'link_before' => '',
|
120 |
+
'link_after' => '',
|
121 |
+
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
|
122 |
+
'item_spacing' => 'preserve',
|
123 |
+
'depth' => $this->depth,
|
124 |
+
'walker' => '',
|
125 |
+
'theme_location' => '',
|
126 |
+
);
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Improve compatibitility with third-party plugins.
|
130 |
+
*
|
131 |
+
* @see wp_nav_menu()
|
132 |
+
*/
|
133 |
+
$menu = apply_filters( 'wp_nav_menu_objects', $menu, $default_args );
|
134 |
+
|
135 |
$menu = self::order_children($menu);
|
136 |
$menu = self::strip_to_depth_limit($menu);
|
137 |
}
|
lib/Post.php
CHANGED
@@ -191,7 +191,6 @@ class Post extends Core implements CoreInterface {
|
|
191 |
if ( 'class' === $field ) {
|
192 |
return $this->css_class();
|
193 |
}
|
194 |
-
|
195 |
return parent::__get($field);
|
196 |
}
|
197 |
|
@@ -213,7 +212,7 @@ class Post extends Core implements CoreInterface {
|
|
213 |
* Determined whether or not an admin/editor is looking at the post in "preview mode" via the
|
214 |
* WordPress admin
|
215 |
* @internal
|
216 |
-
* @return bool
|
217 |
*/
|
218 |
protected static function is_previewing() {
|
219 |
global $wp_query;
|
@@ -237,12 +236,7 @@ class Post extends Core implements CoreInterface {
|
|
237 |
&& is_object($wp_query->queried_object)
|
238 |
&& get_class($wp_query->queried_object) == 'WP_Post'
|
239 |
) {
|
240 |
-
|
241 |
-
if ( self::is_previewing() ) {
|
242 |
-
$pid = $this->get_post_preview_id($wp_query);
|
243 |
-
} else if ( !$pid ) {
|
244 |
-
$pid = $wp_query->queried_object_id;
|
245 |
-
}
|
246 |
} else if ( $pid === null && $wp_query->is_home && isset($wp_query->queried_object_id) && $wp_query->queried_object_id ) {
|
247 |
//hack for static page as home page
|
248 |
$pid = $wp_query->queried_object_id;
|
@@ -265,15 +259,6 @@ class Post extends Core implements CoreInterface {
|
|
265 |
if ( $pid === null && ($pid_from_loop = PostGetter::loop_to_id()) ) {
|
266 |
$pid = $pid_from_loop;
|
267 |
}
|
268 |
-
if (
|
269 |
-
isset($_GET['preview'])
|
270 |
-
&& isset($_GET['preview_nonce'])
|
271 |
-
&& wp_verify_nonce($_GET['preview_nonce'], 'post_preview_'.$wp_query->queried_object_id)
|
272 |
-
&& isset($wp_query->queried_object_id)
|
273 |
-
&& ($wp_query->queried_object_id === $pid || (is_object($pid) && $wp_query->queried_object_id === $pid->ID))
|
274 |
-
) {
|
275 |
-
$pid = $this->get_post_preview_id($wp_query);
|
276 |
-
}
|
277 |
return $pid;
|
278 |
}
|
279 |
|
@@ -285,6 +270,14 @@ class Post extends Core implements CoreInterface {
|
|
285 |
return $this->title();
|
286 |
}
|
287 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
288 |
protected function get_post_preview_id( $query ) {
|
289 |
$can = array(
|
290 |
get_post_type_object($query->queried_object->post_type)->cap->edit_post,
|
@@ -561,6 +554,11 @@ class Post extends Core implements CoreInterface {
|
|
561 |
$post->id = $post->ID;
|
562 |
$post->slug = $post->post_name;
|
563 |
$customs = $this->get_post_custom($post->ID);
|
|
|
|
|
|
|
|
|
|
|
564 |
$post->custom = $customs;
|
565 |
$post = (object) array_merge((array) $customs, (array) $post);
|
566 |
return $post;
|
@@ -576,89 +574,167 @@ class Post extends Core implements CoreInterface {
|
|
576 |
return Helper::get_comment_form($this->ID, $args);
|
577 |
}
|
578 |
|
579 |
-
|
580 |
/**
|
581 |
-
*
|
582 |
-
*
|
583 |
* @api
|
|
|
584 |
* @example
|
585 |
* ```twig
|
586 |
* <section id="job-feed">
|
587 |
* {% for post in job %}
|
588 |
-
*
|
589 |
-
*
|
590 |
-
*
|
591 |
-
*
|
592 |
* {% endfor %}
|
593 |
* </section>
|
594 |
* ```
|
595 |
* ```html
|
596 |
* <section id="job-feed">
|
597 |
-
*
|
598 |
-
*
|
599 |
-
*
|
600 |
-
*
|
601 |
-
*
|
602 |
-
*
|
603 |
-
*
|
604 |
-
*
|
605 |
* </section>
|
606 |
* ```
|
607 |
-
*
|
608 |
-
*
|
609 |
-
*
|
610 |
-
|
611 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
612 |
$taxonomies = array();
|
613 |
-
$TermClass = $TermClass ?: $this->TermClass;
|
614 |
|
|
|
615 |
if ( is_string($merge) && class_exists($merge) ) {
|
616 |
-
$
|
617 |
}
|
618 |
-
|
|
|
|
|
619 |
$taxonomies = $tax;
|
620 |
-
}
|
621 |
-
|
622 |
-
if ( in_array($tax, array('all', 'any', '')) ) {
|
623 |
$taxonomies = get_object_taxonomies($this->post_type);
|
624 |
} else {
|
625 |
$taxonomies = array($tax);
|
626 |
}
|
627 |
}
|
628 |
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
if ( in_array($taxonomy, array('tag', 'tags')) ) {
|
633 |
$taxonomy = 'post_tag';
|
634 |
-
}
|
635 |
-
if ( $taxonomy == 'categories' ) {
|
636 |
$taxonomy = 'category';
|
637 |
}
|
638 |
|
639 |
-
|
|
|
640 |
|
641 |
-
|
642 |
-
/* @var $terms WP_Error */
|
643 |
-
Helper::error_log("Error retrieving terms for taxonomy '$taxonomy' on a post in timber-post.php");
|
644 |
-
Helper::error_log('tax = '.print_r($tax, true));
|
645 |
-
Helper::error_log('WP_Error: '.$terms->get_error_message());
|
646 |
|
647 |
-
|
648 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
649 |
|
650 |
-
//
|
651 |
-
|
652 |
-
|
653 |
-
}
|
654 |
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
$term_class_objects[$taxonomy] = $terms;
|
659 |
}
|
|
|
|
|
660 |
}
|
661 |
-
|
|
|
662 |
}
|
663 |
|
664 |
/**
|
@@ -744,6 +820,9 @@ class Post extends Core implements CoreInterface {
|
|
744 |
* @return mixed
|
745 |
*/
|
746 |
public function get_field( $field_name ) {
|
|
|
|
|
|
|
747 |
$value = apply_filters('timber_post_get_meta_field_pre', null, $this->ID, $field_name, $this);
|
748 |
if ( $value === null ) {
|
749 |
$value = get_post_meta($this->ID, $field_name);
|
@@ -789,6 +868,9 @@ class Post extends Core implements CoreInterface {
|
|
789 |
$old_global_post = $post;
|
790 |
$post = $this;
|
791 |
$class_array = get_post_class($class, $this->ID);
|
|
|
|
|
|
|
792 |
$post = $old_global_post;
|
793 |
if ( is_array($class_array) ) {
|
794 |
return implode(' ', $class_array);
|
@@ -1004,6 +1086,16 @@ class Post extends Core implements CoreInterface {
|
|
1004 |
}
|
1005 |
}
|
1006 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1007 |
/**
|
1008 |
* Gets the actual content of a WP Post, as opposed to post_content this will run the hooks/filters attached to the_content. \This guy will return your posts content with WordPress filters run on it (like for shortcodes and wpautop).
|
1009 |
* @api
|
@@ -1018,6 +1110,9 @@ class Post extends Core implements CoreInterface {
|
|
1018 |
* @return string
|
1019 |
*/
|
1020 |
public function content( $page = 0, $len = -1 ) {
|
|
|
|
|
|
|
1021 |
if ( $form = $this->maybe_show_password_form() ) {
|
1022 |
return $form;
|
1023 |
}
|
@@ -1387,6 +1482,9 @@ class Post extends Core implements CoreInterface {
|
|
1387 |
* @return string
|
1388 |
*/
|
1389 |
public function title() {
|
|
|
|
|
|
|
1390 |
return apply_filters('the_title', $this->post_title, $this->ID);
|
1391 |
}
|
1392 |
|
191 |
if ( 'class' === $field ) {
|
192 |
return $this->css_class();
|
193 |
}
|
|
|
194 |
return parent::__get($field);
|
195 |
}
|
196 |
|
212 |
* Determined whether or not an admin/editor is looking at the post in "preview mode" via the
|
213 |
* WordPress admin
|
214 |
* @internal
|
215 |
+
* @return bool
|
216 |
*/
|
217 |
protected static function is_previewing() {
|
218 |
global $wp_query;
|
236 |
&& is_object($wp_query->queried_object)
|
237 |
&& get_class($wp_query->queried_object) == 'WP_Post'
|
238 |
) {
|
239 |
+
$pid = $wp_query->queried_object_id;
|
|
|
|
|
|
|
|
|
|
|
240 |
} else if ( $pid === null && $wp_query->is_home && isset($wp_query->queried_object_id) && $wp_query->queried_object_id ) {
|
241 |
//hack for static page as home page
|
242 |
$pid = $wp_query->queried_object_id;
|
259 |
if ( $pid === null && ($pid_from_loop = PostGetter::loop_to_id()) ) {
|
260 |
$pid = $pid_from_loop;
|
261 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
262 |
return $pid;
|
263 |
}
|
264 |
|
270 |
return $this->title();
|
271 |
}
|
272 |
|
273 |
+
protected function get_post_preview_object() {
|
274 |
+
global $wp_query;
|
275 |
+
if ( $this->is_previewing() ) {
|
276 |
+
$revision_id = $this->get_post_preview_id( $wp_query );
|
277 |
+
return new $this->PostClass( $revision_id );
|
278 |
+
}
|
279 |
+
}
|
280 |
+
|
281 |
protected function get_post_preview_id( $query ) {
|
282 |
$can = array(
|
283 |
get_post_type_object($query->queried_object->post_type)->cap->edit_post,
|
554 |
$post->id = $post->ID;
|
555 |
$post->slug = $post->post_name;
|
556 |
$customs = $this->get_post_custom($post->ID);
|
557 |
+
if ( $this->is_previewing() ) {
|
558 |
+
global $wp_query;
|
559 |
+
$rev_id = $this->get_post_preview_id($wp_query);
|
560 |
+
$customs = $this->get_post_custom($rev_id);
|
561 |
+
}
|
562 |
$post->custom = $customs;
|
563 |
$post = (object) array_merge((array) $customs, (array) $post);
|
564 |
return $post;
|
574 |
return Helper::get_comment_form($this->ID, $args);
|
575 |
}
|
576 |
|
|
|
577 |
/**
|
578 |
+
* Gets the terms associated with the post.
|
579 |
+
*
|
580 |
* @api
|
581 |
+
* @todo Remove deprecated parameters in 2.x
|
582 |
* @example
|
583 |
* ```twig
|
584 |
* <section id="job-feed">
|
585 |
* {% for post in job %}
|
586 |
+
* <div class="job">
|
587 |
+
* <h2>{{ post.title }}</h2>
|
588 |
+
* <p>{{ post.terms('category')|join(', ') }}</p>
|
589 |
+
* </div>
|
590 |
* {% endfor %}
|
591 |
* </section>
|
592 |
* ```
|
593 |
* ```html
|
594 |
* <section id="job-feed">
|
595 |
+
* <div class="job">
|
596 |
+
* <h2>Cheese Maker</h2>
|
597 |
+
* <p>Food, Cheese, Fromage</p>
|
598 |
+
* </div>
|
599 |
+
* <div class="job">
|
600 |
+
* <h2>Mime</h2>
|
601 |
+
* <p>Performance, Silence</p>
|
602 |
+
* </div>
|
603 |
* </section>
|
604 |
* ```
|
605 |
+
* ```php
|
606 |
+
* // Get all terms of a taxonomy.
|
607 |
+
* $terms = $post->terms( 'category' );
|
608 |
+
*
|
609 |
+
* // Get terms of multiple taxonomies.
|
610 |
+
* $terms = $post->terms( array( 'books', 'movies' ) );
|
611 |
+
*
|
612 |
+
* // Use custom arguments for taxonomy query and options.
|
613 |
+
* $terms = $post->terms( array(
|
614 |
+
* 'query' => [
|
615 |
+
* 'taxonomy' => 'custom_tax',
|
616 |
+
* 'orderby' => 'count',
|
617 |
+
* ],
|
618 |
+
* 'merge' => false,
|
619 |
+
* 'term_class' => 'My_Term_Class'
|
620 |
+
* ) );
|
621 |
+
* ```
|
622 |
+
*
|
623 |
+
* @param string|array $args {
|
624 |
+
* Optional. Name of the taxonomy or array of arguments.
|
625 |
+
*
|
626 |
+
* @type array $query Any array of term query parameters for getting the terms. See
|
627 |
+
* `WP_Term_Query::__construct()` for supported arguments. Use the
|
628 |
+
* `taxonomy` argument to choose which taxonomies to get. Defaults
|
629 |
+
* to querying all registered taxonomies for the post type. You can
|
630 |
+
* use custom or built-in WordPress taxonomies (category, tag).
|
631 |
+
* Timber plays nice and figures out that `tag`, `tags` or
|
632 |
+
* `post_tag` are all the same (also for `categories` or
|
633 |
+
* `category`). For custom taxonomies you need to define the
|
634 |
+
* proper name.
|
635 |
+
* @type bool $merge Whether the resulting array should be one big one (`true`) or
|
636 |
+
* whether it should be an array of sub-arrays for each taxonomy
|
637 |
+
* (`false`). Default `true`.
|
638 |
+
* @type string $term_class The Timber term class to use for the term objects.
|
639 |
+
* }
|
640 |
+
* @param bool $merge Deprecated. Optional. See `$merge` argument in `$args` parameter.
|
641 |
+
* @param string $term_class Deprecated. Optional. See `$term_class` argument in `$args`
|
642 |
+
* parameter.
|
643 |
+
* @return array An array of taxonomies.
|
644 |
+
*/
|
645 |
+
public function terms( $args = array(), $merge = true, $term_class = '' ) {
|
646 |
+
// Ensure backwards compatibility.
|
647 |
+
if ( ! is_array( $args ) || isset( $args[0] ) ) {
|
648 |
+
$args = array(
|
649 |
+
'query' => array(
|
650 |
+
'taxonomy' => $args,
|
651 |
+
),
|
652 |
+
'merge' => $merge,
|
653 |
+
'term_class' => $term_class,
|
654 |
+
);
|
655 |
+
|
656 |
+
if ( empty( $args['term_class']) ) {
|
657 |
+
$args['term_class'] = $this->TermClass;
|
658 |
+
}
|
659 |
+
}
|
660 |
+
|
661 |
+
// Defaults.
|
662 |
+
$args = wp_parse_args( $args, array(
|
663 |
+
'query' => array(
|
664 |
+
'taxonomy' => 'all',
|
665 |
+
),
|
666 |
+
'merge' => true,
|
667 |
+
'term_class' => $this->TermClass,
|
668 |
+
) );
|
669 |
+
|
670 |
+
$tax = $args['query']['taxonomy'];
|
671 |
+
$merge = $args['merge'];
|
672 |
+
$term_class = $args['term_class'];
|
673 |
+
|
674 |
$taxonomies = array();
|
|
|
675 |
|
676 |
+
// @todo: Remove in 2.x
|
677 |
if ( is_string($merge) && class_exists($merge) ) {
|
678 |
+
$term_class = $merge;
|
679 |
}
|
680 |
+
|
681 |
+
// Build an array of taxonomies.
|
682 |
+
if ( is_array( $tax ) ) {
|
683 |
$taxonomies = $tax;
|
684 |
+
} elseif ( is_string( $tax ) ) {
|
685 |
+
if ( in_array( $tax, array( 'all', 'any', '' ) ) ) {
|
|
|
686 |
$taxonomies = get_object_taxonomies($this->post_type);
|
687 |
} else {
|
688 |
$taxonomies = array($tax);
|
689 |
}
|
690 |
}
|
691 |
|
692 |
+
// @todo Remove in 2.x
|
693 |
+
$taxonomies = array_map( function( $taxonomy ) {
|
694 |
+
if ( in_array( $taxonomy, array( 'tag', 'tags' ), true ) ) {
|
|
|
695 |
$taxonomy = 'post_tag';
|
696 |
+
} elseif ( 'categories' === $taxonomy ) {
|
|
|
697 |
$taxonomy = 'category';
|
698 |
}
|
699 |
|
700 |
+
return $taxonomy;
|
701 |
+
}, $taxonomies );
|
702 |
|
703 |
+
$terms = wp_get_post_terms( $this->ID, $taxonomies, $args['query'] );
|
|
|
|
|
|
|
|
|
704 |
|
705 |
+
if ( is_wp_error( $terms ) ) {
|
706 |
+
/**
|
707 |
+
* @var $terms \WP_Error
|
708 |
+
*/
|
709 |
+
Helper::error_log( "Error retrieving terms for taxonomies on a post in timber-post.php" );
|
710 |
+
Helper::error_log( 'tax = ' . print_r( $tax, true ) );
|
711 |
+
Helper::error_log( 'WP_Error: ' . $terms->get_error_message() );
|
712 |
+
|
713 |
+
return $terms;
|
714 |
+
}
|
715 |
+
|
716 |
+
// Map over array of WordPress terms and transform them into instances of the chosen term class.
|
717 |
+
$terms = array_map( function( $term ) use ( $term_class ) {
|
718 |
+
return call_user_func( array( $term_class, 'from' ), $term->term_id, $term->taxonomy );
|
719 |
+
}, $terms );
|
720 |
+
|
721 |
+
if ( ! $merge ) {
|
722 |
+
$terms_sorted = array();
|
723 |
|
724 |
+
// Initialize sub-arrays.
|
725 |
+
foreach ( $taxonomies as $taxonomy ) {
|
726 |
+
$terms_sorted[ $taxonomy ] = array();
|
727 |
+
}
|
728 |
|
729 |
+
// Fill terms into arrays.
|
730 |
+
foreach ( $terms as $term ) {
|
731 |
+
$terms_sorted[ $term->taxonomy ][] = $term;
|
|
|
732 |
}
|
733 |
+
|
734 |
+
return $terms_sorted;
|
735 |
}
|
736 |
+
|
737 |
+
return $terms;
|
738 |
}
|
739 |
|
740 |
/**
|
820 |
* @return mixed
|
821 |
*/
|
822 |
public function get_field( $field_name ) {
|
823 |
+
if ( $rd = $this->get_revised_data_from_method('get_field', $field_name) ) {
|
824 |
+
return $rd;
|
825 |
+
}
|
826 |
$value = apply_filters('timber_post_get_meta_field_pre', null, $this->ID, $field_name, $this);
|
827 |
if ( $value === null ) {
|
828 |
$value = get_post_meta($this->ID, $field_name);
|
868 |
$old_global_post = $post;
|
869 |
$post = $this;
|
870 |
$class_array = get_post_class($class, $this->ID);
|
871 |
+
if ( $this->is_previewing() ) {
|
872 |
+
$class_array = get_post_class($class, $this->post_parent);
|
873 |
+
}
|
874 |
$post = $old_global_post;
|
875 |
if ( is_array($class_array) ) {
|
876 |
return implode(' ', $class_array);
|
1086 |
}
|
1087 |
}
|
1088 |
|
1089 |
+
/**
|
1090 |
+
*
|
1091 |
+
*/
|
1092 |
+
protected function get_revised_data_from_method( $method, ...$args ) {
|
1093 |
+
$rev = $this->get_post_preview_object();
|
1094 |
+
if ( $rev && $this->ID == $rev->post_parent && $this->ID != $rev->ID ) {
|
1095 |
+
return call_user_func_array( array($rev, $method), $args );
|
1096 |
+
}
|
1097 |
+
}
|
1098 |
+
|
1099 |
/**
|
1100 |
* Gets the actual content of a WP Post, as opposed to post_content this will run the hooks/filters attached to the_content. \This guy will return your posts content with WordPress filters run on it (like for shortcodes and wpautop).
|
1101 |
* @api
|
1110 |
* @return string
|
1111 |
*/
|
1112 |
public function content( $page = 0, $len = -1 ) {
|
1113 |
+
if ( $rd = $this->get_revised_data_from_method('content', $page, $len) ) {
|
1114 |
+
return $rd;
|
1115 |
+
}
|
1116 |
if ( $form = $this->maybe_show_password_form() ) {
|
1117 |
return $form;
|
1118 |
}
|
1482 |
* @return string
|
1483 |
*/
|
1484 |
public function title() {
|
1485 |
+
if ( $rd = $this->get_revised_data_from_method('title') ) {
|
1486 |
+
return $rd;
|
1487 |
+
}
|
1488 |
return apply_filters('the_title', $this->post_title, $this->ID);
|
1489 |
}
|
1490 |
|
lib/Timber.php
CHANGED
@@ -35,7 +35,7 @@ use Timber\Loader;
|
|
35 |
*/
|
36 |
class Timber {
|
37 |
|
38 |
-
public static $version = '1.8.
|
39 |
public static $locations;
|
40 |
public static $dirname = 'views';
|
41 |
public static $twig_cache = false;
|
35 |
*/
|
36 |
class Timber {
|
37 |
|
38 |
+
public static $version = '1.8.2';
|
39 |
public static $locations;
|
40 |
public static $dirname = 'views';
|
41 |
public static $twig_cache = false;
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: jarednova, connorjburton, lggorman
|
|
3 |
Tags: template engine, templates, twig
|
4 |
Requires at least: 4.7.9
|
5 |
Tested up to: 4.9.6
|
6 |
-
Stable tag: 1.8.
|
7 |
PHP version: 5.3.0 or greater
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
@@ -34,7 +34,19 @@ _Twig is the template language powering Timber; if you need a little background
|
|
34 |
- Please add bullet points here with your PR. The heading for this section will get the correct version number once released.
|
35 |
|
36 |
**Changes for Theme Developers**
|
37 |
-
- Please add
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
|
39 |
= 1.8.1 =
|
40 |
**Fixes and improvements**
|
3 |
Tags: template engine, templates, twig
|
4 |
Requires at least: 4.7.9
|
5 |
Tested up to: 4.9.6
|
6 |
+
Stable tag: 1.8.2
|
7 |
PHP version: 5.3.0 or greater
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
34 |
- Please add bullet points here with your PR. The heading for this section will get the correct version number once released.
|
35 |
|
36 |
**Changes for Theme Developers**
|
37 |
+
- Please add bullet points here with your PR. The heading for this section will get the correct version number once released.
|
38 |
+
|
39 |
+
|
40 |
+
= 1.8.2 =
|
41 |
+
|
42 |
+
**Changes for Theme Developers**
|
43 |
+
- You can now change the query parameters that are used when getting a post’s terms through `$post->terms()`. #1802
|
44 |
+
- New attributes for responsive images `post.thumbnail.srcset` and `post.thumbnail.sizes` #1819 (thanks @maxxwv)
|
45 |
+
|
46 |
+
**Fixes and improvements**
|
47 |
+
- Using WordPress's `wp_check_filetype_and_ext` for the mime_type mess #1843 (thanks @gchtr)
|
48 |
+
- Fixed how some previewed data (when looking at an unsaved post from the admin) is handled so that parenting relationships match what happens when published #1752
|
49 |
+
- Timber\Menu now respects modifications sent through WP's `wp_nav_menu_objects` filter #1814 (thanks @pascalknecht)
|
50 |
|
51 |
= 1.8.1 =
|
52 |
**Fixes and improvements**
|
timber-starter-theme/index.php
CHANGED
@@ -18,6 +18,6 @@ $context['posts'] = new Timber\PostQuery();
|
|
18 |
$context['foo'] = 'bar';
|
19 |
$templates = array( 'index.twig' );
|
20 |
if ( is_home() ) {
|
21 |
-
array_unshift( $templates, 'home.twig' );
|
22 |
}
|
23 |
Timber::render( $templates, $context );
|
18 |
$context['foo'] = 'bar';
|
19 |
$templates = array( 'index.twig' );
|
20 |
if ( is_home() ) {
|
21 |
+
array_unshift( $templates, 'front-page.twig', 'home.twig' );
|
22 |
}
|
23 |
Timber::render( $templates, $context );
|
timber.php
CHANGED
@@ -4,7 +4,7 @@ Plugin Name: Timber
|
|
4 |
Description: The WordPress Timber Library allows you to write themes using the power of Twig templates.
|
5 |
Plugin URI: http://timber.upstatement.com
|
6 |
Author: Jared Novack + Upstatement
|
7 |
-
Version: 1.8.
|
8 |
Author URI: http://upstatement.com/
|
9 |
*/
|
10 |
// we look for Composer files first in the plugins dir.
|
4 |
Description: The WordPress Timber Library allows you to write themes using the power of Twig templates.
|
5 |
Plugin URI: http://timber.upstatement.com
|
6 |
Author: Jared Novack + Upstatement
|
7 |
+
Version: 1.8.2
|
8 |
Author URI: http://upstatement.com/
|
9 |
*/
|
10 |
// we look for Composer files first in the plugins dir.
|
vendor/autoload.php
CHANGED
@@ -4,4 +4,4 @@
|
|
4 |
|
5 |
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
6 |
|
7 |
-
return
|
4 |
|
5 |
require_once __DIR__ . '/composer' . '/autoload_real.php';
|
6 |
|
7 |
+
return ComposerAutoloaderInitdfecad9ee9bb796afe4d3895d7c737f7::getLoader();
|
vendor/composer/autoload_real.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
-
class
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -19,9 +19,9 @@ class ComposerAutoloaderInit6fa8f4c34559c8e21a30db28ddb43132
|
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
-
spl_autoload_register(array('
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
-
spl_autoload_unregister(array('
|
25 |
|
26 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
27 |
foreach ($map as $namespace => $path) {
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInitdfecad9ee9bb796afe4d3895d7c737f7
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInitdfecad9ee9bb796afe4d3895d7c737f7', 'loadClassLoader'), true, true);
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInitdfecad9ee9bb796afe4d3895d7c737f7', 'loadClassLoader'));
|
25 |
|
26 |
$map = require __DIR__ . '/autoload_namespaces.php';
|
27 |
foreach ($map as $namespace => $path) {
|