/**
  * Create a data tree from a report of the selectable forms.  Deisgned to be fed into tree select
  * @param array $fields 
  * @param array $forms An unorderd array of form names whose values we allow to be selected
  * @param array $displayed The displayed forms for the tree
  * @param array $limits An array with keys form names and value limit data
  * @param array $orders An array with keys form names and values array of field orders for that form.  
  *                      If the form name has no orders, we use default ordering for that form based on its displayed firelds
  * @param int $show_hidden 0=non-hidden, 1=All, 2=hidden only.  Defaults to 0
  * @param string $report A report name to use for the query instead of building it from form cache or directly.
  * @return array
  */
 public static function buildReportTree($fields, $forms, $displayed, $limits, $orders = array(), $show_hidden = 0, $report = null)
 {
     if (!is_array($report) || !array_key_exists('report', $report)) {
         return array();
     }
     $report_table = I2CE_CustomReport::getCachedTableName($report['report']);
     if (!$report_table) {
         return array();
     }
     $map = array();
     if (array_key_exists('map', $report)) {
         $map = $report['map'];
     }
     $where = array();
     $displays = array();
     $report_alias = array();
     $formObjs = array();
     $use_link = '';
     foreach ($fields as $formfield) {
         list($form, $link_field) = $formfield;
         $ff = $form . ($link_field ? "+{$link_field}" : "");
         if (array_key_exists($ff, $map)) {
             $report_alias[$ff] = $map[$ff];
         } elseif (array_key_exists($form, $map)) {
             $report_alias[$form] = $map[$form];
             $report_alias[$ff] = $map[$form];
         } else {
             $report_alias[$form] = $form;
             $report_alias[$ff] = $form;
         }
         //if ( array_key_exists( $ff, $limits ) ) {
         //$limit = $limits[$ff];
         //} else
         if (array_key_exists($report_alias[$ff], $limits)) {
             $limit = $limits[$report_alias[$ff]];
         } elseif (array_key_exists($form, $limits)) {
             $limit = $limits[$form];
         } else {
             $limit = array();
         }
         self::addFormIdToLimit($form, $limit);
         $limit = self::showHiddenLimit($limit, $show_hidden);
         /*
         if ( !$show_hidden ) {
             $hidden = $report_alias[$ff] . '+i2ce_hidden';
             $where[] = "( `$hidden` = 0 OR ISNULL( `$hidden` ) )";
         }
         */
         $disp_fields = I2CE_List::getDisplayFields($form);
         if (array_key_exists($form, $orders)) {
             $order = $orders[$form];
         } else {
             $order = I2CE_List::getSortFields($form);
         }
         $sort_list = array();
         //if ( array_key_exists( $form, $displayed ) && $displayed[$form] ) {
         if (array_key_exists($form, $displayed)) {
             $alias_form = $report_alias[$ff];
             if ($displayed[$form]) {
                 $displays[$alias_form]['form'] = $form;
                 if ($use_link == '') {
                     $displays[$alias_form]['link_field'] = $link_field == '' ? $link_field : "{$alias_form}+{$link_field}";
                 } else {
                     $displays[$alias_form]['link_field'] = $use_link;
                     $use_link = '';
                 }
                 foreach ($disp_fields as $disp) {
                     $displays[$alias_form]['fields'][$disp] = $alias_form . "+{$disp}";
                 }
                 foreach ($order as $i => $ord) {
                     if (!is_string($ord)) {
                         unset($order[$i]);
                         continue;
                     }
                     if ($ord[0] == '-') {
                         $field = substr($ord, 1);
                         $all_orders[] = "`{$alias_form}+{$field}` DESC";
                     } else {
                         $field = $ord;
                         $all_orders[] = "`{$alias_form}+{$field}` ASC";
                     }
                 }
             } elseif ($use_link == '') {
                 $use_link = $link_field == '' ? $link_field : "{$alias_form}+{$link_field}";
             }
         }
         if (!array_key_exists($form, $formObjs)) {
             $formObjs[$form] = I2CE_FormFactory::instance()->createContainer($form);
             if (!$formObjs[$form] instanceof I2CE_Form) {
                 I2CE::raiseError("Could not instantiate {$form}");
                 return array();
             }
         }
         self::$curr_alias = $report_alias[$ff];
         $where[] = $formObjs[$form]->generateWhereClause($limit, array("I2CE_DataTree", "getSQLField"));
     }
     $where_clause = "";
     $order_by = "";
     if (count($where) > 0) {
         $where_clause = " WHERE " . implode(' AND ', $where);
     }
     if (count($all_orders) > 0) {
         $order_by = " ORDER BY " . implode(',', $all_orders);
     }
     $qry = "SELECT * FROM {$report_table} {$where_clause} {$order_by}";
     $db = MDB2::singleton();
     I2CE::raiseMessage($qry);
     $res = $db->query($qry);
     if (I2CE::pearError($res, "Invalid report data tree query: ")) {
         return array();
     }
     $phonebook = array();
     $results = array();
     $display_string = array();
     $display_copy = $displays;
     while ($data = $res->fetchRow()) {
         foreach ($displays as $alias => $disp_data) {
             $id_field = strtolower($alias . "+id");
             if ($data->{$id_field} == null || array_key_exists($data->{$id_field}, $phonebook)) {
                 continue;
             }
             $curr = array();
             $add_this = false;
             if (in_array($disp_data['form'], $forms)) {
                 $curr['value'] = $data->{$id_field};
                 $add_this = true;
             }
             if (!$add_this) {
                 $check_ok = false;
                 foreach ($display_copy as $alias_copy => $disp_data_copy) {
                     if ($alias_copy == $alias) {
                         $check_ok = true;
                         continue;
                     }
                     if (!$check_ok) {
                         continue;
                     }
                     if (array_key_exists('link_field', $disp_data_copy) && $disp_data_copy['link_field'] != '') {
                         $link_field_copy = $disp_data_copy['link_field'];
                         if ($data->{$id_field} == $data->{$link_field_copy}) {
                             $add_this = true;
                             break;
                         }
                     }
                 }
             }
             if (!$add_this) {
                 continue;
             }
             if (!array_key_exists($disp_data['form'], $display_string)) {
                 $display_string[$disp_data['form']] = I2CE_List::getDisplayString($disp_data['form']);
             }
             $disp_array = array();
             $disp_str = $display_string[$disp_data['form']];
             $disp_str_arr = explode('%s', $disp_str);
             $fo = $formObjs[$disp_data['form']];
             $disp_count = 0;
             foreach ($disp_data['fields'] as $field => $dbfield) {
                 $disp_count++;
                 if ($dbfield == $disp_data['link_field']) {
                     // Don't include the data from the link field since it will already be there.
                     if ($disp_count == 1) {
                         unset($disp_str_arr[$disp_count]);
                     } else {
                         unset($disp_str_arr[$disp_count - 1]);
                     }
                     continue;
                 }
                 $dbfield = strtolower($dbfield);
                 $fieldObj = $fo->getField($field);
                 if (!$fieldObj instanceof I2CE_FormField) {
                     I2CE::raiseError("Could not get field {$field}");
                     continue;
                 }
                 if (isset($data->{$dbfield})) {
                     $fieldObj->setFromDB($data->{$dbfield});
                     $disp_array[$field] = $fieldObj->getDisplayValue();
                 } else {
                     $disp_array[$field] = null;
                 }
             }
             $disp_str = implode('%s', $disp_str_arr);
             $display = vsprintf($disp_str, $disp_array);
             $curr['display'] = $display;
             $phonebook[$data->{$id_field}] =& $curr;
             if ($disp_data['link_field'] != '') {
                 $link_field = $disp_data['link_field'];
                 if (array_key_exists($data->{$link_field}, $phonebook)) {
                     $add_to =& $phonebook[$data->{$link_field}];
                     if (!array_key_exists('children', $phonebook[$data->{$link_field}])) {
                         $phonebook[$data->{$link_field}]['children'] = array();
                     }
                     $phonebook[$data->{$link_field}]['children'][] =& $curr;
                 } else {
                     //I2CE::raiseMessage( "Couldn't find $link_field " . $data->$link_field . " in phonebook " );
                 }
             } else {
                 $results[] =& $curr;
             }
             unset($curr);
         }
     }
     return $results;
 }
 /**
  * Perform any actions
  * 
  * @return boolean  true on sucess
  */
 protected function action()
 {
     /*
      * XX lists/form/position/facility+location/county/district?district%2Bregion=region|1
      * XX lists/field/person_position+facility/default/??
      * lists/LIST/[FORM[+FIELD]/[STYLE]]?[limit={JSON}&FORM[+FIELD]=VALUE
      * lists/district/position+facility?country=country|TF
      * lists/facility?facility+location=country|TF
      */
     $list = array_shift($this->request_remainder);
     $is_public = false;
     I2CE::getConfig()->setIfIsSet($is_public, "/modules/forms/forms/{$list}/meta/list/is_public");
     if (!$is_public) {
         $task = "can_view_database_list_{$list}";
         if (!$this->hasPermission("task({$task})")) {
             $this->setError('noaccess_page');
             return false;
         }
     }
     $listObj = I2CE_FormFactory::instance()->createContainer($list);
     if (!$listObj instanceof I2CE_List) {
         $this->setError('invalid_list', array($list));
     }
     $style = 'default';
     $fields = array();
     $forms = array($list);
     $where = array();
     $get = $this->request();
     if (array_key_exists('limit', $get)) {
         $where = json_decode($get['limit']);
         unset($get['limit']);
     }
     $enclose_array = false;
     if (array_key_exists('array', $get)) {
         if ($get['array']) {
             $enclose_array = true;
         }
         unset($get['array']);
     }
     if (count($this->request_remainder) > 0) {
         $formfield = array_shift($this->request_remainder);
         if (strpos($formfield, '+') === false) {
             $form = $formfield;
             $field = $list;
         } else {
             list($form, $field) = explode('+', $formfield, 2);
         }
         $formObj = I2CE_FormFactory::instance()->createContainer($form);
         if (!$formObj instanceof I2CE_Form) {
             $this->setError('invalid_form', array($form));
         }
         if (!$formObj->hasField($field)) {
             $this->setError('invalid_field', array($field, $form));
             return true;
         }
         $fieldObj = $formObj->getField($field);
         if (!$fieldObj instanceof I2CE_FormField_MAPPED) {
             $this->setError('invalid_field', array($field, $form));
         }
         if (count($this->request_remainder) > 0) {
             $style = array_shift($this->request_remainder);
         }
         $form_limits = $fieldObj->getFormLimits($style);
         $form_fields = $fieldObj->getDisplayedFields($style);
         $form_limits = $this->getCurrentListLimits($form_limits, $list, $form_fields);
         array_walk($form_fields, 'self::removeHidden');
         $add_where = array();
         foreach ($get as $formfield => $limit) {
             if (($form_key = array_search($formfield, $form_fields)) !== false) {
                 if (!is_array($limit)) {
                     $limit = array('equals' => $limit);
                 }
                 unset($get[$formfield]);
                 if ($form_key == 0) {
                     if (strpos($formfield, '+') !== false) {
                         list($form, $field) = self::explodeLimitField($formfield);
                         foreach ($limit as $limit_style => $value) {
                             self::addOrCombineFieldLimit($add_where, $form, $field, $value, $limit_style);
                         }
                     }
                 } else {
                     $prev_key = $form_key - 1;
                     $prev_form = $form_fields[$prev_key];
                     $curr_form = $form_fields[$form_key];
                     $new_limit = array();
                     if (strpos($prev_form, '+') === false) {
                         if (($curr_pos = strpos($curr_form, '+')) !== false) {
                             $curr_form = substr($curr_form, 0, $curr_pos);
                         }
                         foreach ($limit as $limit_style => $value) {
                             self::addOrCombineFieldLimit($add_where, $prev_form, $curr_form, $value, $limit_style);
                         }
                     } else {
                         list($form, $field) = self::explodeLimitField($prev_form);
                         foreach ($limit as $limit_style => $value) {
                             self::addOrCombineFieldLimit($add_where, $form, $field, $value, $limit_style);
                         }
                     }
                 }
             }
         }
         $form_limits = self::combineFormLimits($form_limits, $add_where);
         if (!array_key_exists($list, $form_limits)) {
             $skip = true;
             foreach ($form_fields as $ff) {
                 if (($pluspos = strpos($ff, '+')) !== false) {
                     $ff_form = substr($ff, 0, $pluspos);
                 } else {
                     $ff_form = $ff;
                 }
                 $ff = str_replace('[', '', str_replace(']', '', $ff));
                 if ($ff_form == $list) {
                     $skip = false;
                 }
                 if ($skip) {
                     continue;
                 }
                 $fields[] = $ff;
                 if (array_key_exists($ff_form, $form_limits)) {
                     break;
                 }
             }
         } else {
             $fields[] = $list;
         }
         $where = self::combineFormLimits($where, $form_limits);
     } else {
         $fields[] = $list;
     }
     if (count($get) > 0) {
         $add_where = array();
         foreach ($get as $formfield => $limit) {
             if (!is_array($limit)) {
                 $limit = array('equals' => $limit);
             }
             if (strpos($formfield, '+') !== false) {
                 list($form, $field) = self::explodeLimitField($formfield);
                 foreach ($limit as $limit_limit_style => $value) {
                     self::addOrCombineFieldLimit($add_where, $form, $field, $value, $limit_style);
                 }
             }
         }
         $where = self::combineFormLimits($where, $add_where);
     }
     foreach ($where as $w_form => $w_limits) {
         if (!in_array($w_form, $fields)) {
             unset($where[$w_form]);
         }
     }
     $this->data = array('list' => $list);
     //$this->data['data'] = I2CE_List::listOptions( $list );
     //$results = I2CE_DataTree::flattenDataTree( I2CE_DataTree::buildDataTree( array( 'position', 'facility+location', 'county', 'district' ), array( 'position' ), $where ), true );
     //I2CE::raiseMessage("building tree for " . print_r($fields,true).print_r($forms,true).print_r($where,true));
     $results = I2CE_DataTree::flattenDataTree(I2CE_DataTree::buildDataTree($fields, $forms, $where, array(), 0, null, $style), true);
     $this->data['length'] = count($results);
     $this->data['data'] = $results;
     if ($enclose_array) {
         $this->data = array($this->data);
     }
     return true;
 }
