| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- <?php
- /**
- * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
- * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
- * @link https://cakephp.org CakePHP(tm) Project
- * @since 3.0.0
- * @license https://opensource.org/licenses/mit-license.php MIT License
- */
- namespace Cake\ORM\Behavior;
- use Cake\Datasource\EntityInterface;
- use Cake\Event\Event;
- use Cake\I18n\Time;
- use Cake\ORM\Behavior;
- use DateTime;
- use UnexpectedValueException;
- class TimestampBehavior extends Behavior
- {
- /**
- * Default config
- *
- * These are merged with user-provided config when the behavior is used.
- *
- * events - an event-name keyed array of which fields to update, and when, for a given event
- * possible values for when a field will be updated are "always", "new" or "existing", to set
- * the field value always, only when a new record or only when an existing record.
- *
- * refreshTimestamp - if true (the default) the timestamp used will be the current time when
- * the code is executed, to set to an explicit date time value - set refreshTimetamp to false
- * and call setTimestamp() on the behavior class before use.
- *
- * @var array
- */
- protected $_defaultConfig = [
- 'implementedFinders' => [],
- 'implementedMethods' => [
- 'timestamp' => 'timestamp',
- 'touch' => 'touch'
- ],
- 'events' => [
- 'Model.beforeSave' => [
- 'created' => 'new',
- 'modified' => 'always'
- ]
- ],
- 'refreshTimestamp' => true
- ];
- /**
- * Current timestamp
- *
- * @var \DateTime
- */
- protected $_ts;
- /**
- * Initialize hook
- *
- * If events are specified - do *not* merge them with existing events,
- * overwrite the events to listen on
- *
- * @param array $config The config for this behavior.
- * @return void
- */
- public function initialize(array $config)
- {
- if (isset($config['events'])) {
- $this->setConfig('events', $config['events'], false);
- }
- }
- /**
- * There is only one event handler, it can be configured to be called for any event
- *
- * @param \Cake\Event\Event $event Event instance.
- * @param \Cake\Datasource\EntityInterface $entity Entity instance.
- * @throws \UnexpectedValueException if a field's when value is misdefined
- * @return bool Returns true irrespective of the behavior logic, the save will not be prevented.
- * @throws \UnexpectedValueException When the value for an event is not 'always', 'new' or 'existing'
- */
- public function handleEvent(Event $event, EntityInterface $entity)
- {
- $eventName = $event->getName();
- $events = $this->_config['events'];
- $new = $entity->isNew() !== false;
- $refresh = $this->_config['refreshTimestamp'];
- foreach ($events[$eventName] as $field => $when) {
- if (!in_array($when, ['always', 'new', 'existing'])) {
- throw new UnexpectedValueException(
- sprintf('When should be one of "always", "new" or "existing". The passed value "%s" is invalid', $when)
- );
- }
- if ($when === 'always' ||
- ($when === 'new' && $new) ||
- ($when === 'existing' && !$new)
- ) {
- $this->_updateField($entity, $field, $refresh);
- }
- }
- return true;
- }
- /**
- * implementedEvents
- *
- * The implemented events of this behavior depend on configuration
- *
- * @return array
- */
- public function implementedEvents()
- {
- return array_fill_keys(array_keys($this->_config['events']), 'handleEvent');
- }
- /**
- * Get or set the timestamp to be used
- *
- * Set the timestamp to the given DateTime object, or if not passed a new DateTime object
- * If an explicit date time is passed, the config option `refreshTimestamp` is
- * automatically set to false.
- *
- * @param \DateTime|null $ts Timestamp
- * @param bool $refreshTimestamp If true timestamp is refreshed.
- * @return \DateTime
- */
- public function timestamp(DateTime $ts = null, $refreshTimestamp = false)
- {
- if ($ts) {
- if ($this->_config['refreshTimestamp']) {
- $this->_config['refreshTimestamp'] = false;
- }
- $this->_ts = new Time($ts);
- } elseif ($this->_ts === null || $refreshTimestamp) {
- $this->_ts = new Time();
- }
- return $this->_ts;
- }
- /**
- * Touch an entity
- *
- * Bumps timestamp fields for an entity. For any fields configured to be updated
- * "always" or "existing", update the timestamp value. This method will overwrite
- * any pre-existing value.
- *
- * @param \Cake\Datasource\EntityInterface $entity Entity instance.
- * @param string $eventName Event name.
- * @return bool true if a field is updated, false if no action performed
- */
- public function touch(EntityInterface $entity, $eventName = 'Model.beforeSave')
- {
- $events = $this->_config['events'];
- if (empty($events[$eventName])) {
- return false;
- }
- $return = false;
- $refresh = $this->_config['refreshTimestamp'];
- foreach ($events[$eventName] as $field => $when) {
- if (in_array($when, ['always', 'existing'])) {
- $return = true;
- $entity->setDirty($field, false);
- $this->_updateField($entity, $field, $refresh);
- }
- }
- return $return;
- }
- /**
- * Update a field, if it hasn't been updated already
- *
- * @param \Cake\Datasource\EntityInterface $entity Entity instance.
- * @param string $field Field name
- * @param bool $refreshTimestamp Whether to refresh timestamp.
- * @return void
- */
- protected function _updateField($entity, $field, $refreshTimestamp)
- {
- if ($entity->isDirty($field)) {
- return;
- }
- $entity->set($field, $this->timestamp(null, $refreshTimestamp));
- }
- }
|