Overview

Namespaces

  • Charcoal
    • Object
    • User
      • Acl

Classes

  • Charcoal\Object\Content
  • Charcoal\Object\ObjectRevision
  • Charcoal\Object\ObjectRoute
  • Charcoal\Object\ObjectSchedule
  • Charcoal\Object\UserData
  • Charcoal\User\AbstractUser
  • Charcoal\User\Acl\Manager
  • Charcoal\User\Acl\Permission
  • Charcoal\User\Acl\PermissionCategory
  • Charcoal\User\Acl\Role
  • Charcoal\User\Authenticator
  • Charcoal\User\Authorizer
  • Charcoal\User\AuthToken
  • Charcoal\User\AuthTokenMetadata
  • Charcoal\User\GenericUser

Interfaces

  • Charcoal\Object\ArchivableInterface
  • Charcoal\Object\CategorizableInterface
  • Charcoal\Object\CategorizableMultipleInterface
  • Charcoal\Object\CategoryInterface
  • Charcoal\Object\ContentInterface
  • Charcoal\Object\HierarchicalInterface
  • Charcoal\Object\ObjectRevisionInterface
  • Charcoal\Object\ObjectRouteInterface
  • Charcoal\Object\ObjectScheduleInterface
  • Charcoal\Object\PublishableInterface
  • Charcoal\Object\RevisionableInterface
  • Charcoal\Object\RoutableInterface
  • Charcoal\Object\UserDataInterface
  • Charcoal\User\UserInterface

