diff --git a/CRM/Dataprocessor/BAO/DataProcessor.php b/CRM/Dataprocessor/BAO/DataProcessor.php index 57060e8e12fe86808b82fe1bd352bce11e5a574b..829243b2612df3886dd116fddd742b8d960f921f 100644 --- a/CRM/Dataprocessor/BAO/DataProcessor.php +++ b/CRM/Dataprocessor/BAO/DataProcessor.php @@ -85,10 +85,10 @@ class CRM_Dataprocessor_BAO_DataProcessor extends CRM_Dataprocessor_DAO_DataProc } $fields = civicrm_api3('DataProcessorField', 'get', array('data_processor_id' => $dataProcessor['id'], 'options' => array('limit' => 0))); - $outputHandlers = $dataProcessorClass->getAvailableOutputHandlers(); foreach($fields['values'] as $field) { - if (isset($outputHandlers[$field['type']])) { - $outputHandler = $outputHandlers[$field['type']]; + $outputHandler = $factory->getOutputHandlerByName($field['type']); + if ($outputHandler) { + $outputHandler->setDataProcessor($dataProcessorClass); $outputHandler->initialize($field['name'], $field['title'], $field['configuration']); $dataProcessorClass->addOutputFieldHandlers($outputHandler); } diff --git a/CRM/Dataprocessor/Form/Field.php b/CRM/Dataprocessor/Form/Field.php index f3c075244963d006e8adc93020bd5a28d3a5e4a0..e1662f2c8e4d0ad9bcad0cb5de4007347da4a025 100644 --- a/CRM/Dataprocessor/Form/Field.php +++ b/CRM/Dataprocessor/Form/Field.php @@ -40,6 +40,7 @@ class CRM_Dataprocessor_Form_Field extends CRM_Core_Form { * @access public */ function preProcess() { + $factory = dataprocessor_get_factory(); $this->snippet = CRM_Utils_Request::retrieve('snippet', 'String'); if ($this->snippet) { $this->assign('suppressForm', TRUE); @@ -56,20 +57,23 @@ class CRM_Dataprocessor_Form_Field extends CRM_Core_Form { $this->id = CRM_Utils_Request::retrieve('id', 'Integer'); $this->assign('id', $this->id); - if ($this->id) { $this->field = civicrm_api3('DataProcessorField', 'getsingle', array('id' => $this->id)); $this->assign('field', $this->field); } + if (!$this->field) { + $this->field['data_processor_id'] = $this->dataProcessorId; + } - $this->outputHandlers = $this->dataProcessorClass->getAvailableOutputHandlers(); + $this->outputHandlers = $factory->getOutputHandlers(); + asort($this->outputHandlers); $type = CRM_Utils_Request::retrieve('type', 'String'); - if (!$type && $this->field) { + if (!$type && $this->field && isset($this->field['type'])) { $type = $this->field['type']; } if ($type) { - $this->outputHandlerClass = $this->outputHandlers[$type]; + $this->outputHandlerClass = $factory->getOutputHandlerByName($type); $this->assign('has_configuration', $this->outputHandlerClass->hasConfiguration()); } @@ -84,12 +88,7 @@ class CRM_Dataprocessor_Form_Field extends CRM_Core_Form { $this->add('text', 'name', E::ts('Name'), array('size' => CRM_Utils_Type::HUGE), FALSE); $this->add('text', 'title', E::ts('Title'), array('size' => CRM_Utils_Type::HUGE), TRUE); - foreach($this->outputHandlers as $outputHandler) { - $outputHandlersSelect[$outputHandler->getName()] = $outputHandler->getTitle(); - } - asort($outputHandlersSelect); - - $this->add('select', 'type', E::ts('Select Field'), $outputHandlersSelect, true, array( + $this->add('select', 'type', E::ts('Select Field'), $this->outputHandlers, true, array( 'style' => 'min-width:250px', 'class' => 'crm-select2 huge', 'placeholder' => E::ts('- select -'), diff --git a/CRM/Dataprocessor/Utils/DataSourceFields.php b/CRM/Dataprocessor/Utils/DataSourceFields.php index acd5a9e19809358956a4c7d113f4fe7bc52731b7..5bd7efa64207ed04cf8108313df9d918266ecf4e 100644 --- a/CRM/Dataprocessor/Utils/DataSourceFields.php +++ b/CRM/Dataprocessor/Utils/DataSourceFields.php @@ -12,15 +12,17 @@ class CRM_Dataprocessor_Utils_DataSourceFields { * Returns an array with the name of the field as the key and the label of the field as the value. * * @oaram int $dataProcessorId + * @param callable $callback + * Function to filter certain fields. * @return array * @throws \Exception */ - public static function getAvailableFieldsInDataSources($dataProcessorId) { + public static function getAvailableFieldsInDataSources($dataProcessorId, $filterFieldsCallback=null) { $dataProcessor = civicrm_api3('DataProcessor', 'getsingle', array('id' => $dataProcessorId)); $dataProcessorClass = \CRM_Dataprocessor_BAO_DataProcessor::dataProcessorToClass($dataProcessor); $fieldSelect = array(); foreach($dataProcessorClass->getDataSources() as $dataSource) { - $fieldSelect = array_merge($fieldSelect, self::getAvailableFieldsInDataSource($dataSource, $dataSource->getSourceTitle().' :: ', $dataSource->getSourceName().'::')); + $fieldSelect = array_merge($fieldSelect, self::getAvailableFieldsInDataSource($dataSource, $dataSource->getSourceTitle().' :: ', $dataSource->getSourceName().'::', $filterFieldsCallback)); } return $fieldSelect; } @@ -29,13 +31,67 @@ class CRM_Dataprocessor_Utils_DataSourceFields { * Returns an array with the name of the field as the key and the label of the field as the value. * * @oaram SourceInterface $dataSource + * @param $titlePrefix + * @param $namePrefix + * @param callable $callback + * Function to filter certain fields. * @return array * @throws \Exception */ - public static function getAvailableFieldsInDataSource(SourceInterface $dataSource, $titlePrefix='', $namePrefix='') { + public static function getAvailableFieldsInDataSource(SourceInterface $dataSource, $titlePrefix='', $namePrefix='', $filterFieldsCallback=null) { + $fieldSelect = array(); + foreach($dataSource->getAvailableFields()->getFields() as $field) { + $isFieldValid = true; + if ($filterFieldsCallback) { + $isFieldValid = call_user_func($filterFieldsCallback, $field); + } + if ($isFieldValid) { + $fieldSelect[$namePrefix . $field->name] = $titlePrefix . $field->title; + } + } + return $fieldSelect; + } + + /** + * Returns an array with the name of the field as the key and the label of the field as the value. + * + * @oaram int $dataProcessorId + * @param callable $callback + * Function to filter certain fields. + * @return array + * @throws \Exception + */ + public static function getAvailableFilterFieldsInDataSources($dataProcessorId, $filterFieldsCallback=null) { + $dataProcessor = civicrm_api3('DataProcessor', 'getsingle', array('id' => $dataProcessorId)); + $dataProcessorClass = \CRM_Dataprocessor_BAO_DataProcessor::dataProcessorToClass($dataProcessor); + $fieldSelect = array(); + foreach($dataProcessorClass->getDataSources() as $dataSource) { + $fieldSelect = array_merge($fieldSelect, self::getAvailableFieldsInDataSource($dataSource, $dataSource->getSourceTitle().' :: ', $dataSource->getSourceName().'::', $filterFieldsCallback)); + } + return $fieldSelect; + } + + /** + * Returns an array with the name of the field as the key and the label of the field as the value. + * + * @oaram SourceInterface $dataSource + * @param $titlePrefix + * @param $namePrefix + * @param callable $callback + * Function to filter certain fields. + * @return array + * @throws \Exception + */ + public static function getAvailableFilterFieldsInDataSource(SourceInterface $dataSource, $titlePrefix='', $namePrefix='', $filterFieldsCallback=null) { $fieldSelect = array(); foreach($dataSource->getAvailableFilterFields()->getFields() as $field) { - $fieldSelect[$namePrefix.$field->name] = $titlePrefix.$field->title; + $isFieldValid = true; + if ($filterFieldsCallback) { + $isFieldValid = call_user_func($filterFieldsCallback, $field); + } + if ($isFieldValid) { + $fieldSelect[$namePrefix . $field->name] = $titlePrefix . $field->title; + } } return $fieldSelect; } diff --git a/CRM/DataprocessorSearch/Form/AbstractSearch.php b/CRM/DataprocessorSearch/Form/AbstractSearch.php index 0535e2ab36d173e1d49ae79014fd3ce072332912..ceaa55a686609977492428da299383ff94d5de49 100644 --- a/CRM/DataprocessorSearch/Form/AbstractSearch.php +++ b/CRM/DataprocessorSearch/Form/AbstractSearch.php @@ -298,12 +298,14 @@ abstract class CRM_DataprocessorSearch_Form_AbstractSearch extends CRM_Dataproce $field = $outputFieldHandler->getOutputFieldSpecification(); if (!in_array($field->alias, $hiddenFields)) { $columnHeaders[$field->alias] = $field->title; - $sortFields[$sortColumnNr] = array( - 'name' => $field->title, - 'sort' => $field->alias, - 'direction' => CRM_Utils_Sort::DONTCARE, - ); - $sortColumnNr++; + if ($outputFieldHandler instanceof \Civi\DataProcessor\FieldOutputHandler\OutputHandlerSortable) { + $sortFields[$sortColumnNr] = array( + 'name' => $field->title, + 'sort' => $field->alias, + 'direction' => CRM_Utils_Sort::DONTCARE, + ); + $sortColumnNr++; + } } } $this->assign('columnHeaders', $columnHeaders); diff --git a/Civi/DataProcessor/Event/OutputHandlerEvent.php b/Civi/DataProcessor/Event/OutputHandlerEvent.php deleted file mode 100644 index c66e68655dce01f66d9e0e3a0e650519d2e0c780..0000000000000000000000000000000000000000 --- a/Civi/DataProcessor/Event/OutputHandlerEvent.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -/** - * @author Jaap Jansma <jaap.jansma@civicoop.org> - * @license AGPL-3.0 - */ - -namespace Civi\DataProcessor\Event; - -use Civi\DataProcessor\ProcessorType\AbstractProcessorType; -use Symfony\Component\EventDispatcher\Event; - -class OutputHandlerEvent extends Event { - - const NAME = 'dataprocessor.outputhandler'; - - /** - * @var \Civi\DataProcessor\ProcessorType\AbstractProcessorType - */ - public $dataProcessor; - - /** - * @var array - */ - public $handlers = array(); - - public function __construct(AbstractProcessorType $dataProcessor) { - $this->dataProcessor = $dataProcessor; - } - -} \ No newline at end of file diff --git a/Civi/DataProcessor/Event/SourceOutputHandlerEvent.php b/Civi/DataProcessor/Event/SourceOutputHandlerEvent.php deleted file mode 100644 index 39fb4410b55d907f2b14710f9ebf271bff4e8338..0000000000000000000000000000000000000000 --- a/Civi/DataProcessor/Event/SourceOutputHandlerEvent.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php -/** - * @author Jaap Jansma <jaap.jansma@civicoop.org> - * @license AGPL-3.0 - */ - -namespace Civi\DataProcessor\Event; - -use Civi\DataProcessor\DataSpecification\FieldSpecification; -use Civi\DataProcessor\Source\SourceInterface; -use Symfony\Component\EventDispatcher\Event; - -class SourceOutputHandlerEvent extends Event { - - const NAME = 'dataprocessor.source_outputhandler'; - - /** - * @var FieldSpecification - */ - public $fieldSpecification; - - /** - * @var SourceInterface - */ - public $dataSource; - - /** - * @var array - */ - public $handlers = array(); - - public function __construct(FieldSpecification $field, SourceInterface $source) { - $this->fieldSpecification = $field; - $this->dataSource = $source; - } - -} \ No newline at end of file diff --git a/Civi/DataProcessor/Factory.php b/Civi/DataProcessor/Factory.php index 5237c836f0c02151ed78f8b98afe52c7530970b6..1d20489ae99b3c604cad3a02c46459168d3f38db 100644 --- a/Civi/DataProcessor/Factory.php +++ b/Civi/DataProcessor/Factory.php @@ -7,30 +7,16 @@ namespace Civi\DataProcessor; use Civi\DataProcessor\DataFlow\Sort\SortCompareFactory; -use Civi\DataProcessor\DataSpecification\FieldSpecification; use Civi\DataProcessor\Event\FilterHandlerEvent; use Civi\DataProcessor\Event\OutputHandlerEvent; use Civi\DataProcessor\Event\SourceOutputHandlerEvent; -use Civi\DataProcessor\FieldOutputHandler\ContactLinkFieldOutputHandler; -use Civi\DataProcessor\FieldOutputHandler\FileFieldOutputHandler; -use Civi\DataProcessor\FieldOutputHandler\OptionFieldOutputHandler; -use Civi\DataProcessor\FieldOutputHandler\RawFieldOutputHandler; -use Civi\DataProcessor\FilterHandler\SimpleSqlFilter; use Civi\DataProcessor\ProcessorType\AbstractProcessorType; -use Civi\DataProcessor\Source\SourceInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; use CRM_Dataprocessor_ExtensionUtil as E; class Factory { - /** - * @var EventDispatcher - */ - protected $dispatcher; - /** * @var array<String> */ @@ -75,6 +61,16 @@ class Factory { */ protected $filterClasses = array(); + /** + * @var String[] + */ + protected $outputHandlers = array(); + + /** + * @var String[] + */ + protected $outputHandlerClasses = array(); + /** * @var array<String> */ @@ -95,8 +91,6 @@ class Factory { public function __construct() { - $this->dispatcher = \Civi::dispatcher(); - $this->addDataProcessorType('default', 'Civi\DataProcessor\ProcessorType\DefaultProcessorType', E::ts('Default')); $this->addDataSource('activity', 'Civi\DataProcessor\Source\Activity\ActivitySource', E::ts('Activity')); $this->addDataSource('contact', 'Civi\DataProcessor\Source\Contact\ContactSource', E::ts('Contact')); @@ -132,6 +126,11 @@ class Factory { $this->addFilter('simple_sql_filter', 'Civi\DataProcessor\FilterHandler\SimpleSqlFilter', E::ts('Field filter')); $this->addjoinType('simple_join', 'Civi\DataProcessor\DataFlow\MultipleDataFlows\SimpleJoin', E::ts('Select fields to join on')); $this->addjoinType('simple_non_required_join', 'Civi\DataProcessor\DataFlow\MultipleDataFlows\SimpleNonRequiredJoin', E::ts('Select fields to join on (not required)')); + $this->addOutputHandler('raw', 'Civi\DataProcessor\FieldOutputHandler\RawFieldOutputHandler', E::ts('Raw field value')); + $this->addOutputHandler('contact_link', 'Civi\DataProcessor\FieldOutputHandler\ContactLinkFieldOutputHandler', E::ts('Link to view contact')); + $this->addOutputHandler('file_field', 'Civi\DataProcessor\FieldOutputHandler\FileFieldOutputHandler', E::ts('File download link')); + $this->addOutputHandler('option_label', 'Civi\DataProcessor\FieldOutputHandler\OptionFieldOutputHandler', E::ts('Option label')); + } /** @@ -270,37 +269,43 @@ class Factory { * @param $name * @param $class * @param $label - * @return Factory */ - public function addOutput($name, $class, $label) { - $this->outputClasses[$name] = $class; - $this->outputs[$name] = $label; - return $this; + public function addOutputHandler($name, $class, $label) { + $this->outputHandlerClasses[$name] = $class; + $this->outputHandlers[$name] = $label; } - public function getOutputHandlers(FieldSpecification $field, SourceInterface $source) { - $event = new SourceOutputHandlerEvent($field, $source); - $rawOutputhandler = new RawFieldOutputHandler($field, $source); - $event->handlers[$rawOutputhandler->getName()] = $rawOutputhandler; - if ($field->getOptions()) { - $optionOutputHandler = new OptionFieldOutputHandler($field, $source); - $event->handlers[$optionOutputHandler->getName()] = $optionOutputHandler; - } - if ($field->type == 'File') { - $fileOutputHandler = new FileFieldOutputHandler($field, $source); - $event->handlers[$fileOutputHandler->getName()] = $fileOutputHandler; - } - $this->dispatcher->dispatch(SourceOutputHandlerEvent::NAME, $event); - return $event->handlers; + /** + * @return String[] + */ + public function getOutputHandlers() { + return $this->outputHandlers; } /** - * Add an event subscriber class + * @param $name * - * @param \Symfony\Component\EventDispatcher\EventSubscriberInterface $subscriber + * @return \Civi\DataProcessor\FieldOutputHandler\AbstractFieldOutputHandler */ - public function addSubscriber(EventSubscriberInterface $subscriber) { - $this->dispatcher->addSubscriber($subscriber); + public function getOutputHandlerByName($name) { + if ($name && isset($this->outputHandlerClasses[$name])) { + $class = $this->outputHandlerClasses[$name]; + return new $class(); + } else { + return null; + } + } + + /** + * @param $name + * @param $class + * @param $label + * @return Factory + */ + public function addOutput($name, $class, $label) { + $this->outputClasses[$name] = $class; + $this->outputs[$name] = $label; + return $this; } /** diff --git a/Civi/DataProcessor/FieldOutputHandler/AbstractFieldOutputHandler.php b/Civi/DataProcessor/FieldOutputHandler/AbstractFieldOutputHandler.php index 9bb0bbea86f5998995e5de5baa1ef3935d3fd283..af23a5db5a3a793b64b742766f65b7140f7e45c5 100644 --- a/Civi/DataProcessor/FieldOutputHandler/AbstractFieldOutputHandler.php +++ b/Civi/DataProcessor/FieldOutputHandler/AbstractFieldOutputHandler.php @@ -12,28 +12,9 @@ use Civi\DataProcessor\ProcessorType\AbstractProcessorType; abstract class AbstractFieldOutputHandler { /** - * @var \Civi\DataProcessor\DataSpecification\FieldSpecification + * @var AbstractProcessorType */ - protected $outputFieldSpecification; - - /** - * @var \Civi\DataProcessor\Source\SourceInterface - */ - protected $dataSource; - - /** - * Returns the name of the handler type. - * - * @return String - */ - abstract public function getName(); - - /** - * Returns the title of the handler type. - * - * @return String - */ - abstract public function getTitle(); + protected $dataProcessor; /** * Returns the data type of this field @@ -52,20 +33,29 @@ abstract class AbstractFieldOutputHandler { */ abstract public function formatField($rawRecord, $formattedRecord); + /** + * @return \Civi\DataProcessor\DataSpecification\FieldSpecification + */ + abstract public function getOutputFieldSpecification(); + /** * AbstractFieldOutputHandler constructor. - * - * @param \Civi\DataProcessor\Source\SourceInterface $dataSource */ - public function __construct(\Civi\DataProcessor\Source\SourceInterface $dataSource) { - $this->dataSource = $dataSource; + public function __construct() { } /** - * @return \Civi\DataProcessor\Source\SourceInterface + * @param \Civi\DataProcessor\ProcessorType\AbstractProcessorType $dataProcessor */ - public function getDataSource() { - return $this->dataSource; + public function setDataProcessor(AbstractProcessorType $dataProcessor) { + $this->dataProcessor = $dataProcessor; + } + + /** + * @return \Civi\DataProcessor\ProcessorType\AbstractProcessorType + */ + public function getDataProcessor() { + return $this->dataProcessor; } /** @@ -77,15 +67,8 @@ abstract class AbstractFieldOutputHandler { */ public function initialize($alias, $title, $configuration) { // Override this in child classes. - $this->outputFieldSpecification->title = $title; - $this->outputFieldSpecification->alias = $alias; - } - - /** - * @return \Civi\DataProcessor\DataSpecification\FieldSpecification - */ - public function getOutputFieldSpecification() { - return $this->outputFieldSpecification; + //$this->outputFieldSpecification->title = $title; + //$this->outputFieldSpecification->alias = $alias; } /** diff --git a/Civi/DataProcessor/FieldOutputHandler/ContactLinkFieldOutputHandler.php b/Civi/DataProcessor/FieldOutputHandler/ContactLinkFieldOutputHandler.php index 6b0ae5d993063d02a488ed79aa0edfc5383b89b2..d9893d20d45d328cd90740b259c57eaf732352ca 100644 --- a/Civi/DataProcessor/FieldOutputHandler/ContactLinkFieldOutputHandler.php +++ b/Civi/DataProcessor/FieldOutputHandler/ContactLinkFieldOutputHandler.php @@ -12,18 +12,13 @@ use Civi\DataProcessor\Source\SourceInterface; use Civi\DataProcessor\DataSpecification\FieldSpecification; use Civi\DataProcessor\FieldOutputHandler\FieldOutput; -class ContactLinkFieldOutputHandler extends AbstractFieldOutputHandler { +class ContactLinkFieldOutputHandler extends AbstractFieldOutputHandler implements OutputHandlerSortable { /** * @var \Civi\DataProcessor\Source\SourceInterface */ protected $dataSource; - /** - * @var AbstractProcessorType - */ - protected $dataProcessor; - /** * @var SourceInterface */ @@ -44,18 +39,23 @@ class ContactLinkFieldOutputHandler extends AbstractFieldOutputHandler { */ protected $contactNameField; + /** + * @var FieldSpecification + */ + protected $outputFieldSpecification; - public function __construct(AbstractProcessorType $dataProcessor) { - $this->dataProcessor = $dataProcessor; + /** + * @return \Civi\DataProcessor\DataSpecification\FieldSpecification + */ + public function getOutputFieldSpecification() { + return $this->outputFieldSpecification; } /** - * Returns the name of the handler type. - * - * @return String + * @return \Civi\DataProcessor\DataSpecification\FieldSpecification */ - public function getName() { - return 'contact_link'; + public function getSortableInputFieldSpec() { + return $this->contactNameField; } /** @@ -67,15 +67,6 @@ class ContactLinkFieldOutputHandler extends AbstractFieldOutputHandler { return 'String'; } - /** - * Returns the title of this field - * - * @return String - */ - public function getTitle() { - return E::ts('Link to view contact'); - } - /** * Initialize the processor * @@ -85,7 +76,7 @@ class ContactLinkFieldOutputHandler extends AbstractFieldOutputHandler { * @param \Civi\DataProcessor\ProcessorType\AbstractProcessorType $processorType */ public function initialize($alias, $title, $configuration) { - $this->outputFieldSpecification = new FieldSpecification($this->getName(), 'String', $title, null, $alias); + $this->outputFieldSpecification = new FieldSpecification($alias, 'String', $title, null, $alias); $this->contactIdSource = $this->dataProcessor->getDataSourceByName($configuration['contact_id_datasource']); $this->contactIdField = $this->contactIdSource->getAvailableFields()->getFieldSpecificationByName($configuration['contact_id_field']); $this->contactIdSource->ensureFieldInSource($this->contactIdField); @@ -94,7 +85,7 @@ class ContactLinkFieldOutputHandler extends AbstractFieldOutputHandler { $this->contactNameField = $this->contactNameSource->getAvailableFields()->getFieldSpecificationByName($configuration['contact_name_field']); $this->contactNameSource->ensureFieldInSource($this->contactNameField); - //$this->dataSource->ensureFieldInSource($this->inputFieldSpec); + $this->outputFieldSpecification = new FieldSpecification($this->contactIdField->name, 'String', $title, null, $alias); } /** @@ -158,9 +149,6 @@ class ContactLinkFieldOutputHandler extends AbstractFieldOutputHandler { } $form->setDefaults($defaults); } - - // Example add a checkbox to the form. - // $form->add('checkbox', 'show_label', E::ts('Show label')); } /** diff --git a/Civi/DataProcessor/FieldOutputHandler/FileFieldOutputHandler.php b/Civi/DataProcessor/FieldOutputHandler/FileFieldOutputHandler.php index 6479c7907e0cca394d8af6ec47da2d4659147123..ce0c3a56470438189772e7be1c51b83fec3c49f2 100644 --- a/Civi/DataProcessor/FieldOutputHandler/FileFieldOutputHandler.php +++ b/Civi/DataProcessor/FieldOutputHandler/FileFieldOutputHandler.php @@ -11,7 +11,50 @@ use Civi\DataProcessor\Source\SourceInterface; use Civi\DataProcessor\DataSpecification\FieldSpecification; use Civi\DataProcessor\FieldOutputHandler\FieldOutput; -class FileFieldOutputHandler extends AbstractFieldOutputHandler implements OutputHandlerSortable { +class FileFieldOutputHandler extends AbstractFieldOutputHandler { + + /** + * Returns the data type of this field + * + * @return String + */ + protected function getType() { + return 'String'; + } + + /** + * Returns the formatted value + * + * @param $rawRecord + * @param $formattedRecord + * + * @return \Civi\DataProcessor\FieldOutputHandler\FieldOutput + */ + public function formatField($rawRecord, $formattedRecord) { + $rawValue = $rawRecord[$this->inputFieldSpec->alias]; + $output = new FieldOutput($rawValue); + if ($rawValue) { + $attachment = civicrm_api3('Attachment', 'getsingle', array('id' => $rawValue)); + if (!isset($attachment['is_error']) || $attachment['is_error'] == '0') { + $formattedValue = '<a href="' . $attachment['url'] . '">' . $attachment['name'] . '</a>'; + $output->formattedValue = $formattedValue; + } + } + return $output; + } + + /** + * Callback function for determining whether this field could be handled by this output handler. + * + * @param \Civi\DataProcessor\DataSpecification\FieldSpecification $field + * @return bool + */ + public function isFieldValid(FieldSpecification $field) { + if ($field->type == 'File') { + return true; + } + return false; + } /** * @var \Civi\DataProcessor\DataSpecification\FieldSpecification @@ -19,79 +62,109 @@ class FileFieldOutputHandler extends AbstractFieldOutputHandler implements Outpu protected $inputFieldSpec; /** - * @var \Civi\DataProcessor\Source\SourceInterface + * @var \Civi\DataProcessor\DataSpecification\FieldSpecification + */ + protected $outputFieldSpec; + + /** + * @var SourceInterface */ protected $dataSource; - public function __construct(FieldSpecification $inputFieldSpec, SourceInterface $dataSource) { - $this->dataSource = $dataSource; - $this->inputFieldSpec = $inputFieldSpec; - $this->outputFieldSpecification = clone $inputFieldSpec; - $this->outputFieldSpecification->alias = $this->getName(); + /** + * @return \Civi\DataProcessor\DataSpecification\FieldSpecification + */ + public function getOutputFieldSpecification() { + return $this->outputFieldSpec; } /** - * @return \Civi\DataProcessor\DataSpecification\FieldSpecification + * Initialize the processor + * + * @param String $alias + * @param String $title + * @param array $configuration + * @param \Civi\DataProcessor\ProcessorType\AbstractProcessorType $processorType */ - public function getSortableInputFieldSpec() { - return $this->inputFieldSpec; + public function initialize($alias, $title, $configuration) { + $this->dataSource = $this->dataProcessor->getDataSourceByName($configuration['datasource']); + $this->inputFieldSpec = $this->dataSource->getAvailableFields()->getFieldSpecificationByName($configuration['field']); + $this->dataSource->ensureFieldInSource($this->inputFieldSpec); + + $this->outputFieldSpec = clone $this->inputFieldSpec; + $this->outputFieldSpec->alias = $alias; + $this->outputFieldSpec->title = $title; } /** - * Returns the name of the handler type. + * Returns true when this handler has additional configuration. * - * @return String + * @return bool */ - public function getName() { - return 'file_field_'.$this->inputFieldSpec->alias; + public function hasConfiguration() { + return true; } /** - * Returns the data type of this field + * When this handler has additional configuration you can add + * the fields on the form with this function. * - * @return String + * @param \CRM_Core_Form $form + * @param array $field */ - protected function getType() { - return $this->inputFieldSpec->type; + public function buildConfigurationForm(\CRM_Core_Form $form, $field=array()) { + $fieldSelect = $this->getFieldOptions($field['data_processor_id']); + + $form->add('select', 'field', E::ts('Field'), $fieldSelect, true, array( + 'style' => 'min-width:250px', + 'class' => 'crm-select2 huge', + 'placeholder' => E::ts('- select -'), + )); + if (isset($field['configuration'])) { + $configuration = $field['configuration']; + $defaults = array(); + if (isset($configuration['field']) && isset($configuration['datasource'])) { + $defaults['field'] = $configuration['datasource'] . '::' . $configuration['field']; + } + $form->setDefaults($defaults); + } } /** - * Returns the title of this field + * When this handler has configuration specify the template file name + * for the configuration form. * - * @return String + * @return false|string */ - public function getTitle() { - return E::ts('%1 :: %2 (Download link)', array(1 => $this->dataSource->getSourceTitle(), 2 => $this->inputFieldSpec->title)); + public function getConfigurationTemplateFileName() { + return "CRM/Dataprocessor/Form/Field/Configuration/RawFieldOutputHandler.tpl"; } + /** - * Initialize the processor + * Process the submitted values and create a configuration array * - * @param String $alias - * @param String $title - * @param array $configuration - * @param \Civi\DataProcessor\ProcessorType\AbstractProcessorType $processorType + * @param $submittedValues + * @return array */ - public function initialize($alias, $title, $configuration) { - parent::initialize($alias, $title, $configuration); - $this->dataSource->ensureFieldInSource($this->inputFieldSpec); + public function processConfiguration($submittedValues) { + list($datasource, $field) = explode('::', $submittedValues['field'], 2); + $configuration['field'] = $field; + $configuration['datasource'] = $datasource; + return $configuration; } /** - * Returns the formatted value + * Returns all possible fields * - * @param $rawRecord - * @param $formattedRecord + * @param $data_processor_id * - * @return \Civi\DataProcessor\FieldOutputHandler\FieldOutput + * @return array + * @throws \Exception */ - public function formatField($rawRecord, $formattedRecord) { - $rawValue = $rawRecord[$this->inputFieldSpec->alias]; - if ($rawValue) { - $attachment = civicrm_api3('Attachment', 'getsingle', array('id' => $rawValue)); - return new FieldOutput($attachment["url"], $rawValue); - } - return new FieldOutput("", $rawValue); + protected function getFieldOptions($data_processor_id) { + $fieldSelect = \CRM_Dataprocessor_Utils_DataSourceFields::getAvailableFieldsInDataSources($data_processor_id, array($this, 'isFieldValid')); + return $fieldSelect; } diff --git a/Civi/DataProcessor/FieldOutputHandler/OptionFieldOutputHandler.php b/Civi/DataProcessor/FieldOutputHandler/OptionFieldOutputHandler.php index 029f8efa203bae14f38542b352c9dbb055193dd6..90d8df938c17e7683b709da8c589faab9bdf734a 100644 --- a/Civi/DataProcessor/FieldOutputHandler/OptionFieldOutputHandler.php +++ b/Civi/DataProcessor/FieldOutputHandler/OptionFieldOutputHandler.php @@ -11,40 +11,8 @@ use Civi\DataProcessor\Source\SourceInterface; use Civi\DataProcessor\DataSpecification\FieldSpecification; use Civi\DataProcessor\FieldOutputHandler\FieldOutput; -class OptionFieldOutputHandler extends AbstractFieldOutputHandler implements OutputHandlerSortable { +class OptionFieldOutputHandler extends RawFieldOutputHandler { - /** - * @var \Civi\DataProcessor\DataSpecification\FieldSpecification - */ - protected $inputFieldSpec; - - /** - * @var \Civi\DataProcessor\Source\SourceInterface - */ - protected $dataSource; - - public function __construct(FieldSpecification $inputFieldSpec, SourceInterface $dataSource) { - $this->dataSource = $dataSource; - $this->inputFieldSpec = $inputFieldSpec; - $this->outputFieldSpecification = clone $inputFieldSpec; - $this->outputFieldSpecification->alias = $this->getName(); - } - - /** - * @return \Civi\DataProcessor\DataSpecification\FieldSpecification - */ - public function getSortableInputFieldSpec() { - return $this->inputFieldSpec; - } - - /** - * Returns the name of the handler type. - * - * @return String - */ - public function getName() { - return 'option_label_'.$this->inputFieldSpec->alias; - } /** * Returns the data type of this field @@ -52,29 +20,7 @@ class OptionFieldOutputHandler extends AbstractFieldOutputHandler implements Out * @return String */ protected function getType() { - return $this->inputFieldSpec->type; - } - - /** - * Returns the title of this field - * - * @return String - */ - public function getTitle() { - return E::ts('%1 :: %2 (Option)', array(1 => $this->dataSource->getSourceTitle(), 2 => $this->inputFieldSpec->title)); - } - - /** - * Initialize the processor - * - * @param String $alias - * @param String $title - * @param array $configuration - * @param \Civi\DataProcessor\ProcessorType\AbstractProcessorType $processorType - */ - public function initialize($alias, $title, $configuration) { - parent::initialize($alias, $title, $configuration); - $this->dataSource->ensureFieldInSource($this->inputFieldSpec); + return 'String'; } /** @@ -104,5 +50,18 @@ class OptionFieldOutputHandler extends AbstractFieldOutputHandler implements Out return $formattedValue; } + /** + * Callback function for determining whether this field could be handled by this output handler. + * + * @param \Civi\DataProcessor\DataSpecification\FieldSpecification $field + * @return bool + */ + public function isFieldValid(FieldSpecification $field) { + if ($field->getOptions()) { + return true; + } + return false; + } + } \ No newline at end of file diff --git a/Civi/DataProcessor/FieldOutputHandler/RawFieldOutputHandler.php b/Civi/DataProcessor/FieldOutputHandler/RawFieldOutputHandler.php index 43a4dd7b4c16064f1e28760721dca6a440a4c1dd..66b63ddc00bbbb86c9c41cffd4fd0d4812fdac25 100644 --- a/Civi/DataProcessor/FieldOutputHandler/RawFieldOutputHandler.php +++ b/Civi/DataProcessor/FieldOutputHandler/RawFieldOutputHandler.php @@ -17,27 +17,28 @@ class RawFieldOutputHandler extends AbstractFieldOutputHandler implements Output */ protected $inputFieldSpec; - public function __construct(FieldSpecification $inputFieldSpec, SourceInterface $dataSource) { - parent::__construct($dataSource); - $this->inputFieldSpec = $inputFieldSpec; - $this->outputFieldSpecification = clone $inputFieldSpec; - $this->outputFieldSpecification->alias = $this->getName(); - } + /** + * @var \Civi\DataProcessor\DataSpecification\FieldSpecification + */ + protected $outputFieldSpec; + + /** + * @var SourceInterface + */ + protected $dataSource; /** * @return \Civi\DataProcessor\DataSpecification\FieldSpecification */ - public function getSortableInputFieldSpec() { - return $this->inputFieldSpec; + public function getOutputFieldSpecification() { + return $this->outputFieldSpec; } /** - * Returns the name of the handler type. - * - * @return String + * @return \Civi\DataProcessor\DataSpecification\FieldSpecification */ - public function getName() { - return 'raw_'.$this->inputFieldSpec->alias; + public function getSortableInputFieldSpec() { + return $this->inputFieldSpec; } /** @@ -49,15 +50,6 @@ class RawFieldOutputHandler extends AbstractFieldOutputHandler implements Output return $this->inputFieldSpec->type; } - /** - * Returns the title of this field - * - * @return String - */ - public function getTitle() { - return E::ts('%1 :: %2', array(1 => $this->dataSource->getSourceTitle(), 2 => $this->inputFieldSpec->title)); - } - /** * Initialize the processor * @@ -67,8 +59,13 @@ class RawFieldOutputHandler extends AbstractFieldOutputHandler implements Output * @param \Civi\DataProcessor\ProcessorType\AbstractProcessorType $processorType */ public function initialize($alias, $title, $configuration) { - parent::initialize($alias, $title, $configuration); + $this->dataSource = $this->dataProcessor->getDataSourceByName($configuration['datasource']); + $this->inputFieldSpec = $this->dataSource->getAvailableFields()->getFieldSpecificationByName($configuration['field']); $this->dataSource->ensureFieldInSource($this->inputFieldSpec); + + $this->outputFieldSpec = clone $this->inputFieldSpec; + $this->outputFieldSpec->alias = $alias; + $this->outputFieldSpec->title = $title; } /** @@ -83,5 +80,86 @@ class RawFieldOutputHandler extends AbstractFieldOutputHandler implements Output return new FieldOutput($rawRecord[$this->inputFieldSpec->alias]); } + /** + * Returns true when this handler has additional configuration. + * + * @return bool + */ + public function hasConfiguration() { + return true; + } + + /** + * When this handler has additional configuration you can add + * the fields on the form with this function. + * + * @param \CRM_Core_Form $form + * @param array $field + */ + public function buildConfigurationForm(\CRM_Core_Form $form, $field=array()) { + $fieldSelect = $this->getFieldOptions($field['data_processor_id']); + + $form->add('select', 'field', E::ts('Field'), $fieldSelect, true, array( + 'style' => 'min-width:250px', + 'class' => 'crm-select2 huge', + 'placeholder' => E::ts('- select -'), + )); + if (isset($field['configuration'])) { + $configuration = $field['configuration']; + $defaults = array(); + if (isset($configuration['field']) && isset($configuration['datasource'])) { + $defaults['field'] = $configuration['datasource'] . '::' . $configuration['field']; + } + $form->setDefaults($defaults); + } + } + + /** + * When this handler has configuration specify the template file name + * for the configuration form. + * + * @return false|string + */ + public function getConfigurationTemplateFileName() { + return "CRM/Dataprocessor/Form/Field/Configuration/RawFieldOutputHandler.tpl"; + } + + + /** + * Process the submitted values and create a configuration array + * + * @param $submittedValues + * @return array + */ + public function processConfiguration($submittedValues) { + list($datasource, $field) = explode('::', $submittedValues['field'], 2); + $configuration['field'] = $field; + $configuration['datasource'] = $datasource; + return $configuration; + } + + /** + * Returns all possible fields + * + * @param $data_processor_id + * + * @return array + * @throws \Exception + */ + protected function getFieldOptions($data_processor_id) { + $fieldSelect = \CRM_Dataprocessor_Utils_DataSourceFields::getAvailableFieldsInDataSources($data_processor_id, array($this, 'isFieldValid')); + return $fieldSelect; + } + + /** + * Callback function for determining whether this field could be handled by this output handler. + * + * @param \Civi\DataProcessor\DataSpecification\FieldSpecification $field + * @return bool + */ + public function isFieldValid(FieldSpecification $field) { + return true; + } + } \ No newline at end of file diff --git a/Civi/DataProcessor/FilterHandler/SimpleSqlFilter.php b/Civi/DataProcessor/FilterHandler/SimpleSqlFilter.php index 7acad43ddec5b3a18c1e0352fd796c94e79871a7..a16ac2017abb8251e08ac680dd583f91caa7c432 100644 --- a/Civi/DataProcessor/FilterHandler/SimpleSqlFilter.php +++ b/Civi/DataProcessor/FilterHandler/SimpleSqlFilter.php @@ -108,7 +108,7 @@ class SimpleSqlFilter extends AbstractFilterHandler { * @param array $filter */ public function buildConfigurationForm(\CRM_Core_Form $form, $filter=array()) { - $fieldSelect = \CRM_Dataprocessor_Utils_DataSourceFields::getAvailableFieldsInDataSources($filter['data_processor_id']); + $fieldSelect = \CRM_Dataprocessor_Utils_DataSourceFields::getAvailableFilterFieldsInDataSources($filter['data_processor_id']); $form->add('select', 'field', E::ts('Field'), $fieldSelect, true, array( 'style' => 'min-width:250px', diff --git a/Civi/DataProcessor/ProcessorType/AbstractProcessorType.php b/Civi/DataProcessor/ProcessorType/AbstractProcessorType.php index 9c3eba4b55e0d3f333930c657d1c2b2d325283e1..4206e5e6e2c463561eb8279ac820c18f9129c640 100644 --- a/Civi/DataProcessor/ProcessorType/AbstractProcessorType.php +++ b/Civi/DataProcessor/ProcessorType/AbstractProcessorType.php @@ -16,7 +16,6 @@ use Civi\DataProcessor\DataFlow\SqlDataFlow; use Civi\DataProcessor\DataSpecification\FieldSpecification; use Civi\DataProcessor\Event\OutputHandlerEvent; use Civi\DataProcessor\FieldOutputHandler\AbstractFieldOutputHandler; -use Civi\DataProcessor\FieldOutputHandler\ContactLinkFieldOutputHandler; use Civi\DataProcessor\FilterHandler\AbstractFilterHandler; use Civi\DataProcessor\Storage\StorageInterface; @@ -108,29 +107,6 @@ abstract class AbstractProcessorType { return null; } - /** - * @return \Civi\DataProcessor\FieldOutputHandler\AbstractFieldOutputHandler[] - */ - public function getAvailableOutputHandlers() { - $dispatcher = \Civi::dispatcher(); - $factory = dataprocessor_get_factory(); - $handlers = array(); - foreach($this->dataSources as $dataSource) { - foreach($dataSource['datasource']->getAvailableFields()->getFields() as $field) { - $fieldHandlers = $factory->getOutputHandlers($field, $dataSource['datasource']); - $handlers = array_merge($handlers, $fieldHandlers); - } - } - - $handlers['contact_link'] = new ContactLinkFieldOutputHandler($this); - - $event = new OutputHandlerEvent($this); - $event->handlers = $handlers; - $dispatcher->dispatch(OutputHandlerEvent::NAME, $event); - - return $handlers; - } - /** * @param \Civi\DataProcessor\FieldOutputHandler\AbstractFieldOutputHandler $outputFieldHandler */ diff --git a/api/v3/DataProcessor.mgd.php b/api/DataProcessor.mgd.php similarity index 100% rename from api/v3/DataProcessor.mgd.php rename to api/DataProcessor.mgd.php diff --git a/api/v3/DataProcessorField.php b/api/v3/DataProcessorField.php index 725553296453d65826c44540257eb2ad32856df6..d9d56258e54132fceb022a636d8254b42226b603 100644 --- a/api/v3/DataProcessorField.php +++ b/api/v3/DataProcessorField.php @@ -132,3 +132,47 @@ function civicrm_api3_data_processor_field_check_name($params) { 'name' => $name, ); } + +function civicrm_api3_data_processor_field_correct_field_configuration($params) { + $return = array(); + $fields = CRM_COre_DAO::executeQuery("SELECT * FROM civicrm_data_processor_field"); + $dataProcessors = array(); + while($fields->fetch()) { + if (!isset($dataProcessors[$fields->data_processor_id])) { + $dataProcessors[$fields->data_processor_id] = civicrm_api3('DataProcessor', 'getsingle', array('id' => $fields->data_processor_id)); + } + $dataProcessor = CRM_Dataprocessor_BAO_DataProcessor::dataProcessorToClass($dataProcessors[$fields->data_processor_id]); + foreach($dataProcessor->getDataSources() as $dataSource) { + foreach($dataSource->getAvailableFields()->getFields() as $dataSourceField) { + // Check fields for type raw_... or option_label_.... or file_... + // and change their type to raw, option_label or file + // and set the right configuration. + $newType = false; + $configuration = false; + if ($fields->type == 'raw_'.$dataSourceField->alias) { + $configuration = array('field' => $dataSourceField->name, 'datasource' => $dataSource->getSourceName()); + $newType = 'raw'; + } elseif ($fields->type == 'option_label_'.$dataSourceField->alias) { + $configuration = array('field' => $dataSourceField->name, 'datasource' => $dataSource->getSourceName()); + $newType = 'option_label'; + } elseif ($fields->type == 'file_field_'.$dataSourceField->alias) { + $configuration = array('field' => $dataSourceField->name, 'datasource' => $dataSource->getSourceName()); + $newType = 'file_field'; + } + + if ($newType) { + CRM_Core_DAO::executeQuery("UPDATE civicrm_data_processor_field SET `type` = 'raw', `configuration` = %1 WHERE id = %2", array( + 1 => array(json_encode($configuration), 'String'), + 2 => array($fields->id, 'Integer') + )); + $return[$fields->id] = array( + 'original_type' => $fields->type, + 'type' => $newType, + 'configuration' => $configuration, + ); + } + } + } + } + return civicrm_api3_create_success($return); +} diff --git a/templates/CRM/Dataprocessor/Form/Field/Configuration/RawFieldOutputHandler.tpl b/templates/CRM/Dataprocessor/Form/Field/Configuration/RawFieldOutputHandler.tpl new file mode 100644 index 0000000000000000000000000000000000000000..be2a8b6548d018f42c3a39884eac52f6b8e02ea1 --- /dev/null +++ b/templates/CRM/Dataprocessor/Form/Field/Configuration/RawFieldOutputHandler.tpl @@ -0,0 +1,7 @@ +{crmScope extensionKey='dataprocessor'} + <div class="crm-section"> + <div class="label">{$form.field.label}</div> + <div class="content">{$form.field.html}</div> + <div class="clear"></div> + </div> +{/crmScope} \ No newline at end of file diff --git a/templates/CRM/DataprocessorSearch/Form/Search.tpl b/templates/CRM/DataprocessorSearch/Form/Search.tpl index ac0838b0617a62a452001d63a7a2e98fe5b9ed19..ee795c9be19988b1ca89389374ece6350d938387 100644 --- a/templates/CRM/DataprocessorSearch/Form/Search.tpl +++ b/templates/CRM/DataprocessorSearch/Form/Search.tpl @@ -28,7 +28,11 @@ <th scope="col" title="Select Rows">{$form.toggleSelect.html}</th> {foreach from=$columnHeaders key=headerName item=headerTitle} <th scope="col"> - {$sort->_response.$headerName.link} + {if ($sort->_response.$headerName)} + {$sort->_response.$headerName.link} + {else} + {$headerTitle} + {/if} </th> {/foreach} <th scope="col"></th>