/**
  * 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;
 }