/** * Method that renders Entity values through Field Handler Factory. * * @param Cake\ORM\Entity $entity Entity instance * @param Cake\ORM\Table|string $table Table instance * @param array $fields Fields to prettify * @return void */ protected function _prettify(Entity $entity, $table, array $fields = []) { if (!$this->__fhf instanceof FieldHandlerFactory) { $this->__fhf = new FieldHandlerFactory(); } if (empty($fields)) { $fields = array_keys($entity->toArray()); } foreach ($fields as $field) { // handle belongsTo associated data if ($entity->{$field} instanceof Entity) { $tableName = $table->association($entity->{$field}->source())->className(); $this->_prettify($entity->{$field}, $tableName); } // handle hasMany associated data if (is_array($entity->{$field})) { if (empty($entity->{$field})) { continue; } foreach ($entity->{$field} as $associatedEntity) { if (!$associatedEntity instanceof Entity) { continue; } $tableName = $table->association($associatedEntity->source())->className(); $this->_prettify($associatedEntity, $tableName); } } $renderOptions = ['entity' => $entity]; $entity->{$field} = $this->__fhf->renderValue($table instanceof Table ? $table->registryAlias() : $table, $field, $entity->{$field}, $renderOptions); } }
/** * Get related model's properties. * * @param mixed $table related table instance or name * @param sting $data query parameter value * @return mixed */ protected function _getRelatedProperties($table, $data) { if (!is_object($table)) { $tableName = $table; $table = TableRegistry::get($tableName); } else { $tableName = $table->registryAlias(); } $result['id'] = $data; if (method_exists($table, 'getConfig') && is_callable([$table, 'getConfig'])) { $result['config'] = $table->getConfig(); } // display field $result['displayField'] = $table->displayField(); // get associated entity record $result['entity'] = $this->_getAssociatedRecord($table, $data); // get related table's displayField value if (!empty($result['entity'])) { // Pass the value through related field handler // to properly display the user-friendly label. $fhf = new FieldHandlerFactory($this->cakeView); $result['dispFieldVal'] = $fhf->renderValue($table, $table->displayField(), $result['entity']->{$table->displayField()}, ['renderAs' => RelatedFieldHandler::RENDER_PLAIN_VALUE]); } else { $result['dispFieldVal'] = null; } // get plugin and controller names list($result['plugin'], $result['controller']) = pluginSplit($tableName); return $result; }
public function testHasFieldHandler() { $result = $this->fhf->hasFieldHandler('string'); $this->assertTrue($result, "Failed to find field handler for type 'string'"); $result = $this->fhf->hasFieldHandler('non-existing-field-type'); $this->assertFalse($result, "Found field handler for type 'non-existing-field-type'"); }
/** * Check if the field type is valid * * Migration field type needs a field handler. * * @param string $type Field type * @return bool True if valid, false otherwise */ protected function _isValidFieldType($type) { $result = false; $fhf = new FieldHandlerFactory(); if ($fhf->hasFieldHandler($type)) { $result = true; } return $result; }
/** * Lookup CRUD action events handling logic. * * @return \Cake\Network\Response */ public function lookup() { $this->Crud->on('beforeLookup', function (Event $event) { if (!empty($this->request->query['query'])) { $typeaheadFields = []; // Get typeahead fields from configuration if (method_exists($this->{$this->name}, 'typeaheadFields') && is_callable([$this->{$this->name}, 'typeaheadFields'])) { $typeaheadFields = $this->{$this->name}->typeaheadFields(); } // If there are no typeahead fields configured, use displayFields() if (empty($typeaheadFields)) { $typeaheadFields[] = $this->{$this->name}->displayField(); } $conditions = []; if (count($typeaheadFields) > 1) { $conditions['OR'] = []; foreach ($typeaheadFields as $field) { $conditions['OR'][] = [$field . ' LIKE' => '%' . $this->request->query['query'] . '%']; } } elseif (count($typeaheadFields) == 1) { $conditions[] = [$typeaheadFields[0] . ' LIKE' => '%' . $this->request->query['query'] . '%']; } else { throw new \RuntimeException("No typeahead or display field configured for " . $this->name); } $this->paginate['conditions'] = $conditions; } }); $this->Crud->on('afterLookup', function (Event $event) { // Properly populate display values for the found entries. // This will recurse into related modules and get display // values as deep as needed. $entities = $event->subject()->entities; $event->subject()->entities = []; foreach ($entities as $key => $entity) { $fhf = new FieldHandlerFactory(); // We need plain display value. It'll be properly wrapped // in styling only at the top level. $entity = $fhf->renderValue($this->{$this->name}, $this->{$this->name}->displayField(), $entity, ['renderAs' => RelatedFieldHandler::RENDER_PLAIN_VALUE]); $event->subject()->entities[$key] = $entity; } }); return $this->Crud->execute(); }
/** * Field type setter. * * @param string $type field type * @return void */ public function setType($type) { if (empty($type)) { throw new InvalidArgumentException(__CLASS__ . ': Empty field type is not allowed: ' . $this->getName()); } $type = $this->_extractType($type); $fhf = new FieldHandlerFactory(); if (!$fhf->hasFieldHandler($type)) { throw new InvalidArgumentException(__CLASS__ . ': Unsupported field type: ' . $type); } $this->_type = $type; }
/** * sendCalendarReminder method * Notification about the reminder is sent only * when the record belonds to anyone. * @param Cake\Event $event from the afterSave * @param Cake\Datasource\EntityInterface $entity from the afterSave * @return array|bool $sent on whether the email was sent */ public function sendCalendarReminder(Event $event, EntityInterface $entity) { $sent = false; $currentUser = null; //get applications's timezone $timezone = Time::now()->format('e'); $dtz = new \DateTimeZone($timezone); $table = $event->subject(); //get attendees Table for the event if (method_exists($table, 'getConfig') && is_callable([$table, 'getConfig'])) { $config = $table->getConfig(); $remindersTo = $table->getTableAllowRemindersField(); } // skip if attendees Table is not defined if (empty($remindersTo)) { return $sent; } // Figure out which field is a reminder one $reminderField = $table->getReminderFields(); if (empty($reminderField) || !is_array($reminderField)) { return $sent; } $reminderField = $reminderField[0]; if (!is_array($reminderField) || empty($reminderField['name'])) { return $sent; } $reminderField = $reminderField['name']; // Skip sending email if reminder field is empty if (empty($entity->{$reminderField})) { return $sent; } $attendeesFields = $this->_getAttendeesFields($table, ['tables' => $remindersTo]); // skip if no attendees fields found if (empty($attendeesFields)) { return $sent; } // skip if none of the required fields was modified $requiredFields = array_merge((array) $reminderField, $attendeesFields); if (!$this->_requiredFieldsModified($entity, $requiredFields)) { return $sent; } /* * Figure out the subject of the email * * This should happen AFTER the `$table->getConfig()` call, * in case the display field of the table is changed from the * configuration. * * Use singular of the table name and the value of the entity's display field. * For example: "Call: Payment remind" or "Lead: Qobo Ltd". */ $fhf = new FieldHandlerFactory(); $emailSubjectValue = $fhf->renderValue($table, $table->displayField(), $entity->{$table->displayField()}, ['renderAs' => 'plain']); $eventSubject = $emailSubjectValue ?: 'reminder'; $emailSubject = Inflector::singularize($table->alias()) . ": " . $eventSubject; $emailContent = Inflector::singularize($table->alias()) . " information was "; // If the record is being updated, prefix the above subject with "(Updated) ". if (!$entity->isNew()) { $emailSubject = '(Updated) ' . $emailSubject; $emailContent .= "updated"; } else { $emailContent .= "created"; } $emails = $this->_getAttendees($table, $entity, $attendeesFields); if (empty($emails)) { return $sent; } if (method_exists($table, 'getCurrentUser') && is_callable([$table, 'getCurrentUser'])) { $currentUser = $table->getCurrentUser(); $emailContent .= " by " . $currentUser['email']; } // append changelog if entity is not new if (!$entity->isNew()) { $emailContent .= "\n\n" . $this->_getChangelog($entity); } foreach ($emails as $email) { $vCalendar = new \Eluceo\iCal\Component\Calendar('//EN//'); $vAttendees = $this->_getEventAttendees($emails); $vEvent = $this->_getCalendarEvent($entity, ['dtz' => $dtz, 'organizer' => $email, 'subject' => $emailSubject, 'attendees' => $vAttendees, 'field' => $reminderField, 'timezone' => $timezone]); $vEvent->setAttendees($vAttendees); $vCalendar->addComponent($vEvent); $headers = "Content-Type: text/calendar; charset=utf-8"; $headers .= 'Content-Disposition: attachment; filename="event.ics"'; $emailer = new Email('default'); $emailer->to($email)->setHeaders([$headers])->subject($emailSubject)->attachments(['event.ics' => ['contentDisposition' => true, 'mimetype' => 'text/calendar', 'data' => $vCalendar->render()]]); $sent = $emailer->send($emailContent); } return $sent; }
/** * Method that converts csv action fields to database fields and returns their names. * * @param array $fields action fields * @param Event $event Event instance * @return array */ protected function _databaseFields(array $fields, Event $event) { $result = []; $migrationFields = $this->_getMigrationFields($event->subject()->request); if (empty($migrationFields)) { return $result; } $fhf = new FieldHandlerFactory(); foreach ($fields as $field) { if (!array_key_exists($field, $migrationFields)) { $result[] = $field; continue; } $csvField = new CsvField($migrationFields[$field]); foreach ($fhf->fieldToDb($csvField) as $dbField) { $result[] = $dbField->getName(); } } $virtualFields = $event->subject()->{$event->subject()->name}->getVirtualFields(); if (empty($virtualFields)) { return $result; } // handle virtual fields foreach ($fields as $k => $field) { if (!isset($virtualFields[$field])) { continue; } // remove virtual field unset($result[$k]); // add db fields $result = array_merge($result, $virtualFields[$field]); } return $result; }