/**
  * Make sure given array of options is valid for $field.
  * Return list($local_opts, $sys_opts) to save for this $field.
  * Local options are saved to shop app config. System options to contacts app config.
  * If any of option sets returned is null, this field is skipped altogether.
  */
 protected static function tidyOpts($field, $fld_id, $opts)
 {
     if ($fld_id == '%FID%' || !is_array($opts) || !empty($opts['_deleted']) || empty($opts['localized_names'])) {
         return array(null, null);
     }
     if (!empty($opts['_disabled'])) {
         if (!empty($opts['_default_value_enabled']) && isset($opts['_default_value']) && strlen($opts['_default_value'])) {
             // A hack for region field: when user specifies region name, replace it with region code.
             // In case there's a region with code equal to another region's name, prefer the former.
             if ($field instanceof waContactRegionField) {
                 $rm = new waRegionModel();
                 $regions = $rm->select('code, code AS a')->where('code = s:0 OR name = s:0', $opts['_default_value'])->query()->fetchAll('code', true);
                 if ($regions && empty($regions[$opts['_default_value']])) {
                     $opts['_default_value'] = reset($regions);
                 }
             }
             return array(array('hidden' => true, 'value' => $opts['_default_value']), array());
         } else {
             return array(null, null);
         }
     }
     unset($opts['_disabled'], $opts['_type'], $opts['_deleted'], $opts['_default_value'], $opts['_default_value_enabled']);
     $sys_opts = array();
     if (in_array(get_class($field), array('waContactSelectField', 'waContactRadioSelectField', 'waContactChecklistField', 'waContactBranchField'))) {
         if (!empty($opts['options']) && is_array($opts['options'])) {
             if ($field instanceof waContactBranchField) {
                 if (empty($opts['hide']) || !is_array($opts['hide'])) {
                     $opts['hide'] = array();
                 }
             }
             // get rid of empty last element
             if ($el = trim(array_pop($opts['options']))) {
                 $opts['options'][] = $el;
             }
             $branch_hide = array();
             $select_options = array();
             foreach ($opts['options'] as $i => $v) {
                 $v = trim($v);
                 $select_options[$v] = $v;
                 if ($field instanceof waContactBranchField && !empty($opts['hide'][$i])) {
                     $branch_hide[$v] = explode(',', (string) $opts['hide'][$i]);
                 }
             }
             if (!$select_options) {
                 return array(null, null);
             }
             $sys_opts['options'] = $select_options;
             if ($field instanceof waContactBranchField) {
                 $sys_opts['hide'] = $branch_hide;
             }
         } else {
             if (!$field->getParameter('options')) {
                 // Never allow select-based field with no options to select from
                 return array(null, null);
             }
         }
         unset($opts['options']);
     } else {
         if ($field instanceof waContactCompositeField) {
             if (empty($opts['fields']) || !is_array($opts['fields'])) {
                 return array(null, null);
             }
             $subfields = array();
             $subfields_sys = array();
             $existing_subfields = $field->getFields();
             foreach ($opts['fields'] as $sf_id => $o) {
                 if ($sf_id == '%FID%' || !empty($o['_deleted'])) {
                     continue;
                 }
                 if (empty($existing_subfields[$sf_id])) {
                     $sf = self::createFromOpts($o, $opts['fields'] + $existing_subfields);
                     if (!$sf) {
                         continue;
                     }
                     // For conditional fields, update ID in database: replace temporary id with new one
                     if ($sf instanceof waContactConditionalField) {
                         $cfvm = new waContactFieldValuesModel();
                         $cfvm->changeField($sf_id, $sf->getId());
                     }
                     $sf_id = $sf->getId();
                 } else {
                     $sf = $existing_subfields[$sf_id];
                     $subfields_sys[$sf_id] = $sf;
                     // make sure it is saved to system config
                 }
                 list($o, $sys_o) = self::tidyOpts($sf, $sf_id, $o);
                 if ($o === null || $sys_o === null) {
                     continue;
                 }
                 if ($sf instanceof waContactConditionalField) {
                     $sys_o['parent_id'] = $fld_id;
                 }
                 $sf->setParameters($sys_o);
                 $subfields_sys[$sf_id] = $sf;
                 $subfields[$sf_id] = $o;
             }
             if (!$subfields) {
                 return array(null, null);
             }
             $opts['fields'] = $subfields;
             $sys_opts['fields'] = $subfields_sys;
         }
     }
     if ($field->getParameter('app_id') == 'shop') {
         $sys_opts += $opts;
         $opts = array();
         foreach (waContactFields::$customParameters as $k => $v) {
             if (isset($sys_opts[$k])) {
                 $opts[$k] = $sys_opts[$k];
             }
         }
     }
     if (empty($opts) && $opts !== null) {
         $opts = array('__dummy__' => 1);
     }
     return array($opts, $sys_opts);
 }