/** * Initializer function called by the constructor unless the constructor `'init'` flag is set * to `false`. * * @see lithium\core\Object * @throws ConfigException */ public function _init() { parent::_init(); if (!($model = $this->_model)) { throw new ConfigException("`'model'` option needs to be defined."); } $behavior = $this; $model::applyFilter('save', function ($self, $params, $chain) use($behavior) { if ($behavior->invokeMethod('_beforeSave', [$params])) { return $chain->next($self, $params, $chain); } }); $model::applyFilter('delete', function ($self, $params, $chain) use($behavior) { if ($behavior->invokeMethod('_beforeDelete', [$params])) { return $chain->next($self, $params, $chain); } }); }
/** * @todo We may also need to filter `remove()`. */ protected function _init() { parent::_init(); if (PHP_SAPI === 'cli') { return true; } if ($model = $this->_model) { $behavior = $this; $model::applyFilter('save', function ($self, $params, $chain) use($behavior) { $options = ['placeholders' => []]; $configs = $behavior->_config; $fields = $behavior::_formattedFields($configs['fields']); $source = $destination = $configName = []; $data = $behavior::_modified($params['data'], $fields); $dataKeys = array_keys($data); if (empty($dataKeys)) { return $chain->next($self, $params, $chain); } $queried = $params['entity']->export()['data']; if (0 === count(array_intersect_key($queried, $fields))) { return $chain->next($self, $params, $chain); } $params['data'] = []; $params['entity']->set($data); $entity = $params['entity']; $entityData['model'] = $entity->model(); $entityData['data'] = $entity->data(); if (!isset($configs['placeholders'])) { $configs['placeholders'] = []; } $defaults = ['save' => null, 'remove' => null]; $skip = []; $fieldCount = 0; foreach ($fields as $field => $name) { if (array_key_exists($field, $data)) { $configName[$field] = $name; $source[$field] = $_FILES[$field]['tmp_name']; $settings = UploadableStorage::config($name); $settings += $defaults; $path = $settings['save']; $newFile = $_FILES[$field]['name']; if ($entity->exists()) { if (!$entity->modified($field)) { $skip[$field] = true; } else { // We delete the old file $oldFile = $entity->export()['data'][$field]; $removeOptions['placeholders'] = UploadableStorage::placeholders($oldFile, $configs['placeholders'] + ['field' => $field], $entityData); $removePath = UploadableStorage::interpolate($settings['remove'], $removeOptions); UploadableStorage::remove($removePath, $removeOptions + ['name' => $name]); if (null === $data[$field]) { $skip[$field] = true; continue; } $options['placeholders'] = UploadableStorage::placeholders($newFile, $configs['placeholders'] + ['field' => $field], $entityData); $destination[$field] = UploadableStorage::interpolate($path, $options); /** * The field has been modified to now contain 'null' so we * remove the field from the config so that, later on, we don't * try to upload a non-existent file later. */ if (null === $entity->{$field}) { $params['entity']->{$field} = null; unset($configs['fields'][$field]); } else { /** * the field has been modified but it contains a value * so we must upload the new one. */ $fieldValue = static::fieldValue($path, $options['placeholders']); $params['entity']->{$field} = $fieldValue; } } } else { $options['placeholders'] = UploadableStorage::placeholders($newFile, $configs['placeholders'] + ['field' => $field], $entityData); $fieldValue = static::fieldValue($path, $options['placeholders']); $destination[$field] = UploadableStorage::interpolate($path, $options); $params['entity']->{$field} = $fieldValue; } } else { $fieldCount++; } } if (!$params['entity']->validates()) { return false; } $saved = $chain->next($self, $params, $chain); if ($fieldCount == count($fields)) { return $saved; } $options['placeholders'] += $params['entity']->data(); $uploaded = []; foreach ($fields as $field => $name) { if (!isset($skip[$field]) || $skip[$field] !== true) { $options['name'] = $configName[$field]; $uploaded[] = UploadableStorage::save($source[$field], $destination[$field], $options); } } return $saved && !in_array(false, $uploaded, true); }); $model::applyFilter('find', function ($self, $params, $chain) use($behavior) { $data = $chain->next($self, $params, $chain); switch ($params['type']) { case 'first': $entity = $behavior->invokeMethod('_assignAccessors', [$data]); return $entity; break; case 'all': foreach ($data as $datum) { $entity = $behavior->invokeMethod('_assignAccessors', [$datum]); } return $data; break; default: return $data; break; } }); $model::applyFilter('delete', function ($self, $params, $chain) use($behavior) { $entity = $params['entity']; $entityData['model'] = $entity->model(); $entityData['data'] = $entity->data(); $configs = $behavior->_config; $fields = $behavior::_formattedFields($configs['fields']); if (!isset($configs['placeholders'])) { $configs['placeholders'] = []; } $results = []; foreach ($fields as $field => $name) { $path = UploadableStorage::config($name)['remove']; $existingFile = $entity->export()['data'][$field]; $options['placeholders'] = UploadableStorage::placeholders($existingFile, $configs['placeholders'] + ['field' => $field], $entityData); $destination = UploadableStorage::interpolate($path, $options); $results[] = UploadableStorage::remove($destination, $options + ['name' => $name]); } $deleted = $chain->next($self, $params, $chain); return $deleted && !in_array(false, $results, true); }); } }