1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
<?php
namespace Tev\Field;
use Closure;
use Exception;
use Tev\Post\Model\AbstractPost,
Tev\Application\Application,
Tev\Field\Model\NullField;
/**
* Custom field factory.
*
* Used for creating custom field entities.
*/
class Factory
{
/**
* Application instance.
*
* @var \Tev\Application\Application
*/
private $app;
/**
* Registered field type factory functions.
*
* @var \Closure[]
*/
private $registry;
/**
* Constructor.
*
* @param \Tev\Application\Application $app Application instance
* @return void
*/
public function __construct(Application $app)
{
$this->app = $app;
$this->registry = array();
}
/**
* Register a new factory function with the factory.
*
* Can either be field class name or factory callback function. If class
* name, the field data array will be passed to the constructor. If
* callback, the field data array will be passed as the first parameter
* and the application instance will be passed as the second.
*
* For example:
*
* // Class name
*
* $factory->register('text', 'Tev\Field\Model\BasicField');
*
* // Callback
*
* $factory->register('text', function ($data, $app) {
* return new \Tev\Field\Model\BasicField($data);
* });
*
* @param string $type Field type string
* @param string|\Closure $factory Class name or factory function
* @return \Tev\Field\Factory This, for chaining
*/
public function register($type, $factory)
{
$this->registry[$type] = $factory;
return $this;
}
/**
* Check if the given type is registered.
*
* @param string $type Field type string
* @return boolean True if registered false if not
*/
public function registered($type)
{
return isset($this->registry[$type]);
}
/**
* Create a new custom field object.
*
* If the field is not registered, a `\Tev\Field\Model\NullField` will be
* returned.
*
* @param string $field Field name or ID
* @param \Tev\Post\Model\AbstractPost $post Post object field is for
* @return \Tev\Field\Model\AbstractField Field object
*
* @throws \Exception If field type is not registered
*/
public function create($field, AbstractPost $post)
{
$data = get_field_object($field, $post->getId());
return $this->createFromField($data);
}
/**
* Create a new custom field object from an existing set of field data.
*
* If the field is not registered, a `\Tev\Field\Model\NullField` will be
* returned.
*
* @param array $field Field data array
* @param mixed $value If supplied, will be set as the fields value
* @return \Tev\Field\Model\AbstractField Field object
*
* @throws \Exception If field type is not registered
*/
public function createFromField($field, $value = null)
{
if (!is_array($field)) {
return new NullField;
}
if ($value !== null) {
$field['value'] = $value;
}
return $this->resolve($field['type'], $field);
}
/**
* Creata new custom field object that's not in the context of a post
* and doesn't have a loaded value.
*
* @param string $field Field name or ID
* @return \Tev\Field\Model\AbstractField Field object
*
* @throws \Exception If field type is not registered
*/
public function createEmpty($field)
{
return $this->createFromField(get_field_object($field, null, false, false));
}
/**
* Resolve a field object using its type, from the registered factory
* functions.
*
* @param string $type Field type
* @param array $data Field data
* @return \Tev\Field\Model\AbstractField Field object
*
* @throws \Exception If field type is not registered
*/
protected function resolve($type, array $data)
{
if ($this->registered($type)) {
$f = $this->registry[$type];
if ($f instanceof Closure) {
return $f($data, $this->app);
} else {
return new $f($data);
}
} else {
throw new Exception("Field type $type not registered");
}
}
}