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

timber / timber / 20740336611

06 Jan 2026 06:35AM UTC coverage: 89.608% (-0.06%) from 89.667%
20740336611

push

travis-ci

nlemoine
chore(deps): bump actions/checkout from 4 to 6

Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

4596 of 5129 relevant lines covered (89.61%)

63.72 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\Loader\FilesystemLoader;
10
use Twig\TwigFunction;
11

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

16
    public const TRANS_KEY_LEN = 50;
17

18
    public const CACHE_NONE = 'none';
19

20
    public const CACHE_OBJECT = 'cache';
21

22
    public const CACHE_TRANSIENT = 'transient';
23

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

26
    public const CACHE_USE_DEFAULT = 'default';
27

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

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

38
    protected $cache_mode = self::CACHE_TRANSIENT;
39

40
    protected $locations;
41

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

219
        return $output;
80✔
220
    }
221

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

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

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

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

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

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

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

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

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

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

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

318
        return $fs;
419✔
319
    }
320

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

525
        return $twig;
415✔
526
    }
527

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

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

546
        return false;
×
547
    }
548

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

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

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

572
        $result = true;
1✔
573

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

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

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

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

592
        return $result;
1✔
593
    }
594

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

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

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

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

612
        return false;
×
613
    }
614

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

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

654
        return $cache_extension;
×
655
    }
656

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

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

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

696
        return $value;
20✔
697
    }
698

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

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

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

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

743
        return $value;
22✔
744
    }
745

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

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

761
        return $cache_mode;
25✔
762
    }
763

764
    /**
765
     * Checks whether WordPress object cache is activated.
766
     *
767
     * @since 2.0.0
768
     * @return bool
769
     */
770
    protected function is_object_cache()
3✔
771
    {
772
        return isset($GLOBALS['wp_object_cache']) && \is_object($GLOBALS['wp_object_cache']);
3✔
773
    }
774
}
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