silverstripe-framework/src/Core/Extension.php

119 lines
3.0 KiB
PHP

<?php
namespace SilverStripe\Core;
use BadMethodCallException;
use SilverStripe\ORM\DataObject;
/**
* Add extension that can be added to an object with {@link Object::add_extension()}.
* For {@link DataObject} extensions, use {@link DataExtension}.
* Each extension instance has an "owner" instance, accessible through
* {@link getOwner()}.
* Every object instance gets its own set of extension instances,
* meaning you can set parameters specific to the "owner instance"
* in new Extension instances.
*/
abstract class Extension
{
/**
* This is used by extensions designed to be applied to controllers.
* It works the same way as {@link Controller::$allowed_actions}.
*/
private static $allowed_actions = [];
/**
* The object this extension is applied to.
*
* @var Object
*/
protected $owner;
/**
* Stack of all parent owners, not including current owner
*
* @var array
*/
private $ownerStack = [];
public function __construct()
{
}
/**
* Called when this extension is added to a particular class
*
* @param string $class
* @param string $extensionClass
* @param mixed $args
*/
public static function add_to_class($class, $extensionClass, $args = null)
{
// NOP
}
/**
* Set the owner of this extension.
*
* @param object $owner The owner object
*/
public function setOwner($owner)
{
$this->ownerStack[] = $this->owner;
$this->owner = $owner;
}
/**
* Temporarily modify the owner. The original owner is ensured to be restored
*
* @param mixed $owner Owner to set
* @param callable $callback Callback to invoke
* @param array $args Args to pass to callback
* @return mixed
*/
public function withOwner($owner, callable $callback, $args = [])
{
try {
$this->setOwner($owner);
return $callback(...$args);
} finally {
$this->clearOwner();
}
}
/**
* Clear the current owner, and restore extension to the state prior to the last setOwner()
*/
public function clearOwner()
{
if (empty($this->ownerStack)) {
throw new BadMethodCallException("clearOwner() called more than setOwner()");
}
$this->owner = array_pop($this->ownerStack);
}
/**
* Returns the owner of this extension.
*
* @return Object
*/
public function getOwner()
{
return $this->owner;
}
/**
* Helper method to strip eval'ed arguments from a string
* that's passed to {@link DataObject::$extensions} or
* {@link Object::add_extension()}.
*
* @param string $extensionStr E.g. "Versioned('Stage','Live')"
* @return string Extension classname, e.g. "Versioned"
*/
public static function get_classname_without_arguments($extensionStr)
{
// Split out both args and service name
return strtok(strtok($extensionStr ?? '', '(') ?? '', '.');
}
}