Example #1
0
 public function detectCallableForField(FieldInterface $field)
 {
     $method = null;
     $type = null;
     if (!$field instanceof DbField) {
         return false;
     }
     if ($field->isType('reference')) {
         return $this->handleDbReference($field, 'reference');
     } elseif ($field->isType('manytomany')) {
         return $this->handleDbReference($field, 'manytomany');
     }
     if ($field->isType('boolean')) {
         $type = 'boolean';
     } elseif ($field->isType('date', 'timestamp')) {
         $type = 'date';
     } elseif ($field->isType('integer', 'float')) {
         $type = 'numeric';
     } elseif ($field->isType('clob', 'text')) {
         $type = 'text';
     } else {
         return false;
     }
     if (null !== $type) {
         return function () use($type) {
             return array('type' => $type, 'options' => '');
         };
     }
     return false;
 }
 /**
  * Adjust the behavior of the supplied field in the context of the supplied
  * table renderer so that it draws a "handle" that the user can grab to
  * drag the row around.  Adds some custom JS/CSS to pull that off.
  *
  * @param FieldInterface $field
  * @param TableCell $cellRenderer
  * @param string $primaryKeyName
  * @return void
  */
 public function assignToField(FieldInterface $field, TableCell $cellRenderer, $primaryKeyName)
 {
     $this->view->headScript()->appendFile($this->view->bowerUrl('/dewdrop/www/js/listing-sortable.js'));
     $this->view->headLink()->appendStylesheet($this->view->bowerUrl('/dewdrop/www/css/listing-sortable.css'));
     $cellRenderer->getContentRenderer()->assign($field->getId(), function ($helper, array $rowData) use($primaryKeyName) {
         /* @var $helper TableCell\Content */
         return sprintf('<span data-id="%d" class="handle glyphicon glyphicon-align-justify"></span>', $helper->getView()->escapeHtmlAttr($rowData[$primaryKeyName]));
     });
 }
Example #3
0
 /**
  * For DB fields, we can automatically return an Input.
  *
  * @param FieldInterface $field
  * @return bool|callable|mixed
  */
 public function detectCallableForField(FieldInterface $field)
 {
     if (!$field instanceof DbField) {
         return false;
     }
     return function ($helper) use($field) {
         return $field->getInputFilter();
     };
 }
Example #4
0
 private function renderContent(FieldInterface $field, array $rowData, callable $outputFilter = null)
 {
     if (!isset($rowData[$field->getName()]) || !$rowData[$field->getName()]) {
         return null;
     }
     $date = new DateTimeImmutable($rowData[$field->getName()]);
     $output = $date->format($this->format);
     if ($outputFilter) {
         $output = $outputFilter($output);
     }
     return $output;
 }
 public function __invoke(FieldInterface $field)
 {
     $field->assignHelperCallback('SelectFilter.DefaultVars', function () {
         $end = $this->startDate->add($this->dateInterval);
         // Swap dates if end if before start
         if ($end < $this->startDate) {
             return ['comp' => 'on-or-between', 'end' => $this->startDate->format('Y-m-d'), 'start' => $end->format('Y-m-d')];
         } else {
             return ['comp' => 'on-or-between', 'start' => $this->startDate->format('Y-m-d'), 'end' => $end->format('Y-m-d')];
         }
     });
 }
Example #6
0
 private function valueChanged()
 {
     if ($this->field instanceof DbField && !$this->field->hasRow()) {
         return false;
     }
     $newValue = $this->field->getValue();
     if (is_array($this->originalValue) && is_array($newValue)) {
         $intersection = count(array_intersect($this->originalValue, $newValue));
         return count($this->originalValue) !== $intersection || count($newValue) !== $intersection;
     } else {
         return $this->originalValue !== $newValue;
     }
 }
Example #7
0
 public function __invoke(FieldInterface $field)
 {
     $field->addHelperFilter('TableCell.Content', function ($content, TableCell $helper, array $rowData, $rowIndex, $columnIndex) {
         if (!$content) {
             return $content;
         }
         return $helper->getView()->escapeHtml(sprintf($this->template, $content));
     });
     $field->addHelperFilter('CsvCell.Content', function ($content, CsvCell $helper, array $rowData, $rowIndex, $columnIndex) {
         if (!$content) {
             return $content;
         }
         return sprintf($this->template, $content);
     });
 }