Traits

  • Charcoal\Object\ArchivableTrait
  • Charcoal\Object\CategorizableMultipleTrait
  • Charcoal\Object\CategorizableTrait
  • Charcoal\Object\CategoryTrait
  • Charcoal\Object\HierarchicalTrait
  • Charcoal\Object\PublishableTrait
  • Charcoal\Object\RevisionableTrait
  • Charcoal\Object\RoutableTrait
  • Overview
  • Namespace
  • Class
  1: <?php
  2: 
  3: namespace Charcoal\Object;
  4: 
  5: // Dependencies from `PHP`
  6: use \DateTime;
  7: use \DateTimeInterface;
  8: use \Exception;
  9: use \RuntimeException;
 10: use \InvalidArgumentException;
 11: 
 12: // Dependency from 'charcoal-factory'
 13: use \Charcoal\Factory\FactoryInterface;
 14: 
 15: // Dependency from 'charcoal-core'
 16: use \Charcoal\Model\AbstractModel;
 17: 
 18: // Local namespace dependencies
 19: use \Charcoal\Object\ObjectScheduleInterface;
 20: 
 21: /**
 22:  * The object schedule class allows object properties to be changed at a scheduled time.
 23:  *
 24:  * ## Required Services
 25:  *
 26:  * - "model/factory" — {@see \Charcoal\Model\ModelFactory}
 27:  */
 28: class ObjectSchedule extends AbstractModel implements ObjectScheduleInterface
 29: {
 30:     /**
 31:      * Store the factory instance for the current class.
 32:      *
 33:      * @var FactoryInterface
 34:      */
 35:     private $modelFactory;
 36: 
 37:     /**
 38:      * The object type of the scheduled object (required).
 39:      *
 40:      * @var string
 41:      */
 42:     private $targetType;
 43: 
 44:     /**
 45:      * The object ID of the scheduled object (required).
 46:      *
 47:      * @var mixed
 48:      */
 49:     private $targetId;
 50: 
 51:     /**
 52:      * When the item should be processed.
 53:      *
 54:      * The date/time at which this queue item job should be ran.
 55:      * If NULL, 0, or a past date/time, then it should be performed immediately.
 56:      *
 57:      * @var DateTimeInterface $scheduledDate
 58:      */
 59:     private $scheduledDate;
 60: 
 61:     /**
 62:      * The property identifier of the scheduled object (required).
 63:      *
 64:      * @var string
 65:      */
 66:     private $dataDiff = [];
 67: 
 68:     /**
 69:      * Whether the item has been processed.
 70:      *
 71:      * @var boolean $processed
 72:      */
 73:     private $processed = false;
 74: 
 75:     /**
 76:      * When the item was processed.
 77:      *
 78:      * @var DateTimeInterface $processedDate
 79:      */
 80:     private $processedDate;
 81: 
 82:     /**
 83:      * Set an object model factory.
 84:      *
 85:      * @param FactoryInterface $factory The model factory, to create objects.
 86:      * @return ObjectContainerInterface Chainable
 87:      */
 88:     public function setModelFactory(FactoryInterface $factory)
 89:     {
 90:         $this->modelFactory = $factory;
 91: 
 92:         return $this;
 93:     }
 94: 
 95:     /**
 96:      * Retrieve the object model factory.
 97:      *
 98:      * @throws RuntimeException If the model factory was not previously set.
 99:      * @return FactoryInterface
100:      */
101:     protected function modelFactory()
102:     {
103:         if (!isset($this->modelFactory)) {
104:             throw new RuntimeException(
105:                 sprintf('Model Factory is not defined for "%s"', get_class($this))
106:             );
107:         }
108: 
109:         return $this->modelFactory;
110:     }
111: 
112:     /**
113:      * Set the scheduled object's type.
114:      *
115:      * @param string $targetType The object type (model).
116:      * @throws InvalidArgumentException If the object type parameter is not a string.
117:      * @return ObjectScheduleInterface Chainable
118:      */
119:     public function setTargetType($targetType)
120:     {
121:         if (!is_string($targetType)) {
122:             throw new InvalidArgumentException(
123:                 'Scheduled object type must be a string.'
124:             );
125:         }
126: 
127:         $this->targetType = $targetType;
128: 
129:         return $this;
130:     }
131: 
132:     /**
133:      * Retrieve the scheduled object's type.
134:      *
135:      * @return string
136:      */
137:     public function targetType()
138:     {
139:         return $this->targetType;
140:     }
141: 
142:     /**
143:      * Set the scheduled object's ID.
144:      *
145:      * @param mixed $targetId The object ID.
146:      * @return ObjectScheduleInterface Chainable
147:      */
148:     public function setTargetId($targetId)
149:     {
150:         $this->targetId = $targetId;
151: 
152:         return $this;
153:     }
154: 
155:     /**
156:      * Retrieve the scheduled object's ID.
157:      *
158:      * @return mixed
159:      */
160:     public function targetId()
161:     {
162:         return $this->targetId;
163:     }
164: 
165:     /**
166:      * @param array|string $data The data diff.
167:      * @return ObjectRevision
168:      */
169:     public function setDataDiff($data)
170:     {
171:         if (!is_array($data)) {
172:             $data = json_decode($data, true);
173:         }
174:         if ($data === null) {
175:             $data = [];
176:         }
177:         $this->dataDiff = $data;
178:         return $this;
179:     }
180: 
181:     /**
182:      * @return array
183:      */
184:     public function dataDiff()
185:     {
186:         return $this->dataDiff;
187:     }
188: 
189:     /**
190:      * Set the schedule's processed status.
191:      *
192:      * @param boolean $processed Whether the schedule has been processed.
193:      * @return ObjectScheduleInterface Chainable
194:      */
195:     public function setProcessed($processed)
196:     {
197:         $this->processed = !!$processed;
198: 
199:         return $this;
200:     }
201: 
202:     /**
203:      * Determine if the schedule has been processed.
204:      *
205:      * @return boolean
206:      */
207:     public function processed()
208:     {
209:         return $this->processed;
210:     }
211: 
212:     /**
213:      * Set the date/time the item should be processed at.
214:      *
215:      * @param  null|string|DateTimeInterface $ts A date/time string or object.
216:      * @throws InvalidArgumentException If the date/time is invalid.
217:      * @return QueueItemInterface Chainable
218:      */
219:     public function setScheduledDate($ts)
220:     {
221:         if ($ts === null) {
222:             $this->scheduledDate = null;
223:             return $this;
224:         }
225: 
226:         if (is_string($ts)) {
227:             try {
228:                 $ts = new DateTime($ts);
229:             } catch (Exception $e) {
230:                 throw new InvalidArgumentException(
231:                     sprintf('%s (%s)', $e->getMessage(), $ts)
232:                 );
233:             }
234:         }
235: 
236:         if (!($ts instanceof DateTimeInterface)) {
237:             throw new InvalidArgumentException(
238:                 'Invalid "Processing Date" value. Must be a date/time string or a DateTime object.'
239:             );
240:         }
241: 
242:         $this->scheduledDate = $ts;
243: 
244:         return $this;
245:     }
246: 
247:     /**
248:      * Retrieve the date/time the item should be processed at.
249:      *
250:      * @return null|DateTimeInterface
251:      */
252:     public function scheduledDate()
253:     {
254:         return $this->scheduledDate;
255:     }
256: 
257:     /**
258:      * Set the date/time the item was processed at.
259:      *
260:      * @param  null|string|DateTimeInterface $ts A date/time string or object.
261:      * @throws InvalidArgumentException If the date/time is invalid.
262:      * @return QueueItemInterface Chainable
263:      */
264:     public function setProcessedDate($ts)
265:     {
266:         if ($ts === null) {
267:             $this->processedDate = null;
268:             return $this;
269:         }
270: 
271:         if (is_string($ts)) {
272:             try {
273:                 $ts = new DateTime($ts);
274:             } catch (Exception $e) {
275:                 throw new InvalidArgumentException(
276:                     sprintf('%s (%s)', $e->getMessage(), $ts)
277:                 );
278:             }
279:         }
280: 
281:         if (!($ts instanceof DateTimeInterface)) {
282:             throw new InvalidArgumentException(
283:                 'Invalid "Processed Date" value. Must be a date/time string or a DateTime object.'
284:             );
285:         }
286: 
287:         $this->processedDate = $ts;
288: 
289:         return $this;
290:     }
291: 
292:     /**
293:      * Retrieve the date/time the item was processed at.
294:      *
295:      * @return null|DateTimeInterface
296:      */
297:     public function processedDate()
298:     {
299:         return $this->processedDate;
300:     }
301: 
302:     /**
303:      * Hook called before saving the item.
304:      *
305:      * Presets the item as _to-be_ processed and queued now.
306:      *
307:      * @return QueueItemInterface Chainable
308:      */
309:     public function preSave()
310:     {
311:         parent::preSave();
312: 
313:         $this->setProcessed(false);
314: 
315:         return true;
316:     }
317: 
318:     /**
319:      * Process the item.
320:      *
321:      * @param  callable $callback        An optional callback routine executed after the item is processed.
322:      * @param  callable $successCallback An optional callback routine executed when the item is resolved.
323:      * @param  callable $failureCallback An optional callback routine executed when the item is rejected.
324:      * @return boolean  Success / Failure
325:      */
326:     public function process(
327:         callable $callback = null,
328:         callable $successCallback = null,
329:         callable $failureCallback = null
330:     ) {
331: 
332:         if ($this->processed() === true) {
333:             // Do not process twice, ever.
334:             return null;
335:         }
336: 
337:         if ($this->targetType() === null) {
338:             $this->logger->error('Can not process object schedule: no object type defined.');
339:             return false;
340:         }
341: 
342:         if ($this->targetId() === null) {
343:             $this->logger->error(
344:                 sprintf('Can not process object schedule: no object "%s" ID defined.', $this->targetType())
345:             );
346:             return false;
347:         }
348: 
349:         if (empty($this->dataDiff())) {
350:             $this->logger->error('Can not process object schedule: no changes (diff) defined.');
351:             return false;
352:         }
353: 
354:         $obj = $this->modelFactory()->create($this->targetType());
355:         $obj->load($this->targetId());
356:         if (!$obj->id()) {
357:             $this->logger->error(sprintf('Can not load "%s" object %id', $this->targetType(), $this->targetId()));
358:         }
359:         $obj->setData($this->dataDiff());
360:         $update = $obj->update(array_keys($this->dataDiff()));
361: 
362:         if ($update) {
363:             $this->setProcessed(true);
364:             $this->setProcessedDate('now');
365:             $this->update(['processed', 'processed_date']);
366: 
367:             if ($successCallback !== null) {
368:                 $successCallback($this);
369:             }
370:         } else {
371:             if ($failureCallback !== null) {
372:                 $failureCallback($this);
373:             }
374:         }
375: 
376:         if ($callback !== null) {
377:             $callback($this);
378:         }
379: 
380:         return $update;
381:     }
382: }
383: 
API documentation generated by ApiGen