diff --git a/CRM/DataprocessorSearch/ActivitySearch.php b/CRM/DataprocessorSearch/ActivitySearch.php new file mode 100644 index 0000000000000000000000000000000000000000..43678f4a414067a2817f73c59e7c3afd9fe91fc4 --- /dev/null +++ b/CRM/DataprocessorSearch/ActivitySearch.php @@ -0,0 +1,40 @@ +<?php +/** + * @author Jaap Jansma <jaap.jansma@civicoop.org> + * @license AGPL-3.0 + */ + +use Civi\DataProcessor\Output\OutputInterface; + +class CRM_DataprocessorSearch_ActivitySearch implements OutputInterface, CRM_DataprocessorSearch_SearchInterface { + + /** + * Return the url to a configuration page. + * Or return false when no configuration page exists. + * + * @return string|false + */ + public function getConfigurationUrl() { + return 'civicrm/dataprocessor/form/output/activity_search'; + } + + /** + * Returns the url for the search + * + * @param \CRM_Dataprocessor_BAO_Output $output + * @param $dataProcessor + * + * @return string + */ + public function getSearchUrl($output, $dataProcessor) { + return "civicrm/dataprocessor_activity_search/{$dataProcessor['name']}"; + } + + /** + * @return string + */ + public function getSearchControllerClass() { + return 'CRM_DataprocessorSearch_Controller_ActivitySearch'; + } + +} \ No newline at end of file diff --git a/CRM/DataprocessorSearch/ContactSearch.php b/CRM/DataprocessorSearch/ContactSearch.php new file mode 100644 index 0000000000000000000000000000000000000000..f9bd918b760275df7fd0547e605fe09ab936dca6 --- /dev/null +++ b/CRM/DataprocessorSearch/ContactSearch.php @@ -0,0 +1,40 @@ +<?php +/** + * @author Jaap Jansma <jaap.jansma@civicoop.org> + * @license AGPL-3.0 + */ + +use Civi\DataProcessor\Output\OutputInterface; + +class CRM_DataprocessorSearch_ContactSearch implements OutputInterface, CRM_DataprocessorSearch_SearchInterface { + + /** + * Return the url to a configuration page. + * Or return false when no configuration page exists. + * + * @return string|false + */ + public function getConfigurationUrl() { + return 'civicrm/dataprocessor/form/output/contact_search'; + } + + /** + * Returns the url for the search + * + * @param \CRM_Dataprocessor_BAO_Output $output + * @param $dataProcessor + * + * @return string + */ + public function getSearchUrl($output, $dataProcessor) { + return "civicrm/dataprocessor_contact_search/{$dataProcessor['name']}"; + } + + /** + * @return string + */ + public function getSearchControllerClass() { + return 'CRM_DataprocessorSearch_Controller_ContactSearch'; + } + +} \ No newline at end of file diff --git a/CRM/DataprocessorSearch/Controller/ActivitySearch.php b/CRM/DataprocessorSearch/Controller/ActivitySearch.php new file mode 100644 index 0000000000000000000000000000000000000000..bced16f74e7c679cc578a1780ccb6dd3a85de864 --- /dev/null +++ b/CRM/DataprocessorSearch/Controller/ActivitySearch.php @@ -0,0 +1,79 @@ +<?php +/** + * @author Jaap Jansma <jaap.jansma@civicoop.org> + * @license AGPL-3.0 + */ + +/** + * This class is used by the Search functionality. + * + * - the search controller is used for building/processing multiform + * searches. + * + * Typically the first form will display the search criteria and it's results + * + * The second form is used to process search results with the associated actions. + */ +class CRM_DataprocessorSearch_Controller_ActivitySearch extends CRM_Core_Controller { + + /** + * Class constructor. + * + * @param string $title + * @param bool $modal + * @param int|mixed|null $action + */ + public function __construct($title = NULL, $modal = TRUE, $action = CRM_Core_Action::NONE) { + parent::__construct($title, $modal); + + $this->set('component_mode', CRM_Contact_BAO_Query::MODE_ACTIVITY); + $this->_stateMachine = new CRM_DataprocessorSearch_StateMachine_ActivitySearch($this, $action); + + // create and instantiate the pages + $this->addPages($this->_stateMachine, $action); + + // add all the actions + $this->addActions(); + } + + /** + * Process the request, overrides the default QFC run method + * This routine actually checks if the QFC is modal and if it + * is the first invalid page, if so it call the requested action + * if not, it calls the display action on the first invalid page + * avoids the issue of users hitting the back button and getting + * a broken page + * + * This run is basically a composition of the original run and the + * jump action + * + * @return mixed + */ + public function run() { + + $actionName = $this->getActionName(); + list($pageName, $action) = $actionName; + // Hack to replace to userContext for redirecting after a Task has been completed. + // We want the redirect + if (!$this->_pages[$pageName] instanceof CRM_DataprocessorSearch_Form_ActivitySearch) { + $session = CRM_Core_Session::singleton(); + $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String', $this); + $urlPath = CRM_Utils_System::getUrlPath(); + $urlParams = 'force=1'; + if ($qfKey) { + $urlParams .= "&qfKey=$qfKey"; + } + $this->setDestination(CRM_Utils_System::url($urlPath, $urlParams)); + } + + return parent::run(); + } + + /** + * @return mixed + */ + public function selectorName() { + return $this->get('selectorName'); + } + +} diff --git a/CRM/DataprocessorSearch/Controller/Search.php b/CRM/DataprocessorSearch/Controller/ContactSearch.php similarity index 93% rename from CRM/DataprocessorSearch/Controller/Search.php rename to CRM/DataprocessorSearch/Controller/ContactSearch.php index 12ef143e329effe6516d6b379c1e6e6781ed36d1..362ed26a16610d577f921f9205e73519d28abea8 100644 --- a/CRM/DataprocessorSearch/Controller/Search.php +++ b/CRM/DataprocessorSearch/Controller/ContactSearch.php @@ -14,7 +14,7 @@ * * The second form is used to process search results with the associated actions. */ -class CRM_DataprocessorSearch_Controller_Search extends CRM_Core_Controller { +class CRM_DataprocessorSearch_Controller_ContactSearch extends CRM_Core_Controller { /** * Class constructor. @@ -26,7 +26,7 @@ class CRM_DataprocessorSearch_Controller_Search extends CRM_Core_Controller { public function __construct($title = NULL, $modal = TRUE, $action = CRM_Core_Action::NONE) { parent::__construct($title, $modal); - $this->_stateMachine = new CRM_DataprocessorSearch_StateMachine_Search($this, $action); + $this->_stateMachine = new CRM_DataprocessorSearch_StateMachine_ContactSearch($this, $action); // create and instantiate the pages $this->addPages($this->_stateMachine, $action); @@ -54,7 +54,7 @@ class CRM_DataprocessorSearch_Controller_Search extends CRM_Core_Controller { list($pageName, $action) = $actionName; // Hack to replace to userContext for redirecting after a Task has been completed. // We want the redirect - if (!$this->_pages[$pageName] instanceof CRM_DataprocessorSearch_Form_Search) { + if (!$this->_pages[$pageName] instanceof CRM_DataprocessorSearch_Form_ContactSearch) { $session = CRM_Core_Session::singleton(); $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String', $this); $urlPath = CRM_Utils_System::getUrlPath(); diff --git a/CRM/DataprocessorSearch/Form/Search.php b/CRM/DataprocessorSearch/Form/AbstractSearch.php similarity index 77% rename from CRM/DataprocessorSearch/Form/Search.php rename to CRM/DataprocessorSearch/Form/AbstractSearch.php index cbdbe375f9169c53d340b021688f63dece991edc..2fa5c45b5ba853699d0f9e8667aa1261d6dd8547 100644 --- a/CRM/DataprocessorSearch/Form/Search.php +++ b/CRM/DataprocessorSearch/Form/AbstractSearch.php @@ -6,24 +6,41 @@ use CRM_Dataprocessor_ExtensionUtil as E; -class CRM_DataprocessorSearch_Form_Search extends CRM_Core_Form_Search { +abstract class CRM_DataprocessorSearch_Form_AbstractSearch extends CRM_Core_Form_Search { /** * @var \Civi\DataProcessor\ProcessorType\AbstractProcessorType; */ protected $dataProcessor; + /** + * @var int + */ protected $dataProcessorId; + /** + * @var String + */ + protected $title; + /** * @var \CRM_Dataprocessor_BAO_Output */ protected $dataProcessorOutput; + /** + * @var int + */ protected $limit; + /** + * @var int + */ protected $pageId; + /** + * @var bool + */ protected $_debug = FALSE; /** @@ -31,8 +48,84 @@ class CRM_DataprocessorSearch_Form_Search extends CRM_Core_Form_Search { */ protected $sort; + /** + * @var bool + */ protected $formHasRequiredFilters = FALSE; + /** + * Checks whether the output has a valid configuration + * + * @return bool + */ + abstract protected function isConfigurationValid(); + + /** + * Return the data processor ID + * + * @return String + */ + abstract protected function getDataProcessorName(); + + /** + * Returns the name of the output for this search + * + * @return string + */ + abstract protected function getOutputName(); + + /** + * Returns the name of the ID field in the dataset. + * + * @return string + */ + abstract protected function getIdFieldName(); + + /** + * @return string + */ + abstract protected function getEntityTable(); + + /** + * Builds the list of tasks or actions that a searcher can perform on a result set. + * + * @return array + */ + public function buildTaskList() { + return $this->_taskList; + } + + /** + * Returns whether we want to use the prevnext cache. + * @return bool + */ + protected function usePrevNextCache() { + return false; + } + + /** + * Returns whether the ID field is Visible + * + * @return bool + */ + protected function isIdFieldVisible() { + if (isset($this->dataProcessorOutput['configuration']['hide_id_field']) && $this->dataProcessorOutput['configuration']['hide_id_field']) { + return false; + } + return true; + } + + /** + * Return altered rows + * + * @param array $rows + * @param array $ids + * + */ + protected function alterRows(&$rows, $ids) { + + } + public function preProcess() { parent::preProcess(); @@ -62,7 +155,7 @@ class CRM_DataprocessorSearch_Form_Search extends CRM_Core_Form_Search { $pageId = CRM_Utils_Request::retrieve('crmPID', 'Positive', $this, FALSE, 1); $this->addColumnHeaders(); - $this->findRows($pageId, $limit); + $this->buildRows($pageId, $limit); } } @@ -73,27 +166,30 @@ class CRM_DataprocessorSearch_Form_Search extends CRM_Core_Form_Search { * @throws \Exception */ protected function findDataProcessor() { - $dataProcessorId = str_replace('civicrm/dataprocessor_search/', '', CRM_Utils_System::getUrlPath()); - $sql = " - SELECT civicrm_data_processor.id as data_processor_id, civicrm_data_processor_output.id AS output_id - FROM civicrm_data_processor - INNER JOIN civicrm_data_processor_output ON civicrm_data_processor.id = civicrm_data_processor_output.data_processor_id - WHERE is_active = 1 AND civicrm_data_processor.id = %1 AND civicrm_data_processor_output.type = 'search' - "; - $params[1] = array($dataProcessorId, 'Integer'); - $dao = CRM_Dataprocessor_BAO_DataProcessor::executeQuery($sql, $params, TRUE, 'CRM_Dataprocessor_BAO_DataProcessor'); - if (!$dao->fetch()) { - throw new \Exception('Could not find Data Processor with id '.$dataProcessorId); - } - $this->dataProcessor = CRM_Dataprocessor_BAO_DataProcessor::getDataProcessorById($dao->data_processor_id); + if (!$this->dataProcessorId) { + $dataProcessorName = $this->getDataProcessorName(); + $sql = " + SELECT civicrm_data_processor.id as data_processor_id, civicrm_data_processor_output.id AS output_id + FROM civicrm_data_processor + INNER JOIN civicrm_data_processor_output ON civicrm_data_processor.id = civicrm_data_processor_output.data_processor_id + WHERE is_active = 1 AND civicrm_data_processor.name = %1 AND civicrm_data_processor_output.type = %2 + "; + $params[1] = [$dataProcessorName, 'String']; + $params[2] = [$this->getOutputName(), 'String']; + $dao = CRM_Dataprocessor_BAO_DataProcessor::executeQuery($sql, $params, TRUE, 'CRM_Dataprocessor_BAO_DataProcessor'); + if (!$dao->fetch()) { + throw new \Exception('Could not find Data Processor "' . $dataProcessorName.'"'); + } + $this->dataProcessor = CRM_Dataprocessor_BAO_DataProcessor::getDataProcessorById($dao->data_processor_id); + $this->dataProcessorId = $dao->data_processor_id; - $output = CRM_Dataprocessor_BAO_Output::getValues(array('id' => $dao->output_id)); - $this->dataProcessorOutput = $output[$dao->output_id]; + $output = CRM_Dataprocessor_BAO_Output::getValues(['id' => $dao->output_id]); + $this->dataProcessorOutput = $output[$dao->output_id]; - if (!isset($this->dataProcessorOutput['configuration']['contact_id_field'])) { - throw new \Exception('Invalid configuration found for the Search output of the data processor (id = '.$dataProcessorId.')'); + if (!$this->isConfigurationValid()) { + throw new \Exception('Invalid configuration found for the Search output of the data processor "' . $dataProcessorName . '"'); + } } - } /** @@ -104,9 +200,9 @@ class CRM_DataprocessorSearch_Form_Search extends CRM_Core_Form_Search { * * @throws \Civi\DataProcessor\DataFlow\InvalidFlowException */ - protected function findRows($pageId, $limit) { + protected function buildRows($pageId, $limit) { $rows = []; - $contact_ids = array(); + $ids = array(); $prevnextData = array(); $offset = ($pageId - 1) * $limit; @@ -131,47 +227,39 @@ class CRM_DataprocessorSearch_Form_Search extends CRM_Core_Form_Search { $this->pager = new CRM_Utils_Pager($pagerParams); $this->assign('pager', $this->pager); - $contact_id_field = $this->dataProcessorOutput['configuration']['contact_id_field']; - $this->assign('contact_id_field', $contact_id_field); + $id_field = $this->getIdFieldName(); + $this->assign('id_field', $id_field); try { while($record = $this->dataProcessor->getDataFlow()->nextRecord()) { $row = array(); - $row['contact_id'] = $record[$contact_id_field]->formattedValue; - $row['checkbox'] = CRM_Core_Form::CB_PREFIX.$row['contact_id']; + $row['id'] = $record[$id_field]->formattedValue; + $row['checkbox'] = CRM_Core_Form::CB_PREFIX.$row['id']; $row['record'] = $record; $this->addElement('checkbox', $row['checkbox'], NULL, NULL, ['class' => 'select-row']); $prevnextData[] = array( - 'entity_id1' => $row['contact_id'], + 'entity_id1' => $row['id'], + 'entity_table' => $this->getEntityTable(), 'data' => $record, ); - $contact_ids[] = $row['contact_id']; + $ids[] = $row['id']; - $rows[$row['contact_id']] = $row; + $rows[$row['id']] = $row; } } catch (\Civi\DataProcessor\DataFlow\EndOfFlowException $e) { // Do nothing } - // Add the contact type image - if (count($contact_ids)) { - $contactDao = CRM_Core_DAO::executeQuery("SELECT id, contact_type, contact_sub_type FROM civicrm_contact WHERE `id` IN (".implode(",", $contact_ids).")"); - while($contactDao->fetch()) { - $rows[$contactDao->id]['contact_type'] = CRM_Contact_BAO_Contact_Utils::getImage($contactDao->contact_sub_type ? $contactDao->contact_sub_type : $contactDao->contact_type, - FALSE, - $contactDao->id - ); - } - } + $this->alterRows($rows, $ids); $this->addElement('checkbox', 'toggleSelect', NULL, NULL, ['class' => 'select-rows']); - - $cacheKey = "civicrm search {$this->controller->_key}"; - Civi::service('prevnext')->fillWithArray($cacheKey, $prevnextData); $this->assign('rows', $rows); - $this->assign('debug_info', $this->dataProcessor->getDataFlow()->getDebugInformation()); + if ($this->usePrevNextCache()) { + $cacheKey = "civicrm search {$this->controller->_key}"; + CRM_DataprocessorSearch_Utils_PrevNextCache::fillWithArray($cacheKey, $prevnextData); + } } /** @@ -317,12 +405,19 @@ class CRM_DataprocessorSearch_Form_Search extends CRM_Core_Form_Search { */ protected function addColumnHeaders() { $sortFields = array(); - $contact_id_field = $this->dataProcessorOutput['configuration']['contact_id_field']; + $id_field = $this->getIdFieldName(); + $idFieldVisible = $this->isIdFieldVisible(); $columnHeaders = array(); $sortColumnNr = 1; foreach($this->dataProcessor->getDataFlow()->getOutputFieldHandlers() as $outputFieldHandler) { $field = $outputFieldHandler->getOutputFieldSpecification(); - if ($field->alias != $contact_id_field) { + $hiddenField = true; + if ($field->alias != $id_field) { + $hiddenField = false; + } elseif ($field->alias == $id_field && $idFieldVisible) { + $hiddenField = false; + } + if (!$hiddenField) { $columnHeaders[$field->alias] = $field->title; $sortFields[$sortColumnNr] = array( 'name' => $field->title, @@ -338,6 +433,9 @@ class CRM_DataprocessorSearch_Form_Search extends CRM_Core_Form_Search { $this->assign_by_ref('sort', $this->sort); } + /** + * Build the criteria form + */ protected function buildCriteriaForm() { $count = 1; $filterElements = array(); @@ -452,17 +550,17 @@ class CRM_DataprocessorSearch_Form_Search extends CRM_Core_Form_Search { $this->buildCriteriaForm(); - $selectedContactIds = array(); + $selectedIds = array(); $qfKeyParam = CRM_Utils_Array::value('qfKey', $this->_formValues); // We use ajax to handle selections only if the search results component_mode is set to "contacts" - if ($qfKeyParam) { + if ($qfKeyParam && $this->usePrevNextCache()) { $this->addClass('crm-ajax-selection-form'); - $qfKeyParam = "civicrm search {$qfKeyParam}"; - $selectedContactIdsArr = Civi::service('prevnext')->getSelection($qfKeyParam); - $selectedContactIds = array_keys($selectedContactIdsArr[$qfKeyParam]); + $qfKeyParam = "civicrm search {$qfKeyParam}"; + $selectedIdsArr = CRM_DataprocessorSearch_Utils_PrevNextCache::getSelection($qfKeyParam); + $selectedIds = array_keys($selectedIdsArr[$qfKeyParam]); } - $this->assign_by_ref('selectedContactIds', $selectedContactIds); + $this->assign_by_ref('selectedIds', $selectedIds); $this->add('hidden', 'context'); $this->add('hidden', CRM_Utils_Sort::SORT_ID); } @@ -476,17 +574,6 @@ class CRM_DataprocessorSearch_Form_Search extends CRM_Core_Form_Search { return $defaults; } - /** - * Builds the list of tasks or actions that a searcher can perform on a result set. - * - * @return array - */ - public function buildTaskList() { - $taskParams['deletedContacts'] = FALSE; - $this->_taskList += CRM_Contact_Task::permissionedTaskTitles(CRM_Core_Permission::getPermission(), $taskParams); - return $this->_taskList; - } - public function postProcess() { $values = $this->exportValues(); if ($this->_done) { @@ -502,7 +589,7 @@ class CRM_DataprocessorSearch_Form_Search extends CRM_Core_Form_Search { ) { //reset the cache table for new search $cacheKey = "civicrm search {$this->controller->_key}"; - Civi::service('prevnext')->deleteItem(NULL, $cacheKey); + CRM_DataprocessorSearch_Utils_PrevNextCache::deleteItem(NULL, $cacheKey); } if (!empty($_POST)) { @@ -513,10 +600,20 @@ class CRM_DataprocessorSearch_Form_Search extends CRM_Core_Form_Search { if ($buttonName == $this->_actionButtonName) { // check actionName and if next, then do not repeat a search, since we are going to the next page // hack, make sure we reset the task values - $stateMachine = $this->controller->getStateMachine(); - $formName = $stateMachine->getTaskFormName(); + $formName = $this->controller->getStateMachine()->getTaskFormName(); $this->controller->resetPage($formName); return; } } + + /** + * Return a descriptive name for the page, used in wizard header + * + * @return string + */ + public function getTitle() { + $this->findDataProcessor(); + return $this->dataProcessorOutput['configuration']['title']; + } + } \ No newline at end of file diff --git a/CRM/DataprocessorSearch/Form/ActivitySearch.php b/CRM/DataprocessorSearch/Form/ActivitySearch.php new file mode 100644 index 0000000000000000000000000000000000000000..456709d9f0cf4a2e58b1ab3c9dc5f783c3a77f3e --- /dev/null +++ b/CRM/DataprocessorSearch/Form/ActivitySearch.php @@ -0,0 +1,70 @@ +<?php +/** + * @author Jaap Jansma <jaap.jansma@civicoop.org> + * @license AGPL-3.0 + */ + +use CRM_Dataprocessor_ExtensionUtil as E; + +class CRM_DataprocessorSearch_Form_ActivitySearch extends CRM_DataprocessorSearch_Form_AbstractSearch { + + /** + * Return the data processor name + * + * @return String + */ + protected function getDataProcessorName() { + $dataProcessorName = str_replace('civicrm/dataprocessor_activity_search/', '', CRM_Utils_System::getUrlPath()); + return $dataProcessorName; + } + + /** + * Returns the name of the output for this search + * + * @return string + */ + protected function getOutputName() { + return 'activity_search'; + } + + /** + * Checks whether the output has a valid configuration + * + * @return bool + */ + protected function isConfigurationValid() { + if (!isset($this->dataProcessorOutput['configuration']['activity_id_field'])) { + return false; + } + return true; + } + + /** + * Returns the name of the ID field in the dataset. + * + * @return string + */ + protected function getIdFieldName() { + return $this->dataProcessorOutput['configuration']['activity_id_field']; + } + + /** + * @return string + */ + protected function getEntityTable() { + return 'civicrm_activity'; + } + + /** + * Builds the list of tasks or actions that a searcher can perform on a result set. + * + * @return array + */ + public function buildTaskList() { + if (!$this->_taskList) { + $this->_taskList = CRM_Activity_Task::permissionedTaskTitles(CRM_Core_Permission::getPermission()); + } + return $this->_taskList; + } + +} \ No newline at end of file diff --git a/CRM/DataprocessorSearch/Form/ContactSearch.php b/CRM/DataprocessorSearch/Form/ContactSearch.php new file mode 100644 index 0000000000000000000000000000000000000000..0a12d2795094a80eeb2e79031a1cac1be51e6f7e --- /dev/null +++ b/CRM/DataprocessorSearch/Form/ContactSearch.php @@ -0,0 +1,99 @@ +<?php +/** + * @author Jaap Jansma <jaap.jansma@civicoop.org> + * @license AGPL-3.0 + */ + +use CRM_Dataprocessor_ExtensionUtil as E; + +class CRM_DataprocessorSearch_Form_ContactSearch extends CRM_DataprocessorSearch_Form_AbstractSearch { + + /** + * Checks whether the output has a valid configuration + * + * @return bool + */ + protected function isConfigurationValid() { + if (!isset($this->dataProcessorOutput['configuration']['contact_id_field'])) { + return false; + } + return true; + } + + /** + * Return the data processor ID + * + * @return String + */ + protected function getDataProcessorName() { + $dataProcessorName = str_replace('civicrm/dataprocessor_contact_search/', '', CRM_Utils_System::getUrlPath()); + return $dataProcessorName; + } + + /** + * Returns the name of the output for this search + * + * @return string + */ + protected function getOutputName() { + return 'contact_search'; + } + + /** + * Returns the name of the ID field in the dataset. + * + * @return string + */ + protected function getIdFieldName() { + return $this->dataProcessorOutput['configuration']['contact_id_field']; + } + + /** + * @return string + */ + protected function getEntityTable() { + return 'civicrm_contact'; + } + + /** + * Returns whether we want to use the prevnext cache. + * @return bool + */ + protected function usePrevNextCache() { + return true; + } + + /** + * Return altered rows + * + * @param array $rows + * @param array $ids + * + */ + protected function alterRows(&$rows, $ids) { + // Add the contact type image + if (count($ids)) { + $contactDao = CRM_Core_DAO::executeQuery("SELECT id, contact_type, contact_sub_type FROM civicrm_contact WHERE `id` IN (".implode(",", $ids).")"); + while($contactDao->fetch()) { + $rows[$contactDao->id]['contact_type'] = CRM_Contact_BAO_Contact_Utils::getImage($contactDao->contact_sub_type ? $contactDao->contact_sub_type : $contactDao->contact_type, + FALSE, + $contactDao->id + ); + } + } + } + + /** + * Builds the list of tasks or actions that a searcher can perform on a result set. + * + * @return array + */ + public function buildTaskList() { + if (!$this->_taskList) { + $taskParams['deletedContacts'] = FALSE; + $this->_taskList = CRM_Contact_Task::permissionedTaskTitles(CRM_Core_Permission::getPermission(), $taskParams); + } + return $this->_taskList; + } + +} \ No newline at end of file diff --git a/CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.php b/CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.php new file mode 100644 index 0000000000000000000000000000000000000000..ad27c8421b79702859ec6c30368d45878f7bebaa --- /dev/null +++ b/CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.php @@ -0,0 +1,108 @@ +<?php + +use CRM_Dataprocessor_ExtensionUtil as E; + +/** + * Form controller class + * + * @see https://wiki.civicrm.org/confluence/display/CRMDOC/QuickForm+Reference + */ +class CRM_DataprocessorSearch_Form_OutputConfiguration_ActivitySearch extends CRM_Dataprocessor_Form_Output_AbstractOutputForm { + + /** + * @var CRM_DataprocessorSearch_Utils_Navigation + */ + protected $navigation; + + public function preProcess() { + parent::preProcess(); + $this->navigation = CRM_DataprocessorSearch_Utils_Navigation::singleton(); + } + + public function buildQuickForm() { + parent::buildQuickForm(); + + $dataProcessor = CRM_Dataprocessor_BAO_DataProcessor::getDataProcessorById($this->dataProcessorId); + $fields = array(); + foreach($dataProcessor->getDataFlow()->getOutputFieldHandlers() as $outputFieldHandler) { + $field = $outputFieldHandler->getOutputFieldSpecification(); + $fields[$field->alias] = $field->title; + } + + $this->add('text', 'title', E::ts('Title'), true); + + $this->add('select','permission', E::ts('Permission'), CRM_Core_Permission::basicPermissions(), true, array( + 'style' => 'min-width:250px', + 'class' => 'crm-select2 huge', + 'placeholder' => E::ts('- select -'), + )); + $this->add('select', 'activity_id_field', E::ts('Activity ID field'), $fields, true, array( + 'style' => 'min-width:250px', + 'class' => 'crm-select2 huge', + 'placeholder' => E::ts('- select -'), + )); + $this->add('select', 'hide_id_field', E::ts('Show Activity ID field'), array(0=>'Activity ID is Visible', 1=> 'Activity ID is hidden')); + + // navigation field + $navigationOptions = $this->navigation->getNavigationOptions(); + if (isset($this->output['configuration']['navigation_id'])) { + $navigationPath = $this->navigation->getNavigationPathById($this->output['configuration']['navigation_id']); + unset($navigationOptions[$navigationPath]); + } + $this->add('select', 'navigation_parent_path', ts('Parent Menu'), array('' => ts('- select -')) + $navigationOptions, true); + } + + function setDefaultValues() { + $dataProcessors = CRM_Dataprocessor_BAO_DataProcessor::getValues(array('id' => $this->dataProcessorId)); + $dataProcessor = $dataProcessors[$this->dataProcessorId]; + + $defaults = parent::setDefaultValues(); + if ($this->output) { + if (isset($this->output['permission'])) { + $defaults['permission'] = $this->output['permission']; + } + if (isset($this->output['configuration']) && is_array($this->output['configuration'])) { + if (isset($this->output['configuration']['activity_id_field'])) { + $defaults['activity_id_field'] = $this->output['configuration']['activity_id_field']; + } + if (isset($this->output['configuration']['navigation_id'])) { + $defaults['navigation_parent_path'] = $this->navigation->getNavigationParentPathById($this->output['configuration']['navigation_id']); + } + if (isset($this->output['configuration']['title'])) { + $defaults['title'] = $this->output['configuration']['title']; + } + if (isset($this->output['configuration']['hide_id_field'])) { + $defaults['hide_id_field'] = $this->output['configuration']['hide_id_field']; + } + } + } + if (!isset($defaults['permission'])) { + $defaults['permission'] = 'access CiviCRM'; + } + if (empty($defaults['title'])) { + $defaults['title'] = $dataProcessor['title']; + } + + return $defaults; + } + + public function postProcess() { + $values = $this->exportValues(); + + $session = CRM_Core_Session::singleton(); + $redirectUrl = $session->readUserContext(); + + $params['id'] = $this->id; + $params['permission'] = $values['permission']; + $params['configuration']['title'] = $values['title']; + $params['configuration']['activity_id_field'] = $values['activity_id_field']; + $params['configuration']['navigation_parent_path'] = $values['navigation_parent_path']; + $params['configuration']['hide_id_field'] = $values['hide_id_field']; + + CRM_Dataprocessor_BAO_Output::add($params); + + CRM_Utils_System::redirect($redirectUrl); + parent::postProcess(); + } + +} \ No newline at end of file diff --git a/CRM/DataprocessorSearch/Form/OutputConfiguration.php b/CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.php similarity index 87% rename from CRM/DataprocessorSearch/Form/OutputConfiguration.php rename to CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.php index a60686c96bc363477516f1eccad921bdb46d88c9..8b7377d13d012dcaaee13acf527c46feb07ab3da 100644 --- a/CRM/DataprocessorSearch/Form/OutputConfiguration.php +++ b/CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.php @@ -7,7 +7,7 @@ use CRM_Dataprocessor_ExtensionUtil as E; * * @see https://wiki.civicrm.org/confluence/display/CRMDOC/QuickForm+Reference */ -class CRM_DataprocessorSearch_Form_OutputConfiguration extends CRM_Dataprocessor_Form_Output_AbstractOutputForm { +class CRM_DataprocessorSearch_Form_OutputConfiguration_ContactSearch extends CRM_Dataprocessor_Form_Output_AbstractOutputForm { /** * @var CRM_DataprocessorSearch_Utils_Navigation @@ -41,6 +41,7 @@ class CRM_DataprocessorSearch_Form_OutputConfiguration extends CRM_Dataprocessor 'class' => 'crm-select2 huge', 'placeholder' => E::ts('- select -'), )); + $this->add('select', 'hide_id_field', E::ts('Show Contact ID field'), array(0=>'Contact ID is Visible', 1=> 'Contact ID is hidden')); // navigation field $navigationOptions = $this->navigation->getNavigationOptions(); @@ -70,6 +71,9 @@ class CRM_DataprocessorSearch_Form_OutputConfiguration extends CRM_Dataprocessor if (isset($this->output['configuration']['title'])) { $defaults['title'] = $this->output['configuration']['title']; } + if (isset($this->output['configuration']['hide_id_field'])) { + $defaults['hide_id_field'] = $this->output['configuration']['hide_id_field']; + } } } if (!isset($defaults['permission'])) { @@ -93,6 +97,7 @@ class CRM_DataprocessorSearch_Form_OutputConfiguration extends CRM_Dataprocessor $params['configuration']['title'] = $values['title']; $params['configuration']['contact_id_field'] = $values['contact_id_field']; $params['configuration']['navigation_parent_path'] = $values['navigation_parent_path']; + $params['configuration']['hide_id_field'] = $values['hide_id_field']; CRM_Dataprocessor_BAO_Output::add($params); diff --git a/CRM/DataprocessorSearch/Search.php b/CRM/DataprocessorSearch/Search.php index b79164aea1ba47486a7612b5584061e2eeb9fd84..a07353989e7ecfba995d36069d799c4053893ae9 100644 --- a/CRM/DataprocessorSearch/Search.php +++ b/CRM/DataprocessorSearch/Search.php @@ -6,45 +6,45 @@ use Civi\DataProcessor\Output\OutputInterface; -class CRM_DataprocessorSearch_Search implements OutputInterface { +class CRM_DataprocessorSearch_Search { private static $rebuildMenu = false; - /** - * Return the url to a configuration page. - * Or return false when no configuration page exists. - * - * @return string|false - */ - public function getConfigurationUrl() { - return 'civicrm/dataprocessor/form/output/search'; - } - /** * Delegation of the alter menu hook. Add the search outputs to the menu system. * * @param $items */ public static function alterMenu(&$items) { + $factory = dataprocessor_get_factory(); + $sql = " - SELECT o.permission, p.id, p.title, o.configuration + SELECT o.permission, p.id, p.title, o.configuration, o.type, o.id as output_id FROM civicrm_data_processor_output o INNER JOIN civicrm_data_processor p ON o.data_processor_id = p.id - WHERE p.is_active = 1 AND o.type = 'search'"; + WHERE p.is_active = 1"; $dao = CRM_Core_DAO::executeQuery($sql); while ($dao->fetch()) { - $url = 'civicrm/dataprocessor_search/'.$dao->id; - $configuration = json_decode($dao->configuration, TRUE); - $title = $dao->title; - if (isset($configuration['title'])) { - $title = $configuration['title']; + $outputClass = $factory->getOutputByName($dao->type); + if ($outputClass instanceof CRM_DataprocessorSearch_SearchInterface) { + $outputs = CRM_Dataprocessor_BAO_Output::getValues(['id' => $dao->output_id]); + $output = $outputs[$dao->output_id]; + $dataprocessors = CRM_Dataprocessor_BAO_DataProcessor::getValues(['id' => $dao->id]); + $dataprocessor = $dataprocessors[$dao->id]; + $url = $outputClass->getSearchUrl($output, $dataprocessor); + + $configuration = json_decode($dao->configuration, TRUE); + $title = $dao->title; + if (isset($configuration['title'])) { + $title = $configuration['title']; + } + $item = [ + 'title' => $title, + 'page_callback' => $outputClass->getSearchControllerClass(), + 'access_arguments' => [$dao->permission], + ]; + $items[$url] = $item; } - $item = array( - 'title' => $title, - 'page_callback' => 'CRM_DataprocessorSearch_Controller_Search', - 'access_arguments' => array($dao->permission), - ); - $items[$url] = $item; } } @@ -96,7 +96,7 @@ class CRM_DataprocessorSearch_Search implements OutputInterface { $navigationParams['parent_id'] = !empty($navigationDefaults['parent_id']) ? $navigationDefaults['parent_id'] : NULL; } } - self::$rebuildMenu = self::newNavigationItem($params, $dataProcessor, $navigationParams); + self::$rebuildMenu = self::newNavigationItem($params, $dataProcessor, $navigationParams, $output); } } elseif ($op == 'create' && isset($params['configuration']['navigation_parent_path'])) { @@ -151,7 +151,20 @@ class CRM_DataprocessorSearch_Search implements OutputInterface { * * @return bool */ - private static function newNavigationItem(&$params, $dataProcessor, $navigationParams=array()) { + private static function newNavigationItem(&$params, $dataProcessor, $navigationParams=array(), $output=null) { + $url = ""; + $factory = dataprocessor_get_factory(); + $outputClass = FALSE; + if (isset($params['type'])) { + $outputClass = $factory->getOutputByName($params['type']); + } elseif(isset($output['type'])) { + $outputClass = $factory->getOutputByName($output['type']); + } + + if ($outputClass && $outputClass instanceof CRM_DataprocessorSearch_SearchInterface) { + $url = $outputClass->getSearchUrl($params, $dataProcessor); + } + $navigation = CRM_DataprocessorSearch_Utils_Navigation::singleton(); $navigationParams['domain_id'] = CRM_Core_Config::domainID(); $navigationParams['permission'] = array(); @@ -167,7 +180,7 @@ class CRM_DataprocessorSearch_Search implements OutputInterface { unset($params['configuration']['navigation_parent_path']); - $navigationParams['url'] = "civicrm/dataprocessor_search/{$dataProcessor['id']}?reset=1"; + $navigationParams['url'] = $url.'?reset=1'; $navigation = CRM_Core_BAO_Navigation::add($navigationParams); CRM_Core_BAO_Navigation::resetNavigation(); diff --git a/CRM/DataprocessorSearch/SearchInterface.php b/CRM/DataprocessorSearch/SearchInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..5d35808ad44f6ef37278604f485216a2633a5dfa --- /dev/null +++ b/CRM/DataprocessorSearch/SearchInterface.php @@ -0,0 +1,24 @@ +<?php +/** + * @author Jaap Jansma <jaap.jansma@civicoop.org> + * @license AGPL-3.0 + */ + +interface CRM_DataprocessorSearch_SearchInterface { + + /** + * Returns the url for the search + * + * @param \CRM_Dataprocessor_BAO_Output $output + * @param $dataprocessor + * + * @return string + */ + public function getSearchUrl($output, $dataprocessor); + + /** + * @return string + */ + public function getSearchControllerClass(); + +} \ No newline at end of file diff --git a/CRM/DataprocessorSearch/StateMachine/ActivitySearch.php b/CRM/DataprocessorSearch/StateMachine/ActivitySearch.php new file mode 100644 index 0000000000000000000000000000000000000000..f0cfb9c4132dadc4cfb9fb493b53c32561ae2cfa --- /dev/null +++ b/CRM/DataprocessorSearch/StateMachine/ActivitySearch.php @@ -0,0 +1,90 @@ +<?php +/** + * @author Jaap Jansma <jaap.jansma@civicoop.org> + * @license AGPL-3.0 + */ + +class CRM_DataprocessorSearch_StateMachine_ActivitySearch extends CRM_Core_StateMachine { + + /** + * The task that the wizard is currently processing. + * + * @var string + */ + protected $_task; + + /** + * Class constructor. + * + * @param object $controller + * @param \const|int $action + */ + public function __construct($controller, $action = CRM_Core_Action::NONE) { + parent::__construct($controller, $action); + + $this->_pages = array(); + $this->_pages['Search'] = array( + 'className' => 'CRM_DataprocessorSearch_Form_ActivitySearch', + ); + list($task, $result) = $this->taskName($controller, 'Search'); + $this->_task = $task; + + if (is_array($task)) { + foreach ($task as $t) { + $this->_pages[$t] = NULL; + } + } + else { + $this->_pages[$task] = NULL; + } + + $this->addSequentialPages($this->_pages, $action); + } + + /** + * Determine the form name based on the action. This allows us + * to avoid using conditional state machine, much more efficient + * and simpler + * + * @param CRM_Core_Controller $controller + * The controller object. + * + * @param string $formName + * + * @return array + * the name of the form that will handle the task + */ + public function taskName($controller, $formName = 'Search') { + // total hack, check POST vars and then session to determine stuff + $value = CRM_Utils_Array::value('task', $_POST); + if (!isset($value)) { + $value = $this->_controller->get('task'); + } + $this->_controller->set('task', $value); + return CRM_Activity_Task::getTask($value); + } + + /** + * Return the form name of the task. + * + * @return string + */ + public function getTaskFormName() { + var_dump($this->_task); + return CRM_Utils_String::getClassName($this->_task); + } + + /** + * Should the controller reset the session. + * In some cases, specifically search we want to remember + * state across various actions and want to go back to the + * beginning from the final state, but retain the same session + * values + * + * @return bool + */ + public function shouldReset() { + return FALSE; + } + +} diff --git a/CRM/DataprocessorSearch/StateMachine/Search.php b/CRM/DataprocessorSearch/StateMachine/ContactSearch.php similarity index 93% rename from CRM/DataprocessorSearch/StateMachine/Search.php rename to CRM/DataprocessorSearch/StateMachine/ContactSearch.php index 657e517b54fe0334e6b0c6dcc0193de9486c8957..4b7d7127caef69cf3630a4ee17f7ded756d06592 100644 --- a/CRM/DataprocessorSearch/StateMachine/Search.php +++ b/CRM/DataprocessorSearch/StateMachine/ContactSearch.php @@ -4,7 +4,7 @@ * @license AGPL-3.0 */ -class CRM_DataprocessorSearch_StateMachine_Search extends CRM_Core_StateMachine { +class CRM_DataprocessorSearch_StateMachine_ContactSearch extends CRM_Core_StateMachine { /** * The task that the wizard is currently processing @@ -24,7 +24,7 @@ class CRM_DataprocessorSearch_StateMachine_Search extends CRM_Core_StateMachine $this->_pages = array(); $this->_pages['Basic'] = array( - 'className' => 'CRM_DataprocessorSearch_Form_Search', + 'className' => 'CRM_DataprocessorSearch_Form_ContactSearch', ); list($task, $result) = $this->taskName($controller); $this->_task = $task; diff --git a/CRM/DataprocessorSearch/Utils/PrevNextCache.php b/CRM/DataprocessorSearch/Utils/PrevNextCache.php new file mode 100644 index 0000000000000000000000000000000000000000..5cf0bee48c6122965bb57517dca896d4c8048db4 --- /dev/null +++ b/CRM/DataprocessorSearch/Utils/PrevNextCache.php @@ -0,0 +1,106 @@ +<?php +/** + * @author Jaap Jansma <jaap.jansma@civicoop.org> + * @license AGPL-3.0 + */ + +class CRM_DataprocessorSearch_Utils_PrevNextCache { + + /** + * Delete an item from the prevnext cache table based on the entity. + * + * @param int $id + * @param string $cacheKey + */ + public function deleteItem($id = NULL, $cacheKey = NULL) { + if (Civi::container()->has('prevnext')) { + return Civi::service('prevnext')->deleteItem($id, $cacheKey); + } else { + // Backwards compatibility + $sql = "DELETE FROM civicrm_prevnext_cache WHERE (1)"; + $params = []; + + if (is_numeric($id)) { + $sql .= " AND ( entity_id1 = %2 OR entity_id2 = %2 )"; + $params[2] = [$id, 'Integer']; + } + + if (isset($cacheKey)) { + $sql .= " AND cacheKey = %3"; + $params[3] = [$cacheKey, 'String']; + } + CRM_Core_DAO::executeQuery($sql, $params); + } + } + + public static function fillWithArray($cacheKey, $rows) { + if (Civi::container()->has('prevnext')) { + return Civi::service('prevnext')->fillWithArray($cacheKey, $rows); + } else { + // Backwards compatibility + if (empty($rows)) { + return; + } + + $insert = CRM_Utils_SQL_Insert::into('civicrm_prevnext_cache') + ->columns([ + 'entity_table', + 'entity_id1', + 'entity_id2', + 'cacheKey', + 'data' + ]); + + foreach ($rows as &$row) { + $insert->row($row + ['cacheKey' => $cacheKey, 'entity_id2' => $row['entity_id1']]); + } + + CRM_Core_DAO::executeQuery($insert->toSQL()); + return TRUE; + } + return; + } + + /** + * Get the selections. + * + * @param string $cacheKey + * Cache key. + * @param string $action + * One of the following: + * - 'get' - get only selection records + * - 'getall' - get all the records of the specified cache key + * + * @return array|NULL + */ + public function getSelection($cacheKey, $action = 'get') { + if (Civi::container()->has('prevnext')) { + Civi::service('prevnext')->getSelection($cacheKey, $action); + } else { + // Backwards compatibility + if (!$cacheKey) { + return NULL; + } + $params = []; + + if ($cacheKey && ($action == 'get' || $action == 'getall')) { + $actionGet = ($action == "get") ? " AND is_selected = 1 " : ""; + $sql = " + SELECT entity_id1 FROM civicrm_prevnext_cache + WHERE cacheKey = %1 + $actionGet + ORDER BY id + "; + $params[1] = [$cacheKey, 'String']; + + $contactIds = [$cacheKey => []]; + $cIdDao = CRM_Core_DAO::executeQuery($sql, $params); + while ($cIdDao->fetch()) { + $contactIds[$cacheKey][$cIdDao->entity_id1] = 1; + } + return $contactIds; + } + } + } + +} \ No newline at end of file diff --git a/Civi/DataProcessor/Factory.php b/Civi/DataProcessor/Factory.php index f7ee609085ac668fca704b5861e08179b090b428..c8667bcf2e7fc19738451c2293f1e2fc989b0873 100644 --- a/Civi/DataProcessor/Factory.php +++ b/Civi/DataProcessor/Factory.php @@ -118,7 +118,8 @@ class Factory { $this->addDataSource('membership_status', 'Civi\DataProcessor\Source\Member\MembershipStatusSource', E::ts('Membership Status')); $this->addDataSource('csv', 'Civi\DataProcessor\Source\CSV', E::ts('CSV File')); $this->addOutput('api', 'Civi\DataProcessor\Output\Api', E::ts('API')); - $this->addOutput('search', 'CRM_DataprocessorSearch_Search', E::ts('Search')); + $this->addOutput('contact_search', 'CRM_DataprocessorSearch_ContactSearch', E::ts('Contact Search')); + $this->addOutput('activity_search', 'CRM_DataprocessorSearch_ActivitySearch', E::ts('Activity Search')); $this->addFilter('simple_sql_filter', 'Civi\DataProcessor\FilterHandler\SimpleSqlFilter', E::ts('Simple Filter')); $this->addjoinType('simple_join', 'Civi\DataProcessor\DataFlow\MultipleDataFlows\SimpleJoin', E::ts('Simple Join')); $this->addjoinType('simple_non_required_join', 'Civi\DataProcessor\DataFlow\MultipleDataFlows\SimpleNonRequiredJoin', E::ts('Simple (but not required) Join')); diff --git a/templates/CRM/DataprocessorSearch/Form/ActivitySearch.tpl b/templates/CRM/DataprocessorSearch/Form/ActivitySearch.tpl new file mode 100644 index 0000000000000000000000000000000000000000..004d808ee0824ff8682c71446896d5897a7f3670 --- /dev/null +++ b/templates/CRM/DataprocessorSearch/Form/ActivitySearch.tpl @@ -0,0 +1 @@ +{include file="CRM/DataprocessorSearch/Form/Search.tpl"} \ No newline at end of file diff --git a/templates/CRM/DataprocessorSearch/Form/ContactSearch.tpl b/templates/CRM/DataprocessorSearch/Form/ContactSearch.tpl new file mode 100644 index 0000000000000000000000000000000000000000..bb0b8981f637a798521c4ff5e3b2c3d6dd6d899b --- /dev/null +++ b/templates/CRM/DataprocessorSearch/Form/ContactSearch.tpl @@ -0,0 +1,68 @@ +{include file="CRM/DataprocessorSearch/Form/CriteriaForm.tpl"} + +{if $debug && isset($debug_info.query)} + <div class="crm-block crm-form-block"> + <h3>Executes queries</h3> + {foreach from=$debug_info.query item=query} + <pre id="debug_info" class="linenums prettyprint prettyprinted" style="font-size: 11px; padding: 1em; border: 1px solid lightgrey; margin-top: 1em; overflow: auto;">{strip} + {$query|replace:"SELECT":"SELECT\r\n "|replace:"FROM":"\r\nFROM"|replace:"INNER JOIN":"\r\nINNER JOIN"|replace:"LEFT JOIN":"\r\nLEFT JOIN"|replace:"WHERE":"\r\nWHERE"|replace:"ORDER BY":"\r\nORDER BY"|replace:"LIMIT":"\r\nLIMIT"|replace:"AND":"\r\n AND"|replace:"`, `":"`,\r\n `"} + {/strip}</pre> + {/foreach} + </div> +{/if} + +{if (isset($rows) && !empty($rows))} + <div class="crm-content-block"> + <div class="crm-results-block"> + {* This section handles form elements for action task select and submit *} + <div class="crm-search-tasks"> + {include file="CRM/common/searchResultTasks.tpl"} + </div> + + {include file="CRM/common/pager.tpl" location="top"} + + <div class="crm-search-results"> + <a href="#" class="crm-selection-reset crm-hover-button"><i class="crm-i fa-times-circle-o"></i> {ts}Reset all selections{/ts}</a> + <table class="selector row-highlight"> + <thead class="sticky"> + <tr> + <th scope="col" title="Select Rows">{$form.toggleSelect.html}</th> + <th scope="col"></th> + {foreach from=$columnHeaders key=headerName item=headerTitle} + <th scope="col"> + {$sort->_response.$headerName.link} + </th> + {/foreach} + <th scope="col"></th> + </tr></thead> + + + {foreach from=$rows item=row} + <tr id='rowid{$row.id}' class="{cycle values="odd-row,even-row"}"> + {assign var=cbName value=$row.checkbox} + {assign var=id value=$row.id} + {assign var=record value=$row.record} + <td>{$form.$cbName.html}</td> + <td>{$row.contact_type}</td> + {foreach from=$columnHeaders key=headerName item=headerTitle} + {assign var=columnValue value=$record.$headerName} + <td>{$columnValue->formattedValue}</td> + {/foreach} + + <td> + <a href="{crmURL p='civicrm/contact/view' q="reset=1&cid=`$contact_id`"}"> + {ts}View contact{/ts} + </a> + </td> + </tr> + {/foreach} + + </table> + </div> + + {include file="CRM/common/pager.tpl" location="bottom"} + </div> + </div> + + {include file="CRM/DataprocessorSearch/Form/ResultsJavascript.tpl"} +{/if} \ No newline at end of file diff --git a/templates/CRM/DataprocessorSearch/Form/CriteriaForm.tpl b/templates/CRM/DataprocessorSearch/Form/CriteriaForm.tpl new file mode 100644 index 0000000000000000000000000000000000000000..4747db016182a35e51f6482a6e378c445498e697 --- /dev/null +++ b/templates/CRM/DataprocessorSearch/Form/CriteriaForm.tpl @@ -0,0 +1,73 @@ +<div class="crm-form-block crm-search-form-block"> + <div class="crm-accordion-wrapper crm-advanced_search_form-accordion {if (!empty($rows))}collapsed{/if}"> + <div class="crm-accordion-header crm-master-accordion-header"> + {ts}Edit Search Criteria{/ts} + </div> + <!-- /.crm-accordion-header --> + <div class="crm-accordion-body"> + <div id="searchForm" class="form-item"> + <table> + <tr> + <th>{ts}Name{/ts}</th> + <th>{ts}Operator{/ts}</th> + <th>{ts}Value{/ts}</th> + </tr> + {foreach from=$filters key=filterName item=filter} + {assign var=fieldOp value=$filterName|cat:"_op"} + {assign var=filterVal value=$filterName|cat:"_value"} + {assign var=filterMin value=$filterName|cat:"_min"} + {assign var=filterMax value=$filterName|cat:"_max"} + {if $filter.type == 'Date'} + <tr> + <td>{$filter.title}</td> + {include file="CRM/DataprocessorSearch/Form/DateRange.tpl" fieldName=$filterName from='_from' to='_to'} + </tr> + {elseif $form.$fieldOp.html} + <tr> + <td class="label">{$filter.title}</td> + <td>{$form.$fieldOp.html}</td> + <td> + <span id="{$filterVal}_cell">{$form.$filterVal.label} {$form.$filterVal.html}</span> + <span id="{$filterMin}_max_cell">{$form.$filterMin.label} {$form.$filterMin.html} {$form.$filterMax.label} {$form.$filterMax.html}</span> + </td> + </tr> + {/if} + {/foreach} + </table> + <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="botton"}</div> + </div> + </div> + </div> +</div> + +{literal} +<script type="text/javascript"> + {/literal} + {foreach from=$filters item=filter key=filterName} + {literal}var val = "dnc";{/literal} + {assign var=fieldOp value=$filterName|cat:"_op"} + {if !($field.operatorType & 4) && !$field.no_display && $form.$fieldOp.html} + {literal}var val = document.getElementById("{/literal}{$fieldOp}{literal}").value;{/literal} + {/if} + {literal}showHideMaxMinVal( "{/literal}{$filterName}{literal}", val );{/literal} + {/foreach} + + {literal} + function showHideMaxMinVal( field, val ) { + var fldVal = field + "_value_cell"; + var fldMinMax = field + "_min_max_cell"; + if ( val == "bw" || val == "nbw" ) { + cj('#' + fldVal ).hide(); + cj('#' + fldMinMax ).show(); + } else if (val =="nll" || val == "nnll") { + cj('#' + fldVal).hide() ; + cj('#' + field + '_value').val(''); + cj('#' + fldMinMax ).hide(); + } else { + cj('#' + fldVal ).show(); + cj('#' + fldMinMax ).hide(); + } + } + +</script> +{/literal} diff --git a/templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.tpl b/templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.tpl new file mode 100644 index 0000000000000000000000000000000000000000..435f8e0b5c497924ad69bd70231f9950eeae2013 --- /dev/null +++ b/templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ActivitySearch.tpl @@ -0,0 +1,38 @@ +{crmScope extensionKey='dataprocessor'} + <div class="crm-submit-buttons"> + {include file="CRM/common/formButtons.tpl" location="top"} + </div> + + <h3>{ts}Output configuration{/ts}</h3> + <div class="crm-block crm-form-block crm-data-processor_output-block"> + <div class="crm-section"> + <div class="label">{$form.title.label}</div> + <div class="content">{$form.title.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section"> + <div class="label">{$form.navigation_parent_path.label}</div> + <div class="content">{$form.navigation_parent_path.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section"> + <div class="label">{$form.permission.label}</div> + <div class="content">{$form.permission.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section"> + <div class="label">{$form.activity_id_field.label}</div> + <div class="content">{$form.activity_id_field.html}</div> + <div class="clear"></div> + </div> + <div class="crm-section"> + <div class="label">{$form.hide_id_field.label}</div> + <div class="content">{$form.hide_id_field.html}</div> + <div class="clear"></div> + </div> + </div> + + <div class="crm-submit-buttons"> + {include file="CRM/common/formButtons.tpl" location="bottom"} + </div> +{/crmScope} \ No newline at end of file diff --git a/templates/CRM/DataprocessorSearch/Form/OutputConfiguration.tpl b/templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.tpl similarity index 85% rename from templates/CRM/DataprocessorSearch/Form/OutputConfiguration.tpl rename to templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.tpl index 99a80c600764715efae7a8761db3671a100b4594..855b29286d4d79a6fb32b4dbeeedd6f1e2ea9eb0 100644 --- a/templates/CRM/DataprocessorSearch/Form/OutputConfiguration.tpl +++ b/templates/CRM/DataprocessorSearch/Form/OutputConfiguration/ContactSearch.tpl @@ -25,6 +25,11 @@ <div class="content">{$form.contact_id_field.html}</div> <div class="clear"></div> </div> + <div class="crm-section"> + <div class="label">{$form.hide_id_field.label}</div> + <div class="content">{$form.hide_id_field.html}</div> + <div class="clear"></div> + </div> </div> <div class="crm-submit-buttons"> diff --git a/templates/CRM/DataprocessorSearch/Form/ResultsJavascript.tpl b/templates/CRM/DataprocessorSearch/Form/ResultsJavascript.tpl new file mode 100644 index 0000000000000000000000000000000000000000..91ae61a5b285d16c4fbfbd1752e2bcdd11b6b5b2 --- /dev/null +++ b/templates/CRM/DataprocessorSearch/Form/ResultsJavascript.tpl @@ -0,0 +1,13 @@ +<script type="text/javascript"> + {literal} + CRM.$(function($) { + // Clear any old selection that may be lingering in quickform + $("input.select-row, input.select-rows", 'form.crm-search-form').prop('checked', false).closest('tr').removeClass('crm-row-selected'); + // Retrieve stored checkboxes + var selectedIds = {/literal}{$selectedIds|@json_encode}{literal}; + if (selectedIds.length > 0) { + $('#mark_x_' + selectedIds.join(',#mark_x_') + ',input[name=radio_ts][value=ts_sel]').trigger('click'); + } + }); + {/literal} +</script> \ No newline at end of file diff --git a/templates/CRM/DataprocessorSearch/Form/Search.tpl b/templates/CRM/DataprocessorSearch/Form/Search.tpl index 3c6d8d1885984849a4b95b1e975baf144422a016..407cfdf8858c489a9d238f9a9d7d9a2e47ad41c5 100644 --- a/templates/CRM/DataprocessorSearch/Form/Search.tpl +++ b/templates/CRM/DataprocessorSearch/Form/Search.tpl @@ -1,44 +1,4 @@ -<div class="crm-form-block crm-search-form-block"> - <div class="crm-accordion-wrapper crm-advanced_search_form-accordion {if (!empty($rows))}collapsed{/if}"> - <div class="crm-accordion-header crm-master-accordion-header"> - {ts}Edit Search Criteria{/ts} - </div> - <!-- /.crm-accordion-header --> - <div class="crm-accordion-body"> - <div id="searchForm" class="form-item"> - <table> - <tr> - <th>{ts}Name{/ts}</th> - <th>{ts}Operator{/ts}</th> - <th>{ts}Value{/ts}</th> - </tr> - {foreach from=$filters key=filterName item=filter} - {assign var=fieldOp value=$filterName|cat:"_op"} - {assign var=filterVal value=$filterName|cat:"_value"} - {assign var=filterMin value=$filterName|cat:"_min"} - {assign var=filterMax value=$filterName|cat:"_max"} - {if $filter.type == 'Date'} - <tr> - <td>{$filter.title}</td> - {include file="CRM/DataprocessorSearch/Form/DateRange.tpl" fieldName=$filterName from='_from' to='_to'} - </tr> - {elseif $form.$fieldOp.html} - <tr> - <td class="label">{$filter.title}</td> - <td>{$form.$fieldOp.html}</td> - <td> - <span id="{$filterVal}_cell">{$form.$filterVal.label} {$form.$filterVal.html}</span> - <span id="{$filterMin}_max_cell">{$form.$filterMin.label} {$form.$filterMin.html} {$form.$filterMax.label} {$form.$filterMax.html}</span> - </td> - </tr> - {/if} - {/foreach} - </table> - <div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="botton"}</div> - </div> - </div> - </div> -</div> +{include file="CRM/DataprocessorSearch/Form/CriteriaForm.tpl"} {if $debug && isset($debug_info.query)} <div class="crm-block crm-form-block"> @@ -67,7 +27,6 @@ <thead class="sticky"> <tr> <th scope="col" title="Select Rows">{$form.toggleSelect.html}</th> - <th scope="col"></th> {foreach from=$columnHeaders key=headerName item=headerTitle} <th scope="col"> {$sort->_response.$headerName.link} @@ -78,12 +37,11 @@ {foreach from=$rows item=row} - <tr id='rowid{$row.contact_id}' class="{cycle values="odd-row,even-row"}"> + <tr id='rowid{$row.id}' class="{cycle values="odd-row,even-row"}"> {assign var=cbName value=$row.checkbox} - {assign var=contact_id value=$row.contact_id} + {assign var=id value=$row.id} {assign var=record value=$row.record} <td>{$form.$cbName.html}</td> - <td>{$row.contact_type}</td> {foreach from=$columnHeaders key=headerName item=headerTitle} {assign var=columnValue value=$record.$headerName} <td>{$columnValue->formattedValue}</td> @@ -104,51 +62,5 @@ </div> </div> - <script type="text/javascript"> - {literal} - CRM.$(function($) { - // Clear any old selection that may be lingering in quickform - $("input.select-row, input.select-rows", 'form.crm-search-form').prop('checked', false).closest('tr').removeClass('crm-row-selected'); - // Retrieve stored checkboxes - var cids = {/literal}{$selectedContactIds|@json_encode}{literal}; - if (cids.length > 0) { - //$('#mark_x_' + cids.join(',#mark_x_') + ',input[name=radio_ts][value=ts_sel]').prop('checked', true); - $('#mark_x_' + cids.join(',#mark_x_') + ',input[name=radio_ts][value=ts_sel]').trigger('click'); - } - }); - {/literal} - </script> -{/if} - - -{literal} -<script type="text/javascript"> - {/literal} - {foreach from=$filters item=filter key=filterName} - {literal}var val = "dnc";{/literal} - {assign var=fieldOp value=$filterName|cat:"_op"} - {if !($field.operatorType & 4) && !$field.no_display && $form.$fieldOp.html} - {literal}var val = document.getElementById("{/literal}{$fieldOp}{literal}").value;{/literal} - {/if} - {literal}showHideMaxMinVal( "{/literal}{$filterName}{literal}", val );{/literal} - {/foreach} - - {literal} - function showHideMaxMinVal( field, val ) { - var fldVal = field + "_value_cell"; - var fldMinMax = field + "_min_max_cell"; - if ( val == "bw" || val == "nbw" ) { - cj('#' + fldVal ).hide(); - cj('#' + fldMinMax ).show(); - } else if (val =="nll" || val == "nnll") { - cj('#' + fldVal).hide() ; - cj('#' + field + '_value').val(''); - cj('#' + fldMinMax ).hide(); - } else { - cj('#' + fldVal ).show(); - cj('#' + fldMinMax ).hide(); - } - } - -</script> -{/literal} + {include file="CRM/DataprocessorSearch/Form/ResultsJavascript.tpl"} +{/if} \ No newline at end of file diff --git a/xml/Menu/dataprocessor.xml b/xml/Menu/dataprocessor.xml index e3e78a0649158d35a7f79f960050e02a20a8bd17..8fc489337d194f7df67c3c71d7b46ffa15e549b3 100644 --- a/xml/Menu/dataprocessor.xml +++ b/xml/Menu/dataprocessor.xml @@ -78,8 +78,15 @@ <access_arguments>administer CiviCRM</access_arguments> </item> <item> - <path>civicrm/dataprocessor/form/output/search</path> - <page_callback>CRM_DataprocessorSearch_Form_OutputConfiguration</page_callback> + <path>civicrm/dataprocessor/form/output/contact_search</path> + <page_callback>CRM_DataprocessorSearch_Form_OutputConfiguration_ContactSearch</page_callback> + <title>DataProcessor</title> + <access_arguments>access CiviCRM</access_arguments> + <access_arguments>administer CiviCRM</access_arguments> + </item> + <item> + <path>civicrm/dataprocessor/form/output/activity_search</path> + <page_callback>CRM_DataprocessorSearch_Form_OutputConfiguration_ActivitySearch</page_callback> <title>DataProcessor</title> <access_arguments>access CiviCRM</access_arguments> <access_arguments>administer CiviCRM</access_arguments>