Example #8
0
 /**
  * Sort the listing in both ascending and descending order for the
  * supplied field, catching any exceptions if the sorted query causes
  * a problem.
  *
  * @param FieldInterface $field
  * @return array
  */
 public function runOnSingleField(FieldInterface $field)
 {
     $directions = ['ASC', 'DESC'];
     $results = [];
     foreach ($directions as $direction) {
         $results[$direction] = array('success' => false, 'message' => null, 'sql' => '');
         $request = new Request(array(), array($this->listing->getPrefix() . 'sort' => urldecode($field->getQueryStringId()), $this->listing->getPrefix() . 'dir' => $direction));
         $this->sortHelper->setRequest($request);
         try {
             // Don't need much data here, just need to run the query.
             $select = $this->listing->getModifiedSelect($this->fields)->limit(1);
             $results[$direction]['sql'] = (string) $select->reset(Select::LIMIT_COUNT);
             $select->getAdapter()->fetchAll($select);
             $results[$direction]['success'] = true;
         } catch (CorePhpException $e) {
             $results[$direction]['message'] = $e->getMessage();
         }
     }
     return $results;
 }
Example #9
0
 public function __invoke(FieldInterface $field)
 {
     $field->addHelperFilter('TableCell.Content', function ($content, TableCell $helper, array $rowData, $rowIndex, $columnIndex) {
         if (!$content) {
             return null;
         }
         if (!$this->urlTemplate || !isset($rowData[$this->id]) || !$rowData[$this->id]) {
             return $content;
         } else {
             $node = new Node('a');
             $node->setHtml($content)->setAttribute('href', sprintf($this->urlTemplate, $rowData[$this->id]))->setAttribute('class', implode(' ', $this->cssClasses));
             if ($this->title) {
                 $node->setAttribute('title', $this->title);
             }
             if ($this->target) {
                 $node->setAttribute('target', $this->target);
             }
             return $node;
         }
     });
 }
Example #10
0
 /**
  * Build a Fields object that can be used when rendering the grouped counts.  Supplies a field
  * to render the actual HTML value from the original Fields object used when fetching data for
  * the listing and a field to render the count for that value.  We don't do any escaping here
  * because we assume that the original Fields object handled that in its rendering code.  The
  * fields object returned from this method supports both TableCell and CsvCell rendering.
  *
  * @return Fields
  */
 public function buildRenderFields()
 {
     $fields = new Fields();
     $fields->add('content')->setLabel($this->groupField->getLabel())->setVisible(true)->assignHelperCallback('TableCell.Content', function (TableCell\Content $helper, array $rowData) {
         // Not escaping here because we assume it was escaped by the original renderer in fetchData()
         return $rowData['content'];
     })->assignHelperCallback('CsvCell.Content', function (CsvCell\Content $helper, array $rowData) {
         return $rowData['content'];
     })->add('count')->setLabel('Count')->setVisible(true)->assignHelperCallback('TableCell.Content', function (TableCell\Content $helper, array $rowData) {
         return $helper->getView()->escapeHtml($rowData['count']);
     })->assignHelperCallback('CsvCell.Content', function (CsvCell\Content $helper, array $rowData) {
         return $rowData['count'];
     });
     return $fields;
 }
 /**
  * Detect which view helper should be used to edit the supplied
  * \Dewdrop\Db\Field.  THis is basic logic used to determine a suitable
  * helper:
  *
  * <ol>
  *     <li>
  *         If a custom helper was assigned by calling customizeField(),
  *         use that.
  *     </li>
  *     <li>
  *         If it is an EAV field, use whatever helper is assigned in the
  *         EAV definition.
  *     </li>
  *     <li>
  *         Otherwise, look at the field's type to determine which helper
  *         would be appropriate.
  *     </li>
  *     <li>
  *         If a suitable helper cannot be determined, throw an exception.
  *     </li>
  * </ol>
  *
  * @throws \Dewdrop\Exception
  * @param Field $field
  * @return string
  */
 public function detect(FieldInterface $field)
 {
     if (array_key_exists($field->getControlName(), $this->customHelpers)) {
         return $this->customHelpers[$field->getControlName()];
     } elseif ($field instanceof EavField) {
         return $field->getEditHelperName();
     } elseif ($field->isType('boolean', 'boolean')) {
         return 'inputCheckbox';
     } elseif ($field->isType('manytomany')) {
         return 'checkboxList';
     } elseif ($field->isType('reference')) {
         return 'select';
     } elseif ($field->isType('clob')) {
         return 'textarea';
     } elseif ($field->isType('text', 'integer', 'float')) {
         return 'inputText';
     } elseif ($field->isType('date')) {
         return 'inputDate';
     } elseif ($field->isType('timestamp')) {
         return 'inputTimestamp';
     }
     throw new Exception('Fields\\EditHelperDetector: Could not find a suitable view helper for field ' . $field->getControlName() . '.');
 }
