* @copyright Cornelius Weiss * @version $Id$ */ /** * export plugin of addressbook */ class addressbook_export_contacts_csv implements importexport_iface_export_plugin { /** * Constants used for exploding categories & multi-selectboxes into seperate fields */ const NO_EXPLODE = False; const MAIN_CATS = 'main_cats'; // Only the top-level categories get their own field const EACH_CAT = 'each_cat'; // Every category gets its own field const EXPLODE = 'explode'; // For [custom] multi-selects, each option gets its own field public function __construct() { $this->ui= new addressbook_ui(); $this->get_selects(); } /** * Exports records as defined in $_definition * * @param egw_record $_definition */ public function export( $_stream, importexport_definition $_definition) { $options = $_definition->plugin_options; $this->export_object = $export_object = new importexport_export_csv($_stream, (array)$options); $selection = array(); // Addressbook defines its own export imits $limit_exception = bo_merge::is_export_limit_excepted(); $export_limit = bo_merge::getExportLimit($app='addressbook'); if (!$limit_exception) $export_object->export_limit = $export_limit; // we may not need that after all if($export_limit == 'no' && !$limit_exception) { return; } // Need to switch the app to get the same results $old_app = $GLOBALS['egw_info']['flags']['currentapp']; $GLOBALS['egw_info']['flags']['currentapp'] = 'addressbook'; if ($options['selection'] == 'search') { // uicontacts selection with checkbox 'use_all' $query = $GLOBALS['egw']->session->appsession('index','addressbook'); $query['num_rows'] = -1; // all $query['csv_export'] = true; // so get_rows method _can_ produce different content or not store state in the session if(!array_key_exists('filter',$query)) $query['filter'] = $GLOBALS['egw_info']['user']['account_id']; $this->ui->get_rows($query,$selection,$readonlys, true); // only return the ids } elseif ( $options['selection'] == 'all' ) { if ($GLOBALS['egw_info']['user']['preferences']['addressbook']['hide_accounts']) { $col_filter['account_id'] = null; } $selection = ExecMethod2('addressbook.addressbook_bo.search', array(), true, '', '','',false,'AND',false,$col_filter); //$uicontacts->get_rows($query,$selection,$readonlys,true); } elseif ($options['selection'] == 'filter') { $fields = importexport_helper_functions::get_filter_fields($_definition->application, $this); $filter = $_definition->filter; $known_fields = $this->ui->get_fields('supported'); $query = array(); // Handle ranges foreach($filter as $field => $value) { if($field == 'cat_id') { $query['col_filter'][$field] = implode(',',$value); continue; } // Birthdays in addressbook are formatted Y-m-d if($field == 'bday') { if($value['from']) { $query['col_filter'][] = "contact_bday >= " . $GLOBALS['egw']->db->quote(date('Y-m-d', (int)$value['from'])); } if($value['to']) { $query['col_filter'][] = "contact_bday <= " . $GLOBALS['egw']->db->quote(date('Y-m-d', (int)$value['to'])); } continue; } if(strpos($field, '#') !== 0) { $field = 'contact_'.$field; } $query['col_filter'][$field] = $value; if(!is_array($value) || (!$value['from'] && !$value['to'])) continue; // Ranges are inclusive, so should be provided that way (from 2 to 10 includes 2 and 10) if($value['from']) $query['col_filter'][] = "$field >= " . (int)$value['from']; if($value['to']) $query['col_filter'][] = "$field <= " . (int)$value['to']; unset($query['col_filter'][$field]); } $selection = ExecMethod2('addressbook.addressbook_bo.search', array(), true, '', '','',false,'AND',false,$query['col_filter']); } else { $selection = explode(',',$options['selection']); } $GLOBALS['egw_info']['flags']['currentapp'] = $old_app; if(bo_merge::hasExportLimit($export_limit) && !$limit_exception) { $selection = array_slice($selection, 0, $export_limit); } if($options['explode_multiselects']) { $customfields = config::get_customfields('addressbook'); $additional_fields = array(); $cat_obj = new categories('', 'addressbook'); foreach($options['explode_multiselects'] as $field => $explode) { switch($explode['explode']) { case self::MAIN_CATS: $cats = $cat_obj->return_array('mains', 0, false,'','ASC','',true); foreach($cats as $settings) { $additional_fields[$field][$settings['id']] = array( 'count' => 0, 'label' => $settings['name'], 'subs' => array(), ); $subs = $cat_obj->return_sorted_array(0, False, '', 'ASC', 'cat_name', True, $settings['id']); foreach($subs as $sub) { $name = $sub['name']; $path = $sub; while($path['parent'] != $settings['id']) { $path = $cat_obj->read($path['parent']); $name = $path['name'] . '/' . $name; } $additional_fields[$field][$settings['id']]['subs'][$sub['id']] = $name; } } break; case self::EACH_CAT: $cats = $cat_obj->return_array('all', 0, false,'','ASC','',true); foreach($cats as $settings) { $name = $settings['name']; $path = $settings; while($path['level'] != 0) { $path = $cat_obj->read($path['parent']); $name = $path['name'] . '/' . $name; } $additional_fields[$field][$settings['id']] = array( 'count' => 0, 'label' => $name ); } break; case self::EXPLODE: // Only works for custom fields $index = substr($field, 1); foreach($customfields[$index]['values'] as $key => $value) { $additional_fields[$field][$key] = array( 'count' => 0, 'label' => $customfields[$index]['label'] . ': ' . $value, ); } break; } } // Check records to see if additional fields are actually used foreach ($selection as $_contact) { if(is_array($_contact) && array_key_exists('photo', $_contact)) { unset($_contact['photo']); } if(is_array($_contact) && count($_contact) == 1 && $_contact['id']) { $_contact = $_contact['id']; } if(is_array($_contact) && $_contact['id']) { $contact = new addressbook_egw_record(); $contact->set_record($_contact); } else { $contact = new addressbook_egw_record($_contact); } foreach($additional_fields as $field => &$values) { if(!$contact->$field) continue; foreach($values as $value => &$settings) { if(!is_array($contact->$field)) { $contact->$field = explode(',', $contact->$field); } if(is_array($contact->$field) && in_array($value, $contact->$field)) { $settings['count']++; } elseif($contact->$field == $value) { $settings['count']++; } elseif($options['explode_multiselects'][$field]['explode'] == self::MAIN_CATS && array_intersect($contact->$field, array_keys($settings['subs']))) { $settings['count']++; } } } } unset($field); unset($value); unset($settings); // Add additional columns foreach($additional_fields as $field => $additional_values) { // Remove original unset($options['mapping'][$field]); // Add exploded $field_count = 0; foreach($additional_values as $value => $settings) { if($settings['count'] > 0) { $field_count += $settings['count']; $options['mapping'][$field.'-'.$value] = $settings['label']; } } if($field_count > 0) { // Set some options for converting $options['explode_multiselects'][$field]['values'] = $additional_values; } else { // Don't need this anymore unset($options['explode_multiselects'][$field]); } } } $export_object->set_mapping($options['mapping']); // $options['selection'] is array of identifiers as this plugin doesn't // support other selectors atm. foreach ($selection as $_contact) { if(is_array($_contact) && array_key_exists('photo', $_contact)) { unset($_contact['photo']); } if(is_array($_contact) && count($_contact) == 1 && $_contact['id']) { $_contact = $_contact['id']; } if(is_array($_contact) && $_contact['id']) { $contact = new addressbook_egw_record(); $contact->set_record($_contact); } else { $contact = new addressbook_egw_record($_contact); } // Some conversion $this->convert($contact, $options); if($options['convert']) { importexport_export_csv::convert($contact, addressbook_egw_record::$types, 'addressbook',$this->selects); } else { // Implode arrays, so they don't say 'Array' foreach($contact->get_record_array() as $key => $value) { if(is_array($value)) $contact->$key = implode(',', $value); } } $export_object->export_record($contact); unset($contact); } return $export_object; } /** * returns translated name of plugin * * @return string name */ public static function get_name() { return lang('Addressbook CSV export'); } /** * returns translated (user) description of plugin * * @return string descriprion */ public static function get_description() { return lang("Exports contacts from your Addressbook into a CSV File."); } /** * retruns file suffix for exported file * * @return string suffix */ public static function get_filesuffix() { return 'csv'; } public static function get_mimetype() { return 'text/csv'; } /** * Suggest a file name for the downloaded file * No suffix */ public function get_filename() { if(is_object($this->export_object) && $this->export_object->get_num_of_records() == 1) { return $this->export_object->record->get_title(); } return false; } /** * return html for options. * this way the plugin has all opertunities for options tab * * @return string html */ public function get_options_etpl() { } /** * returns slectors of this plugin via xajax * */ public function get_selectors_etpl() { return array( 'name' => 'importexport.export_csv_selectors', ); } /** * Convert some internal data to something with more meaning * * Dates, times, user IDs, category IDs */ public static function convert(addressbook_egw_record &$record, $options) { if ($record->tel_prefer) { $field = $record->tel_prefer; $record->tel_prefer = $record->$field; } if(!is_array($options['explode_multiselects'])) { return; } foreach((array)$options['explode_multiselects'] as $field => $explode_settings) { if(!is_array($record->$field)) $record->$field = explode(',', $record->$field); foreach((array)$explode_settings['values'] as $value => $settings) { $field_name = "$field-$value"; $record->$field_name = array(); if(is_array($record->$field) && in_array($value, $record->$field) || $record->$field == $value) { if($explode_settings['explode'] != self::MAIN_CATS) { $record->$field_name = $options['convert'] ? lang('Yes') : true; } elseif($options['convert']) { // 3 part assign due to magic get method $record_value = $record->$field_name; $record_value[] = $settings['label']; $record->$field_name = $record_value; } else { $record->$field_name = $value; } } if($explode_settings['explode'] == self::MAIN_CATS && count(array_intersect($record->$field, array_keys($settings['subs'])))) { // 3 part assign due to magic get method $record_value = $record->$field_name; if(!is_array($record_value)) $record_value = array($record_value); foreach(array_intersect($record->$field, array_keys($settings['subs'])) as $sub_id) { $record_value[] = $options['convert'] ? $settings['subs'][$sub_id] : $sub_id; } $record->$field_name = $record_value; } if(is_array($record->$field_name)) $record->$field_name = implode(($options['convert'] ? ', ' : ','), $record->$field_name); } } } protected function get_selects() { $this->selects = array( 'tid' => array('n' => 'Contact') ); foreach($this->ui->content_types as $tid => $data) { $this->selects['tid'][$tid] = $data['name']; } } /** * Adjust automatically generated filter fields */ public function get_filter_fields(Array &$filters) { unset($filters['last_event']); unset($filters['next_event']); foreach($filters as $field_name => &$settings) { if($this->selects[$field_name]) $settings['values'] = $this->selects[$field_name]; } $filters['owner'] = array( 'name' => 'owner', 'label' => 'addressbook', 'type' => 'select', 'rows' => 5, 'enhance' => true, 'values' => $this->ui->get_addressbooks(EGW_ACL_READ) ); } }