julienmonnerie/kirby/src/Cms/Collections.php

136 lines
3 KiB
PHP
Raw Normal View History

2022-06-17 17:51:59 +02:00
<?php
namespace Kirby\Cms;
2022-12-19 14:56:05 +01:00
use Closure;
2022-06-17 17:51:59 +02:00
use Kirby\Exception\NotFoundException;
use Kirby\Filesystem\F;
use Kirby\Toolkit\Controller;
/**
* Manages and loads all collections
* in site/collections, which can then
* be reused in controllers, templates, etc
*
* This class is mainly used in the `$kirby->collection()`
* method to provide easy access to registered collections
*
* @package Kirby Cms
* @author Bastian Allgeier <bastian@getkirby.com>
* @link https://getkirby.com
* @copyright Bastian Allgeier
* @license https://getkirby.com/license
*/
class Collections
{
2022-08-31 15:02:43 +02:00
/**
* Each collection is cached once it
* has been called, to avoid further
* processing on sequential calls to
* the same collection.
*/
2024-12-20 12:37:52 +01:00
protected array $cache = [];
2022-08-31 15:02:43 +02:00
/**
* Store of all collections
*/
2024-12-20 12:37:52 +01:00
protected array $collections = [];
2022-08-31 15:02:43 +02:00
/**
* Magic caller to enable something like
* `$collections->myCollection()`
*
2024-12-20 12:37:52 +01:00
* @return \Kirby\Toolkit\Collection|null
* @todo 5.0 Add return type declaration
2022-08-31 15:02:43 +02:00
*/
public function __call(string $name, array $arguments = [])
{
return $this->get($name, ...$arguments);
}
/**
* Loads a collection by name if registered
*
2024-12-20 12:37:52 +01:00
* @return \Kirby\Toolkit\Collection|null
* @todo 4.0 Add deprecation warning when anything else than a Collection is returned
* @todo 5.0 Add return type declaration
2022-08-31 15:02:43 +02:00
*/
public function get(string $name, array $data = [])
{
// if not yet loaded
2022-12-19 14:56:05 +01:00
$this->collections[$name] ??= $this->load($name);
2022-08-31 15:02:43 +02:00
// if not yet cached
if (
isset($this->cache[$name]) === false ||
$this->cache[$name]['data'] !== $data
) {
$controller = new Controller($this->collections[$name]);
$this->cache[$name] = [
'result' => $controller->call(null, $data),
'data' => $data
];
}
// return cloned object
if (is_object($this->cache[$name]['result']) === true) {
return clone $this->cache[$name]['result'];
}
return $this->cache[$name]['result'];
}
/**
* Checks if a collection exists
*
* @param string $name
* @return bool
*/
public function has(string $name): bool
{
if (isset($this->collections[$name]) === true) {
return true;
}
try {
$this->load($name);
return true;
2022-12-19 14:56:05 +01:00
} catch (NotFoundException) {
2022-08-31 15:02:43 +02:00
return false;
}
}
/**
* Loads collection from php file in a
* given directory or from plugin extension.
*
* @param string $name
* @return mixed
* @throws \Kirby\Exception\NotFoundException
*/
public function load(string $name)
{
$kirby = App::instance();
// first check for collection file
$file = $kirby->root('collections') . '/' . $name . '.php';
if (is_file($file) === true) {
2022-12-19 14:56:05 +01:00
$collection = F::load($file, allowOutput: false);
2022-08-31 15:02:43 +02:00
2022-12-19 14:56:05 +01:00
if ($collection instanceof Closure) {
2022-08-31 15:02:43 +02:00
return $collection;
}
}
// fallback to collections from plugins
$collections = $kirby->extensions('collections');
if (isset($collections[$name]) === true) {
return $collections[$name];
}
throw new NotFoundException('The collection cannot be found');
}
2022-06-17 17:51:59 +02:00
}