Exemple #3
0
 /**
  * Internal method to search all the ids for forms that are below
  * the given matched form id.
  * @param string $match The form id to match at the top.
  * @param array $fields The getDisplayedFields() for the field object.
  * @param array $forms The getSelectableFroms() for the field object.
  * @param array $displayed A list of forms that should be included in the results.
  * @param int $show_hidden 0=non-hidden, 1=All, 2=hidden only.
  * @return array
  */
 protected static function _searchLowerMatches($match_form, $match_ids, $fields, $forms, $displayed, $show_hidden)
 {
     $formfield = array_shift($fields);
     if (!is_array($formfield)) {
         return array();
     }
     list($form, $link_field) = $formfield;
     $limit = array('operator' => 'FIELD_LIMIT', 'field' => $link_field, 'style' => 'in', 'data' => array('value' => $match_ids));
     $limit = I2CE_DataTree::showHiddenLimit($limit, $show_hidden);
     $order = I2CE_List::getSortFields($form);
     $field_datas = I2CE_FormStorage::listFields($form, 'id', false, $limit, $order);
     $matched = array();
     foreach (array_keys($field_datas) as $matched_id) {
         $matched[] = $form . "|" . $matched_id;
     }
     if ($displayed[$form]) {
         return array_merge($matched, self::_searchLowerMatches($form, $matched, $fields, $forms, $displayed, $show_hidden));
     } else {
         return self::_searchLowerMatches($form, $matched, $fields, $forms, $displayed, $show_hidden);
     }
 }
 /**
  *@returns array where keys are ids, values are arrays with the following keys 'value', 'display'
  */
 public function getMapOptions($type = 'default', $show_hidden = 0, $flat = true, $add_limits = array())
 {
     $forms = $this->getSelectableForms();
     $fields = $this->getDisplayedFields($type);
     $limits = $this->getFormLimits($type);
     $report = $this->getDisplayReport($type);
     if (is_array($add_limits) && count($add_limits) > 0) {
         if (!is_array($limits) || count($limits) > 0) {
             $limits = $add_limits;
         } else {
             //need to go through each form and possibly merge limits
             foreach ($add_limits as $form => $formLimits) {
                 if (!array_key_exists($form, $limits) || !is_array($limits[$form]) || count($limits[$form]) == 0) {
                     $limits[$form] = $formLimits;
                 } else {
                     $limits[$form] = array('operator' => 'AND', 'operand' => array(0 => $limits[$form], 1 => $formLimits));
                 }
             }
         }
     }
     $orders = $this->getFormOrders($type);
     //echo "For " . ($this->getContainer() instanceof I2CE_Form ? $this->getContainer()->getName() . " + " : "" ) . $this->getName() . " using " . $report . "\n";
     //I2CE::raiseError( "For " . ($this->getContainer() instanceof I2CE_Form ? $this->getContainer()->getName() . " + " : "" ) . $this->getName() . " using " . print_r($limits,true) );
     $data = I2CE_DataTree::buildDataTree($fields, $forms, $limits, $orders, $show_hidden, $report);
     if (!$data) {
         //I2CE::raiseError("Could not build data tree for " .implode(',',$fields) . " and " . implode(",",$forms));
         return array();
     }
     if ($flat) {
         $data = I2CE_DataTree::flattenDataTree($data);
     }
     return $data;
 }