Example #12
0
 /**
  * Wrap a field's callback to ensure that a reference to the helper is
  * always supplied as the first argument to the callback.
  *
  * @param callable $callable
  * @param FieldInterface $field
  * @return callable
  */
 protected function wrapCallable(callable $callable, FieldInterface $field = null)
 {
     return function () use($callable, $field) {
         $arguments = func_get_args();
         array_unshift($arguments, $this);
         $output = call_user_func_array($callable, $arguments);
         if ($field) {
             /* @var $filter callable */
             foreach ($field->getHelperFilters($this->name) as $filter) {
                 $filterArguments = $arguments;
                 array_unshift($filterArguments, $output);
                 $output = call_user_func_array($filter, $filterArguments);
             }
         }
         return $output;
     };
 }
Example #13
0
 /**
  * If no custom callback is defined for a field, it will fall back to this
  * method to find a suitable callback.  In the case of the Header helper,
  * we fall back to all field's just returning their label.
  *
  * @param FieldInterface $field
  * @return callable
  */
 public function detectCallableForField(FieldInterface $field)
 {
     return function () use($field) {
         return $this->view->escapeHtml($field->getLabel());
     };
 }
Example #14
0
 /**
  * Try to detect a default callback for the provided field.  THis helper
  * will only provide a default for database fields of common types.  For
  * custom fields, you'll have to assign your own callback, if you want them
  * to be sortable.
  *
  * @param FieldInterface $field
  * @return false|callable
  */
 public function detectCallableForField(FieldInterface $field)
 {
     $method = null;
     if (!$field instanceof DbField) {
         return false;
     }
     if ($field->isType('reference')) {
         $method = 'sortDbReference';
     } elseif ($field->isType('date', 'timestamp')) {
         $method = 'sortDbDate';
     } elseif ($field->isType('manytomany', 'clob', 'string', 'numeric', 'boolean')) {
         $method = 'sortDbDefault';
     }
     if (!$method) {
         return false;
     } else {
         return function ($helper, Select $select, $direction) use($field, $method) {
             return $this->{$method}($field, $select, $direction);
         };
     }
 }
Example #15
0
 /**
  * If no custom callback is defined for a field, it will fall back to this
  * method to find a suitable callback.  In the case of the Header helper,
  * we fall back to all fields just returning their labels.
  *
  * @param FieldInterface $field
  * @return callable
  */
 public function detectCallableForField(FieldInterface $field)
 {
     return function () use($field) {
         return $field->getLabel();
     };
 }
Example #16
0
 public function detectCallableForField(FieldInterface $field)
 {
     $type = null;
     if (!$field instanceof DbField) {
         return false;
     }
     if ($field->isType('manytomany')) {
         /* @var $field \Dewdrop\Db\ManyToMany\Field */
         $filter = new ManyToManyFilter($field->getManyToManyRelationship());
     } else {
         if ($field->isType('reference')) {
             $type = 'Reference';
         } elseif ($field->isType('boolean')) {
             $type = 'Boolean';
         } elseif ($field->isType('date', 'timestamp')) {
             $type = 'Date';
         } elseif ($field->isType('integer', 'float')) {
             $type = 'Numeric';
         } elseif ($field->isType('clob', 'text')) {
             $type = 'Text';
         } else {
             return false;
         }
         if ($field instanceof EavField) {
             $tableName = $field->getName();
             $fieldName = 'value';
         } else {
             $tableName = $field->getTable()->getTableName();
             $fieldName = $field->getName();
         }
         $className = '\\Dewdrop\\Db\\Select\\Filter\\' . $type;
         $filter = new $className($tableName, $fieldName);
     }
     return function ($helper, $select, $conditionSetName, $queryVars) use($filter) {
         return $filter->apply($select, $conditionSetName, $queryVars);
     };
 }
