• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

timber / timber / 20846050397

09 Jan 2026 08:35AM UTC coverage: 89.608%. Remained the same
20846050397

Pull #3181

travis-ci

web-flow
Merge 5bae5023f into 6ae23b1a2
Pull Request #3181: test: Fix issue with image test that sets a constant

4596 of 5129 relevant lines covered (89.61%)

63.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.08
/src/Loader.php
1
<?php
2

3
namespace Timber;
4

5
use InvalidArgumentException;
6
use Timber\Cache\Cleaner;
7
use Twig\CacheExtension;
8
use Twig\Environment;
9
use Twig\Extension\DebugExtension;
10
use Twig\Loader\FilesystemLoader;
11
use Twig\TwigFunction;
12

13
class Loader
14
{
15
    public const CACHEGROUP = 'timberloader';
16

17
    public const TRANS_KEY_LEN = 50;
18

19
    public const CACHE_NONE = 'none';
20

21
    public const CACHE_OBJECT = 'cache';
22

23
    public const CACHE_TRANSIENT = 'transient';
24

25
    public const CACHE_SITE_TRANSIENT = 'site-transient';
26

27
    public const CACHE_USE_DEFAULT = 'default';
28

29
    /** Identifier of the main namespace. Will likely mirror Twig\Loader\FilesystemLoader::MAIN_NAMESPACE */
30
    public const MAIN_NAMESPACE = '__main__';
31

32
    public static $cache_modes = [
33
        self::CACHE_NONE,
34
        self::CACHE_OBJECT,
35
        self::CACHE_TRANSIENT,
36
        self::CACHE_SITE_TRANSIENT,
37
    ];
38

39
    protected $cache_mode = self::CACHE_TRANSIENT;
40

41
    protected $locations;
42

43
    /**
44
     * @param bool|string   $caller the calling directory or false
45
     */
46
    public function __construct($caller = false)
429✔
47
    {
48
        $this->locations = LocationManager::get_locations($caller);
429✔
49

50
        /**
51
         * Filters the cache mode.
52
         *
53
         * You can read more about Caching in the
54
         * [Performance/Caching]({{<relref "performance.md" >}}) guide.
55
         *
56
         * @since 0.20.10
57
         *
58
         * @param string $cache_mode The cache mode. Can be one of the following:
59
         *                           `Timber\Loader::CACHE_NONE`,
60
         *                           `Timber\Loader::CACHE_OBJECT`,
61
         *                           `Timber\Loader::CACHE_TRANSIENT`,
62
         *                           `Timber\Loader::CACHE_SITE_TRANSIENT`,
63
         *                           `Timber\Loader::CACHE_USE_DEFAULT`.
64
         *                           Default `Timber\Loader::CACHE_TRANSIENT`.
65
         */
66
        $this->cache_mode = \apply_filters('timber/cache/mode', $this->cache_mode);
429✔
67

68
        /**
69
         * Filters the cache mode.
70
         *
71
         * @deprecated 2.0.0, use `timber/cache/mode`
72
         */
73
        $this->cache_mode = \apply_filters_deprecated(
429✔
74
            'timber_cache_mode',
429✔
75
            [$this->cache_mode],
429✔
76
            '2.0.0',
429✔
77
            'timber/cache/mode'
429✔
78
        );
429✔
79
    }
80

81
    /**
82
     * @param string            $file
83
     * @param array             $data
84
     * @param array|boolean        $expires (array for options, false for none, integer for # of seconds)
85
     * @param string            $cache_mode
86
     * @return bool|string
87
     */
88
    public function render($file, $data = null, $expires = false, $cache_mode = self::CACHE_USE_DEFAULT)
81✔
89
    {
90
        // Different $expires if user is anonymous or logged in
91
        if (\is_array($expires)) {
81✔
92
            /** @var array $expires */
93
            if (\is_user_logged_in() && isset($expires[1])) {
4✔
94
                $expires = $expires[1];
1✔
95
            } else {
96
                $expires = $expires[0];
3✔
97
            }
98
        }
99

100
        if ($expires === 0) {
81✔
101
            $expires = false;
×
102
        }
103

104
        $key = null;
81✔
105
        $output = false;
81✔
106
        if (false !== $expires) {
81✔
107
            \ksort($data);
14✔
108
            $encoded = \json_encode($data);
14✔
109

110
            /**
111
             * The encoding might fail, e.g. when an object has a recursion. In that case, we’d rather not cache the
112
             * data instead of possibly returning the wrong data.
113
             */
114
            if (false !== $encoded) {
14✔
115
                $key = \md5($file . $encoded);
14✔
116
                $output = $this->get_cache($key, self::CACHEGROUP, $cache_mode);
14✔
117
            }
118
        }
119

120
        if (false === $output || null === $output) {
81✔
121
            $twig = $this->get_twig();
81✔
122
            if (\strlen($file)) {
81✔
123
                $loader = $this->get_loader();
81✔
124
                $result = $loader->getCacheKey($file);
81✔
125

126
                /**
127
                 * Fires after …
128
                 *
129
                 * @todo Add summary, description parameter description
130
                 *
131
                 * @param string $result
132
                 */
133
                \do_action('timber/loader/render_file', $result);
81✔
134

135
                /**
136
                 * Fires after …
137
                 *
138
                 * This action is used by the Timber Debug Bar extension.
139
                 *
140
                 * @todo Add summary
141
                 *
142
                 * @deprecated 2.0.0, use `timber/loader/render_file`
143
                 */
144
                \do_action_deprecated(
81✔
145
                    'timber_loader_render_file',
81✔
146
                    [$result],
81✔
147
                    '2.0.0',
81✔
148
                    'timber/loader/render_file'
81✔
149
                );
81✔
150
            }
151

152
            /**
153
             * Filters …
154
             *
155
             * @todo Add summary, description, example, parameter descriptions
156
             *
157
             * @since 0.20.10
158
             *
159
             * @param array  $data
160
             * @param string $file
161
             */
162
            $data = \apply_filters('timber/loader/render_data', $data, $file);
81✔
163

164
            /**
165
             * Filters …
166
             *
167
             * @todo Add summary
168
             *
169
             * @deprecated 2.0.0, use `timber/loader/render_data`
170
             */
171
            $data = \apply_filters_deprecated(
81✔
172
                'timber_loader_render_data',
81✔
173
                [$data],
81✔
174
                '2.0.0',
81✔
175
                'timber/loader/render_data'
81✔
176
            );
81✔
177

178
            $template = $twig->load($file);
81✔
179
            $output = $template->render($data);
80✔
180

181
            /**
182
             * Filters $output before it is cached.
183
             *
184
             * @since 2.1.0
185
             *
186
             * @param string $output
187
             * @param array  $data
188
             * @param string $file
189
             */
190
            $output = \apply_filters('timber/output/pre-cache', $output, $data, $file);
80✔
191
        }
192

193
        if (false !== $output && false !== $expires && null !== $key) {
80✔
194
            $this->delete_cache();
14✔
195
            $this->set_cache($key, $output, self::CACHEGROUP, $expires, $cache_mode);
14✔
196
        }
197

198
        /**
199
         * Filters …
200
         *
201
         * @todo  Add summary, description, example, parameter descriptions
202
         *
203
         * @since 0.20.10
204
         *
205
         * @param string $output
206
         * @param array  $data
207
         * @param string $file
208
         */
209
        $output = \apply_filters('timber/output', $output, $data, $file);
80✔
210

211
        /**
212
         * Filters …
213
         *
214
         * @todo Add summary
215
         *
216
         * @deprecated 2.0.0, use `timber/output`
217
         */
218
        $output = \apply_filters_deprecated('timber_output', [$output], '2.0.0', 'timber/output');
80✔
219

220
        return $output;
80✔
221
    }
222

223
    protected function delete_cache()
14✔
224
    {
225
        Cleaner::delete_transients();
14✔
226
    }
227

228
    /**
229
     * Get first existing template.
230
     *
231
     * @param array|string $templates  Name(s) of the Twig template(s) to choose from.
232
     * @return string|bool             Name of chosen template, otherwise false.
233
     */
234
    public function choose_template($templates)
85✔
235
    {
236
        // Change $templates into array, if needed
237
        if (!\is_array($templates)) {
85✔
238
            $templates = (array) $templates;
81✔
239
        }
240

241
        // Get Twig loader
242
        $loader = $this->get_loader();
85✔
243

244
        // Run through template array
245
        foreach ($templates as $template) {
85✔
246
            // Remove any whitespace around the template name
247
            $template = \trim((string) $template);
85✔
248
            // Use the Twig loader to test for existence
249
            if ($loader->exists($template)) {
85✔
250
                // Return name of existing template
251
                return $template;
81✔
252
            }
253
        }
254

255
        // No existing template was found
256
        return false;
4✔
257
    }
258

259
    /**
260
     * @return FilesystemLoader
261
     */
262
    public function get_loader()
419✔
263
    {
264
        $paths = $this->locations;
419✔
265

266
        /**
267
         * Filters the template paths used by the Loader.
268
         *
269
         * @since 0.20.10
270
         *
271
         * @deprecated 2.0.0, use `timber/locations`
272
         *
273
         * @param array $paths
274
         */
275
        $paths = \apply_filters_deprecated(
419✔
276
            'timber/loader/paths',
419✔
277
            [$paths],
419✔
278
            '2.0.0',
419✔
279
            'timber/locations'
419✔
280
        );
419✔
281

282
        $open_basedir = \ini_get('open_basedir');
419✔
283
        $rootPath = '/';
419✔
284
        if ($open_basedir) {
419✔
285
            $rootPath = null;
×
286
        }
287

288
        $fs = new FilesystemLoader([], $rootPath);
419✔
289

290
        foreach ($paths as $namespace => $path_locations) {
419✔
291
            if (\is_array($path_locations)) {
419✔
292
                \array_map(function ($path) use ($fs, $namespace) {
418✔
293
                    if (\is_string($namespace)) {
418✔
294
                        $fs->addPath($path, $namespace);
418✔
295
                    } else {
296
                        $fs->addPath($path, Loader::MAIN_NAMESPACE);
7✔
297
                    }
298
                }, $path_locations);
418✔
299
            } else {
300
                Helper::deprecated(
2✔
301
                    'add_filter( \'timber/loader/paths\', [\'path/to/my/templates\'] ) in a non-associative array',
2✔
302
                    'add_filter( \'timber/loader/paths\', [ 0 => [ \'path/to/my/templates\' ] ] )',
2✔
303
                    '2.0.0'
2✔
304
                );
2✔
305
                $fs->addPath($path_locations, self::MAIN_NAMESPACE);
2✔
306
            }
307
        }
308

309
        /**
310
         * Filters …
311
         *
312
         * @todo Add summary, description, example, parameter description
313
         *
314
         * @link https://github.com/timber/timber/pull/1254
315
         * @since 1.1.11
316
         */
317
        $fs = \apply_filters('timber/loader/loader', $fs);
419✔
318

319
        return $fs;
419✔
320
    }
321

322
    /**
323
     * @return Environment
324
     */
325
    public function get_twig()
415✔
326
    {
327
        // Default options.
328
        $environment_options = [
415✔
329
            'debug' => WP_DEBUG,
415✔
330
            'autoescape' => false,
415✔
331
            'cache' => false,
415✔
332
        ];
415✔
333

334
        /**
335
         * Filters the environment options that are used when creating a Twig Environment instance.
336
         *
337
         * By default, Timber sets the following values:
338
         *
339
         * - `'debug' => WP_DEBUG`
340
         * - `'autoescape' => false`
341
         * - `'cache' => false`
342
         *
343
         * @api
344
         * @since 1.9.5
345
         * @link https://twig.symfony.com/doc/2.x/api.html#environment-options
346
         * @example
347
         * ```php
348
         * add_filter( 'timber/twig/environment/options', 'update_twig_environment_options' );
349
         *
350
         * /**
351
         *  * Updates Twig environment options.
352
         *  *
353
         *  * @link https://twig.symfony.com/doc/2.x/api.html#environment-options
354
         *  *
355
         *  * \@param array $options An array of environment options.
356
         *  *
357
         *  * @return array
358
         *  *\/
359
         * function update_twig_environment_options( $options ) {
360
         *     $options['cache']       = true;
361
         *     $options['auto_reload'] = true;
362
         *
363
         *     return $options;
364
         * }
365
         * ```
366
         *
367
         * @param array $environment_options An array of Twig environment options.
368
         */
369
        $environment_options = \apply_filters(
415✔
370
            'timber/twig/environment/options',
415✔
371
            $environment_options
415✔
372
        );
415✔
373

374
        /**
375
         * @deprecated 2.0.0
376
         */
377
        if (isset(Timber::$autoescape) && false !== Timber::$autoescape) {
415✔
378
            Helper::deprecated(
1✔
379
                'Timber::$autoescape',
1✔
380
                'the \'timber/twig/environment/options filter\'',
1✔
381
                '2.0.0'
1✔
382
            );
1✔
383

384
            $environment_options['autoescape'] = Timber::$autoescape;
1✔
385
        }
386

387
        /**
388
         * Backwards compatibility fix.
389
         *
390
         * The value `true` doesn’t exist anymore for the `autoescape` option. You need to define
391
         * an auto-escaping fallback strategy. This fallback uses the `html` strategy.
392
         */
393
        if (true === $environment_options['autoescape']) {
415✔
394
            $environment_options['autoescape'] = 'html';
2✔
395
        }
396

397
        /**
398
         * Alias Timber::$cache can be used for Timber::$twig_cache.
399
         *
400
         * @deprecated 2.0.0
401
         */
402
        if (isset(Timber::$cache) && true === Timber::$cache) {
415✔
403
            Timber::$twig_cache = true;
1✔
404
        }
405

406
        /**
407
         * @deprecated 2.0.0
408
         */
409
        if (isset(Timber::$twig_cache) && false !== Timber::$twig_cache) {
415✔
410
            Helper::deprecated(
2✔
411
                'Timber::$cache and Timber::$twig_cache',
2✔
412
                'the \'timber/twig/environment/options filter\'',
2✔
413
                '2.0.0'
2✔
414
            );
2✔
415

416
            $environment_options['cache'] = Timber::$twig_cache;
2✔
417
        }
418

419
        if (true === $environment_options['cache']) {
415✔
420
            $twig_cache_loc = TIMBER_LOC . '/cache/twig';
8✔
421

422
            /**
423
             * Filters the cache location used for Twig.
424
             *
425
             * Allows you to set a new cache location for Twig. If the folder doesn’t exist yet, it
426
             * will be created automatically.
427
             *
428
             * @since 0.20.10
429
             * @deprecated 2.0.0
430
             *
431
             * @param string $twig_cache_loc Full path to the cache location. Default `/cache/twig`
432
             *                               in the Timber root folder.
433
             */
434
            $twig_cache_loc = \apply_filters_deprecated(
8✔
435
                'timber/cache/location',
8✔
436
                [$twig_cache_loc],
8✔
437
                '2.0.0',
8✔
438
                'timber/twig/environment/options'
8✔
439
            );
8✔
440

441
            if (!\file_exists($twig_cache_loc)) {
8✔
442
                \mkdir($twig_cache_loc, 0777, true);
8✔
443
            }
444

445
            $environment_options['cache'] = $twig_cache_loc;
8✔
446
        }
447
        $twig = new Environment($this->get_loader(), $environment_options);
415✔
448

449
        if (WP_DEBUG) {
415✔
450
            $twig->addExtension(new DebugExtension());
415✔
451
        } else {
452
            $twig->addFunction(new TwigFunction('dump', fn () => null));
×
453
        }
454

455
        /**
456
         * Filters the cache extension activation.
457
         *
458
         * Allows users to disable the cache extension and use their own
459
         *
460
         * @since 2.0.0
461
         * @param bool $enable_cache_extension Whether to enable the cache extension.
462
         */
463
        $enable_cache_extension = \apply_filters('timber/cache/enable_extension', true);
415✔
464

465
        if ($enable_cache_extension && \class_exists(CacheExtension\Extension::class)) {
415✔
466
            $twig->addExtension($this->_get_cache_extension());
×
467
        }
468

469
        /**
470
         * Filters …
471
         *
472
         * @todo Add summary, description, example
473
         *
474
         * @since 0.20.10
475
         *
476
         * @param Environment $twig The Twig environment you can add functionality to.
477
         */
478
        $twig = \apply_filters('timber/loader/twig', $twig);
415✔
479

480
        /**
481
         * Filters …
482
         *
483
         * @deprecated 2.0.0, use `timber/twig`
484
         */
485
        $twig = \apply_filters_deprecated('twig_apply_filters', [$twig], '2.0.0', 'timber/twig');
415✔
486

487
        /**
488
         * Filters the Twig environment used in the global context.
489
         *
490
         * You can use this filter if you want to add additional functionality to Twig, like global
491
         * variables, filters or functions.
492
         *
493
         * @since 0.21.9
494
         * @example
495
         * ```php
496
         * /**
497
         *  * Adds Twig functionality.
498
         *  *
499
         *  * \@param \Twig\Environment $twig The Twig Environment to which you can add additional functionality.
500
         *  *\/
501
         * add_filter( 'timber/twig', function( $twig ) {
502
         *     // Make get_theme_file_uri() usable as {{ theme_file() }} in Twig.
503
         *     $twig->addFunction( new Twig\TwigFunction( 'theme_file', 'get_theme_file_uri' ) );
504
         *
505
         *     return $twig;
506
         * } );
507
         * ```
508
         *
509
         * ```twig
510
         * <a class="navbar-brand" href="{{ site.url }}">
511
         *     <img src="{{ theme_file( 'build/img/logo-example.svg' ) }}" alt="Logo {{ site.title }}">
512
         * </a>
513
         * ```
514
         *
515
         * @param Environment $twig The Twig environment.
516
         */
517
        $twig = \apply_filters('timber/twig', $twig);
415✔
518

519
        /**
520
         * Filters the Twig environment used in the global context.
521
         *
522
         * @deprecated 2.0.0
523
         */
524
        $twig = \apply_filters_deprecated('get_twig', [$twig], '2.0.0', 'timber/twig');
415✔
525

526
        return $twig;
415✔
527
    }
528

529
    /**
530
     * Clears Timber’s cache.
531
     *
532
     * @param string $cache_mode
533
     * @return bool Whether Timber’s cache was cleared
534
     */
535
    public function clear_cache_timber($cache_mode = self::CACHE_USE_DEFAULT)
9✔
536
    {
537
        //_transient_timberloader
538
        $cache_mode = $this->_get_cache_mode($cache_mode);
9✔
539

540
        if (self::CACHE_TRANSIENT === $cache_mode || self::CACHE_SITE_TRANSIENT === $cache_mode) {
9✔
541
            // $wpdb->query() might return 0 affected rows, but that means it’s still successful.
542
            return false !== self::clear_cache_timber_database();
8✔
543
        } elseif (self::CACHE_OBJECT === $cache_mode && $this->is_object_cache()) {
1✔
544
            return false !== self::clear_cache_timber_object();
1✔
545
        }
546

547
        return false;
×
548
    }
549

550
    /**
551
     * Clears Timber cache in database.
552
     *
553
     * @return bool|int Number of deleted rows or false on error.
554
     */
555
    protected static function clear_cache_timber_database()
8✔
556
    {
557
        global $wpdb;
558

559
        return $wpdb->query($wpdb->prepare(
8✔
560
            "DELETE FROM $wpdb->options WHERE option_name LIKE '%s'",
8✔
561
            '_transient%timberloader_%'
8✔
562
        ));
8✔
563
    }
564

565
    /**
566
     * @return bool True when no cache was found or all cache was deleted, false when there was an
567
     *              error deleting the cache.
568
     */
569
    protected static function clear_cache_timber_object()
1✔
570
    {
571
        global $wp_object_cache;
572

573
        $result = true;
1✔
574

575
        // Return true if no object cache is set.
576
        if (!isset($wp_object_cache->cache[self::CACHEGROUP])) {
1✔
577
            return $result;
×
578
        }
579

580
        $items = $wp_object_cache->cache[self::CACHEGROUP];
1✔
581

582
        foreach ($items as $key => $value) {
1✔
583
            if (\is_multisite()) {
1✔
584
                $key = \preg_replace('/^(.*?):/', '', (string) $key);
×
585
            }
586

587
            // If any cache couldn’t be deleted, the result will be false.
588
            if (!\wp_cache_delete($key, self::CACHEGROUP)) {
1✔
589
                $result = false;
×
590
            }
591
        }
592

593
        return $result;
1✔
594
    }
595

596
    public function clear_cache_twig()
11✔
597
    {
598
        $twig = $this->get_twig();
11✔
599

600
        // Get the configured cache location.
601
        $cache_location = $twig->getCache(true);
11✔
602

603
        // Cache not activated.
604
        if (!$cache_location) {
11✔
605
            return true;
3✔
606
        }
607

608
        if (\is_string($cache_location) && \is_dir($cache_location)) {
8✔
609
            self::rrmdir($cache_location);
8✔
610
            return true;
8✔
611
        }
612

613
        return false;
×
614
    }
615

616
    /**
617
     * Remove a directory and everything inside
618
     *
619
     * @param string|false $dirPath
620
     */
621
    public static function rrmdir($dirPath)
8✔
622
    {
623
        if (!\is_dir($dirPath)) {
8✔
624
            throw new InvalidArgumentException("$dirPath must be a directory");
×
625
        }
626
        if (\substr($dirPath, \strlen($dirPath) - 1, 1) != '/') {
8✔
627
            $dirPath .= '/';
8✔
628
        }
629
        $files = \glob($dirPath . '*', GLOB_MARK);
8✔
630
        foreach ($files as $file) {
8✔
631
            if (\is_dir($file)) {
×
632
                self::rrmdir($file);
×
633
            } else {
634
                \unlink($file);
×
635
            }
636
        }
637
        \rmdir($dirPath);
8✔
638
    }
639

640
    /**
641
     * @return CacheExtension\Extension
642
     */
643
    private function _get_cache_extension()
×
644
    {
645
        $key_generator = new Cache\KeyGenerator();
×
646
        $cache_provider = new Cache\WPObjectCacheAdapter($this);
×
647
        $cache_lifetime = \apply_filters('timber/cache/extension/lifetime', 0);
×
648
        $cache_strategy = new CacheExtension\CacheStrategy\GenerationalCacheStrategy(
×
649
            $cache_provider,
×
650
            $key_generator,
×
651
            $cache_lifetime
×
652
        );
×
653
        $cache_extension = new CacheExtension\Extension($cache_strategy);
×
654

655
        return $cache_extension;
×
656
    }
657

658
    /**
659
     * @param string $key
660
     * @param string $group
661
     * @param string $cache_mode
662
     * @return bool
663
     */
664
    public function get_cache($key, $group = self::CACHEGROUP, $cache_mode = self::CACHE_USE_DEFAULT)
20✔
665
    {
666
        $cache_mode = $this->_get_cache_mode($cache_mode);
20✔
667
        $value = false;
20✔
668
        $trans_key = \substr($group . '_' . $key, 0, self::TRANS_KEY_LEN);
20✔
669

670
        /**
671
         * Filters the transient key used for caching.
672
         *
673
         * @api
674
         * @since 2.1.0
675
         * @example
676
         * ```
677
         * add_filter( 'timber/cache/transient_key', function( $trans_key, $key, $group, $cache_mode ) {
678
         *     return $trans_key . '_my_suffix';
679
         * }, 10, 4 );
680
         * ```
681
         *
682
         * @param string $trans_key The transient key.
683
         * @param string $key The cache key.
684
         * @param string $group The cache group.
685
         * @param string $cache_mode The cache mode.
686
         */
687
        $trans_key = \apply_filters('timber/cache/transient_key', $trans_key, $key, $group, $cache_mode);
20✔
688

689
        if (self::CACHE_TRANSIENT === $cache_mode) {
20✔
690
            $value = \get_transient($trans_key);
15✔
691
        } elseif (self::CACHE_SITE_TRANSIENT === $cache_mode) {
5✔
692
            $value = \get_site_transient($trans_key);
1✔
693
        } elseif (self::CACHE_OBJECT === $cache_mode && $this->is_object_cache()) {
4✔
694
            $value = \wp_cache_get($key, $group);
3✔
695
        }
696

697
        return $value;
20✔
698
    }
699

700
    /**
701
     * @param string $key
702
     * @param string|boolean $value
703
     * @param string $group
704
     * @param integer $expires
705
     * @param string $cache_mode
706
     * @return string|boolean
707
     */
708
    public function set_cache($key, $value, $group = self::CACHEGROUP, $expires = 0, $cache_mode = self::CACHE_USE_DEFAULT)
22✔
709
    {
710
        if ((int) $expires < 1) {
22✔
711
            $expires = 0;
3✔
712
        }
713

714
        $cache_mode = $this->_get_cache_mode($cache_mode);
22✔
715
        $trans_key = \substr($group . '_' . $key, 0, self::TRANS_KEY_LEN);
22✔
716

717
        /**
718
         * Filters the transient key used for caching.
719
         *
720
         * @api
721
         * @since 2.1.0
722
         * @example
723
         * ```
724
         * add_filter( 'timber/cache/transient_key', function( $trans_key, $key, $group, $cache_mode ) {
725
         *     return $trans_key . '_my_suffix';
726
         * }, 10, 4 );
727
         * ```
728
         *
729
         * @param string $trans_key The transient key.
730
         * @param string $key The cache key.
731
         * @param string $group The cache group.
732
         * @param string $cache_mode The cache mode.
733
         */
734
        $trans_key = \apply_filters('timber/cache/transient_key', $trans_key, $key, $group, $cache_mode);
22✔
735

736
        if (self::CACHE_TRANSIENT === $cache_mode) {
22✔
737
            \set_transient($trans_key, $value, $expires);
17✔
738
        } elseif (self::CACHE_SITE_TRANSIENT === $cache_mode) {
5✔
739
            \set_site_transient($trans_key, $value, $expires);
1✔
740
        } elseif (self::CACHE_OBJECT === $cache_mode && $this->is_object_cache()) {
4✔
741
            \wp_cache_set($key, $value, $group, $expires);
3✔
742
        }
743

744
        return $value;
22✔
745
    }
746

747
    /**
748
     * @param string $cache_mode
749
     * @return string
750
     */
751
    private function _get_cache_mode($cache_mode)
25✔
752
    {
753
        if (empty($cache_mode) || self::CACHE_USE_DEFAULT === $cache_mode) {
25✔
754
            $cache_mode = $this->cache_mode;
22✔
755
        }
756

757
        // Fallback if self::$cache_mode did not get a valid value
758
        if (!\in_array($cache_mode, self::$cache_modes)) {
25✔
759
            $cache_mode = self::CACHE_OBJECT;
×
760
        }
761

762
        return $cache_mode;
25✔
763
    }
764

765
    /**
766
     * Checks whether WordPress object cache is activated.
767
     *
768
     * @since 2.0.0
769
     * @return bool
770
     */
771
    protected function is_object_cache()
3✔
772
    {
773
        return isset($GLOBALS['wp_object_cache']) && \is_object($GLOBALS['wp_object_cache']);
3✔
774
    }
775
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc