|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Charcoal\Object; |
|
4
|
|
|
|
|
5
|
|
|
use InvalidArgumentException; |
|
6
|
|
|
|
|
7
|
|
|
// From Pimple |
|
8
|
|
|
use Pimple\Container; |
|
9
|
|
|
|
|
10
|
|
|
// From 'charcoal-factory' |
|
11
|
|
|
use Charcoal\Factory\FactoryInterface; |
|
12
|
|
|
|
|
13
|
|
|
// From 'charcoal-core' |
|
14
|
|
|
use Charcoal\Model\AbstractModel; |
|
15
|
|
|
|
|
16
|
|
|
// From `charcoal-translation` |
|
17
|
|
|
use Charcoal\Translator\TranslatorAwareTrait; |
|
18
|
|
|
|
|
19
|
|
|
// From `charcoal-object` |
|
20
|
|
|
use Charcoal\Object\ContentInterface; |
|
21
|
|
|
use Charcoal\Object\AuthorableInterface; |
|
22
|
|
|
use Charcoal\Object\AuthorableTrait; |
|
23
|
|
|
use Charcoal\Object\RevisionableInterface; |
|
24
|
|
|
use Charcoal\Object\RevisionableTrait; |
|
25
|
|
|
use Charcoal\Object\TimestampableInterface; |
|
26
|
|
|
use Charcoal\Object\TimestampableTrait; |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* |
|
30
|
|
|
*/ |
|
31
|
|
|
class Content extends AbstractModel implements |
|
32
|
|
|
AuthorableInterface, |
|
33
|
|
|
ContentInterface, |
|
34
|
|
|
RevisionableInterface, |
|
35
|
|
|
TimestampableInterface |
|
36
|
|
|
{ |
|
37
|
|
|
use AuthorableTrait; |
|
38
|
|
|
use RevisionableTrait; |
|
39
|
|
|
use TranslatorAwareTrait; |
|
40
|
|
|
use TimestampableTrait; |
|
41
|
|
|
|
|
42
|
|
|
/** |
|
43
|
|
|
* Objects are active by default |
|
44
|
|
|
* @var boolean |
|
45
|
|
|
*/ |
|
46
|
|
|
private $active = true; |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* The position is used for ordering lists |
|
50
|
|
|
* @var integer |
|
51
|
|
|
*/ |
|
52
|
|
|
private $position = 0; |
|
53
|
|
|
|
|
54
|
|
|
|
|
55
|
|
|
/** |
|
56
|
|
|
* @var FactoryInterface |
|
57
|
|
|
*/ |
|
58
|
|
|
private $modelFactory; |
|
59
|
|
|
|
|
60
|
|
|
/** |
|
61
|
|
|
* @var string[] |
|
62
|
|
|
*/ |
|
63
|
|
|
private $requiredAclPermissions = []; |
|
64
|
|
|
|
|
65
|
|
|
/** |
|
66
|
|
|
* Dependencies |
|
67
|
|
|
* @param Container $container DI Container. |
|
68
|
|
|
* @return void |
|
69
|
|
|
*/ |
|
70
|
|
|
public function setDependencies(Container $container) |
|
71
|
|
|
{ |
|
72
|
|
|
parent::setDependencies($container); |
|
73
|
|
|
|
|
74
|
|
|
$this->setTranslator($container['translator']); |
|
75
|
|
|
$this->setModelFactory($container['model/factory']); |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
|
|
/** |
|
79
|
|
|
* @param FactoryInterface $factory The factory used to create models. |
|
80
|
|
|
* @return Content Chainable |
|
81
|
|
|
*/ |
|
82
|
|
|
protected function setModelFactory(FactoryInterface $factory) |
|
83
|
|
|
{ |
|
84
|
|
|
$this->modelFactory = $factory; |
|
85
|
|
|
return $this; |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
/** |
|
89
|
|
|
* @return FactoryInterface The model factory. |
|
90
|
|
|
*/ |
|
91
|
|
|
protected function modelFactory() |
|
92
|
|
|
{ |
|
93
|
|
|
return $this->modelFactory; |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
/** |
|
97
|
|
|
* @param boolean $active The active flag. |
|
98
|
|
|
* @return Content Chainable |
|
99
|
|
|
*/ |
|
100
|
|
|
public function setActive($active) |
|
101
|
|
|
{ |
|
102
|
|
|
$this->active = !!$active; |
|
103
|
|
|
return $this; |
|
104
|
|
|
} |
|
105
|
|
|
|
|
106
|
|
|
/** |
|
107
|
|
|
* @return boolean |
|
108
|
|
|
*/ |
|
109
|
|
|
public function active() |
|
110
|
|
|
{ |
|
111
|
|
|
return $this->active; |
|
112
|
|
|
} |
|
113
|
|
|
|
|
114
|
|
|
/** |
|
115
|
|
|
* @param integer $position The position (for ordering purpose). |
|
116
|
|
|
* @throws InvalidArgumentException If the position is not an integer (or numeric integer string). |
|
117
|
|
|
* @return Content Chainable |
|
118
|
|
|
*/ |
|
119
|
|
|
public function setPosition($position) |
|
120
|
|
|
{ |
|
121
|
|
|
if ($position === null) { |
|
122
|
|
|
$this->position = null; |
|
123
|
|
|
return $this; |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
|
if (!is_numeric($position)) { |
|
127
|
|
|
throw new InvalidArgumentException(sprintf( |
|
128
|
|
|
'Position must be an integer, received %s', |
|
129
|
|
|
is_object($position) ? get_class($position) : gettype($position) |
|
130
|
|
|
)); |
|
131
|
|
|
} |
|
132
|
|
|
|
|
133
|
|
|
$this->position = (int)$position; |
|
134
|
|
|
return $this; |
|
135
|
|
|
} |
|
136
|
|
|
|
|
137
|
|
|
/** |
|
138
|
|
|
* @return integer |
|
139
|
|
|
*/ |
|
140
|
|
|
public function position() |
|
141
|
|
|
{ |
|
142
|
|
|
return $this->position; |
|
143
|
|
|
} |
|
144
|
|
|
|
|
145
|
|
|
|
|
146
|
|
|
/** |
|
147
|
|
|
* @throws InvalidArgumentException If the ACL permissions are invalid. |
|
148
|
|
|
* @param string|string[] $permissions The required ACL permissions. |
|
149
|
|
|
* @return Content Chainable |
|
150
|
|
|
*/ |
|
151
|
|
|
public function setRequiredAclPermissions($permissions) |
|
152
|
|
|
{ |
|
153
|
|
|
if ($permissions === null || !$permissions) { |
|
154
|
|
|
$this->permissions = []; |
|
|
|
|
|
|
155
|
|
|
return $this; |
|
156
|
|
|
} |
|
157
|
|
|
if (is_string($permissions)) { |
|
158
|
|
|
$permissions = explode(',', $permissions); |
|
159
|
|
|
$permissions = array_map('trim', $permissions); |
|
160
|
|
|
} |
|
161
|
|
|
if (!is_array($permissions)) { |
|
162
|
|
|
throw new InvalidArgumentException( |
|
163
|
|
|
sprintf('Invalid ACL permissions. Permissions need to be an array (%s given)', gettype($permissions)) |
|
164
|
|
|
); |
|
165
|
|
|
} |
|
166
|
|
|
$this->requiredAclPermissions = $permissions; |
|
167
|
|
|
return $this; |
|
168
|
|
|
} |
|
169
|
|
|
|
|
170
|
|
|
/** |
|
171
|
|
|
* @return string[] |
|
172
|
|
|
*/ |
|
173
|
|
|
public function requiredAclPermissions() |
|
174
|
|
|
{ |
|
175
|
|
|
return $this->requiredAclPermissions; |
|
176
|
|
|
} |
|
177
|
|
|
|
|
178
|
|
|
/** |
|
179
|
|
|
* StorableTrait > preSave(): Called automatically before saving the object to source. |
|
180
|
|
|
* For content object, set the `created` and `lastModified` properties automatically |
|
181
|
|
|
* @return boolean |
|
182
|
|
|
*/ |
|
183
|
|
|
public function preSave() |
|
184
|
|
|
{ |
|
185
|
|
|
parent::preSave(); |
|
186
|
|
|
|
|
187
|
|
|
// Timestampable properties |
|
188
|
|
|
$this->setCreated('now'); |
|
189
|
|
|
$this->setLastModified('now'); |
|
190
|
|
|
|
|
191
|
|
|
return true; |
|
192
|
|
|
} |
|
193
|
|
|
|
|
194
|
|
|
/** |
|
195
|
|
|
* StorableTrait > preUpdate(): Called automatically before updating the object to source. |
|
196
|
|
|
* For content object, set the `lastModified` property automatically. |
|
197
|
|
|
* |
|
198
|
|
|
* @param array $properties The properties (ident) set for update. |
|
199
|
|
|
* @return boolean |
|
200
|
|
|
*/ |
|
201
|
|
|
public function preUpdate(array $properties = null) |
|
202
|
|
|
{ |
|
203
|
|
|
parent::preUpdate($properties); |
|
|
|
|
|
|
204
|
|
|
|
|
205
|
|
|
// Content is revisionable |
|
206
|
|
|
if ($this->revisionEnabled()) { |
|
207
|
|
|
$this->generateRevision(); |
|
208
|
|
|
} |
|
209
|
|
|
|
|
210
|
|
|
// Timestampable propertiees |
|
211
|
|
|
$this->setLastModified('now'); |
|
212
|
|
|
|
|
213
|
|
|
return true; |
|
214
|
|
|
} |
|
215
|
|
|
} |
|
216
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.