Example #17
0
 public function renderFieldContent(FieldInterface $field, InputFilter $inputFilter, Renderer $renderer, $position, $renderLabels = true)
 {
     $output = '';
     $input = $inputFilter->has($field->getId()) ? $inputFilter->get($field->getId()) : null;
     $messages = $input ? $input->getMessages() : null;
     $output .= sprintf($this->renderFormGroupOpenTag(), $messages ? ' has-feedback has-error alert alert-danger' : '');
     $controlOutput = $renderer->getControlRenderer()->render($field, $position);
     if ($renderLabels && $this->controlRequiresLabel($controlOutput)) {
         $output .= $this->renderLabel($field, $renderer, $input);
     }
     $output .= $controlOutput;
     if ($messages) {
         $output .= $this->renderMessages($messages);
     }
     if ($field->getNote()) {
         $output .= sprintf('<div class="help-block">%s</div>', $this->view->escapeHtml($field->getNote()));
     }
     $output .= '</div>';
     return $output;
 }
Example #18
0
 /**
  * If no custom callback is defined for a field, it will fall back to this
  * method to find a suitable callback.  In the case of the Content helper,
  * we only provide a fall back for DB-based fields.  Custom fields will have
  * to define a callback in order to function properly.
  *
  * @param FieldInterface $field
  * @return mixed
  */
 public function detectCallableForField(FieldInterface $field)
 {
     $method = null;
     if (!$field instanceof DbField) {
         return false;
     }
     if ($field->isType('boolean')) {
         $method = 'renderDbBoolean';
     } elseif ($field->isType('reference')) {
         $method = 'renderDbReference';
     } elseif ($field->isType('date')) {
         $method = 'renderDbDate';
     } elseif ($field->isType('timestamp')) {
         $method = 'renderDbTimestamp';
     } elseif ($field->isType('manytomany', 'clob', 'string', 'numeric')) {
         $method = 'renderDbText';
     }
     if (!$method) {
         return false;
     } else {
         return function ($helper, array $rowData) use($field, $method) {
             return $this->{$method}($field, $rowData);
         };
     }
 }
Example #19
0
 /**
  * Get the validation messages associated with a specific field.
  *
  * @param FieldInterface $field
  * @return array
  */
 public function getMessages(FieldInterface $field)
 {
     return $this->getInputFilter()->get($field->getId())->getMessages();
 }
Example #20
0
 /**
  * Get the callback that will be used for the given FieldInterface object.
  *
  * @param FieldInterface $field
  * @throws \Dewdrop\Fields\Exception\HelperCallableNotAvailableForField
  * @return callable
  */
 public function getFieldAssignment(FieldInterface $field)
 {
     if (!$this->hasValidName()) {
         return false;
     }
     $id = $field->getId();
     if (!array_key_exists($id, $this->assignments)) {
         if (!$field->hasHelperCallback($this->name)) {
             $callback = $this->detectCallableForField($field);
         } else {
             $callback = $field->getHelperCallback($this->name);
         }
         if (!is_callable($callback)) {
             throw new HelperCallableNotAvailableForField("Field {$id} does not have a callable assigned and one could not be detected.");
         }
         $this->assignments[$id] = $this->wrapCallable($callback);
     }
     return $this->assignments[$id];
 }
Example #21
0
 /**
  * Add the supplied field to this collection after another specified field already in the collection. Can be a
  * FieldInterface object or a string, in which case a new custom field will be added with the supplied string as its
  * ID.
  *
  * The newly added FieldInterface object is returned from this method so that it can be further customized
  * immediately, using method chaining. Once you've completed calling methods on the FieldInterface object itself,
  * you can call any \Dewdrop\Fields methods to return execution to that context.
  *
  * @param FieldInterface|string $field
  * @param FieldInterface|string $after
  * @param string $modelName
  * @throws Exception
  * @return FieldInterface
  */
 public function insertAfter($field, $after, $modelName = null)
 {
     if ($after instanceof FieldInterface) {
         $afterId = $after->getId();
     } else {
         $afterId = (string) $after;
     }
     if (!$this->has($afterId, $afterPosition)) {
         throw new Exception("Field with ID \"{$afterId}\" does not exist in this collection");
     }
     $field = $this->prepareFieldForAdding($field, $modelName);
     array_splice($this->fields, $afterPosition + 1, 0, [$field]);
     return $field;
 }
 /**
  * A shortcut/utility method that sets up an EditControl.Control callback
  * to use OptionInputDecorator.
  *
  * @param FieldInterface $field
  * @param CrudInterface $controlComponent
  * @param CrudInterface $optionComponent
  * @param callable $originalHtmlCallback
  */
 public static function assignEditControlCallback(FieldInterface $field, CrudInterface $controlComponent, CrudInterface $optionComponent, callable $originalHtmlCallback = null)
 {
     $field->assignHelperCallback('EditControl.Control', OptionInputDecorator::createEditControlCallback($field, $controlComponent, $optionComponent, $originalHtmlCallback));
 }