]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - modules/Import/views/view.step3.php
Release 6.5.0
[Github/sugarcrm.git] / modules / Import / views / view.step3.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM Community Edition is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38 /*********************************************************************************
39
40  * Description: view handler for step 3 of the import process
41  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
42  * All Rights Reserved.
43  ********************************************************************************/
44 require_once('modules/Import/views/ImportView.php');
45 require_once('modules/Import/sources/ImportFile.php');
46 require_once('modules/Import/ImportFileSplitter.php');
47 require_once('modules/Import/ImportCacheFiles.php');
48 require_once('modules/Import/ImportDuplicateCheck.php');
49
50 require_once('include/upload_file.php');
51
52 class ImportViewStep3 extends ImportView
53 {
54
55     protected $pageTitleKey = 'LBL_STEP_3_TITLE';
56     protected $currentFormID = 'importstep3';
57     protected $previousAction = 'Confirm';
58     protected $nextAction = 'dupcheck';
59
60         /**
61      * @see SugarView::display()
62      */
63         public function display()
64     {
65         global $mod_strings, $app_strings, $current_user, $sugar_config, $app_list_strings, $locale;
66
67         $this->ss->assign("IMPORT_MODULE", $_REQUEST['import_module']);
68         $has_header = ( isset( $_REQUEST['has_header']) ? 1 : 0 );
69         $sugar_config['import_max_records_per_file'] = ( empty($sugar_config['import_max_records_per_file']) ? 1000 : $sugar_config['import_max_records_per_file'] );
70         $this->ss->assign("CURRENT_STEP", $this->currentStep);
71         // attempt to lookup a preexisting field map
72         // use the custom one if specfied to do so in step 1
73         $mapping_file = new ImportMap();
74         $field_map = $mapping_file->set_get_import_wizard_fields();
75         $default_values = array();
76                 $ignored_fields = array();
77
78         if ( !empty( $_REQUEST['source_id']))
79         {
80             $GLOBALS['log']->fatal("Loading import map properties.");
81             $mapping_file = new ImportMap();
82             $mapping_file->retrieve( $_REQUEST['source_id'],false);
83             $_REQUEST['source'] = $mapping_file->source;
84             $has_header = $mapping_file->has_header;
85             if (isset($mapping_file->delimiter))
86                 $_REQUEST['custom_delimiter'] = $mapping_file->delimiter;
87             if (isset($mapping_file->enclosure))
88                 $_REQUEST['custom_enclosure'] = htmlentities($mapping_file->enclosure);
89             $field_map = $mapping_file->getMapping();
90             //print_r($field_map);die();
91                         $default_values = $mapping_file->getDefaultValues();
92             $this->ss->assign("MAPNAME",$mapping_file->name);
93             $this->ss->assign("CHECKMAP",'checked="checked" value="on"');
94         }
95         else
96         {
97             $classname = $this->getMappingClassName(ucfirst($_REQUEST['source']));
98
99             //Set the $_REQUEST['source'] to be 'other' for ImportMapOther special case
100             if($classname == 'ImportMapOther')
101             {
102                 $_REQUEST['source'] = 'other';
103             }
104
105             if (class_exists($classname))
106             {
107                 $mapping_file = new $classname;
108                 $ignored_fields = $mapping_file->getIgnoredFields($_REQUEST['import_module']);
109                 $field_map2 = $mapping_file->getMapping($_REQUEST['import_module']);
110                 $field_map = array_merge($field_map,$field_map2);
111             }
112         }
113
114         $delimiter = $this->getRequestDelimiter();
115         
116         $this->ss->assign("CUSTOM_DELIMITER", $delimiter);
117         $this->ss->assign("CUSTOM_ENCLOSURE", ( !empty($_REQUEST['custom_enclosure']) ? $_REQUEST['custom_enclosure'] : "" ));
118
119        //populate import locale  values from import mapping if available, these values will be used througout the rest of the code path
120
121         $uploadFileName = $_REQUEST['file_name'];
122
123         // Now parse the file and look for errors
124         $importFile = new ImportFile( $uploadFileName, $delimiter, html_entity_decode($_REQUEST['custom_enclosure'],ENT_QUOTES), FALSE);
125
126         if ( !$importFile->fileExists() ) {
127             $this->_showImportError($mod_strings['LBL_CANNOT_OPEN'],$_REQUEST['import_module'],'Step2');
128             return;
129         }
130
131         $charset = $importFile->autoDetectCharacterSet();
132
133         // retrieve first 3 rows
134         $rows = array();
135
136         //Keep track of the largest row count found.
137         $maxFieldCount = 0;
138         for ( $i = 0; $i < 3; $i++ )
139         {
140             $rows[] = $importFile->getNextRow();
141             $maxFieldCount = $importFile->getFieldCount() > $maxFieldCount ?  $importFile->getFieldCount() : $maxFieldCount;
142         }
143         $ret_field_count = $maxFieldCount;
144
145         // Bug 14689 - Parse the first data row to make sure it has non-empty data in it
146         $isempty = true;
147         if ( $rows[(int)$has_header] != false ) {
148             foreach ( $rows[(int)$has_header] as $value ) {
149                 if ( strlen(trim($value)) > 0 ) {
150                     $isempty = false;
151                     break;
152                 }
153             }
154         }
155
156         if ($isempty || $rows[(int)$has_header] == false) {
157             $this->_showImportError($mod_strings['LBL_NO_LINES'],$_REQUEST['import_module'],'Step2');
158             return;
159         }
160
161         // save first row to send to step 4
162         $this->ss->assign("FIRSTROW", base64_encode(serialize($rows[0])));
163
164         // Now build template
165         $this->ss->assign("TMP_FILE", $uploadFileName );
166         $this->ss->assign("SOURCE", $_REQUEST['source'] );
167         $this->ss->assign("TYPE", $_REQUEST['type'] );
168         $this->ss->assign("DELETE_INLINE_PNG",  SugarThemeRegistry::current()->getImage('basic_search','align="absmiddle" alt="'.$app_strings['LNK_DELETE'].'" border="0"'));
169         $this->ss->assign("PUBLISH_INLINE_PNG",  SugarThemeRegistry::current()->getImage('advanced_search','align="absmiddle" alt="'.$mod_strings['LBL_PUBLISH'].'" border="0"'));
170
171         $this->instruction = 'LBL_SELECT_MAPPING_INSTRUCTION';
172         $this->ss->assign('INSTRUCTION', $this->getInstruction());
173
174         $this->ss->assign("MODULE_TITLE", $this->getModuleTitle(false));
175         $this->ss->assign("STEP4_TITLE",
176             strip_tags(str_replace("\n","",getClassicModuleTitle(
177                 $mod_strings['LBL_MODULE_NAME'],
178                 array($mod_strings['LBL_MODULE_NAME'],$mod_strings['LBL_STEP_4_TITLE']),
179                 false
180                 )))
181             );
182         $this->ss->assign("HEADER", $app_strings['LBL_IMPORT']." ". $mod_strings['LBL_MODULE_NAME']);
183
184         // we export it as email_address, but import as email1
185         $field_map['email_address'] = 'email1';
186
187         // build each row; row count is determined by the the number of fields in the import file
188         $columns = array();
189         $mappedFields = array();
190
191         // this should be populated if the request comes from a 'Back' button click
192         $importColumns = $this->getImportColumns();
193         $column_sel_from_req = false;
194         if (!empty($importColumns)) {
195             $column_sel_from_req = true;
196         }
197
198         for($field_count = 0; $field_count < $ret_field_count; $field_count++) {
199             // See if we have any field map matches
200             $defaultValue = "";
201             // Bug 31260 - If the data rows have more columns than the header row, then just add a new header column
202             if ( !isset($rows[0][$field_count]) )
203                 $rows[0][$field_count] = '';
204             // See if we can match the import row to a field in the list of fields to import
205             $firstrow_name = trim(str_replace(":","",$rows[0][$field_count]));
206             if ($has_header && isset( $field_map[$firstrow_name] ) ) {
207                 $defaultValue = $field_map[$firstrow_name];
208             }
209             elseif (isset($field_map[$field_count])) {
210                 $defaultValue = $field_map[$field_count];
211             }
212             elseif (empty( $_REQUEST['source_id'])) {
213                 $defaultValue = trim($rows[0][$field_count]);
214             }
215
216             // build string of options
217             $fields  = $this->bean->get_importable_fields();
218             $options = array();
219             $defaultField = '';
220             global $current_language;
221                     $moduleStrings = return_module_language($current_language, $this->bean->module_dir);
222
223             foreach ( $fields as $fieldname => $properties ) {
224                 // get field name
225                 if (!empty($moduleStrings['LBL_EXPORT_'.strtoupper($fieldname)]) )
226                 {
227                      $displayname = str_replace(":","", $moduleStrings['LBL_EXPORT_'.strtoupper($fieldname)] );
228                 }
229                 else if (!empty ($properties['vname']))
230                 {
231                     $displayname = str_replace(":","",translate($properties['vname'] ,$this->bean->module_dir));
232                 }
233                 else
234                     $displayname = str_replace(":","",translate($properties['name'] ,$this->bean->module_dir));
235                 // see if this is required
236                 $req_mark  = "";
237                 $req_class = "";
238                 if ( array_key_exists($fieldname, $this->bean->get_import_required_fields()) ) {
239                     $req_mark  = ' ' . $app_strings['LBL_REQUIRED_SYMBOL'];
240                     $req_class = ' class="required" ';
241                 }
242                 // see if we have a match
243                 $selected = '';
244                 if ($column_sel_from_req && isset($importColumns[$field_count])) {
245                     if ($fieldname == $importColumns[$field_count]) {
246                         $selected = ' selected="selected" ';
247                         $defaultField = $fieldname;
248                         $mappedFields[] = $fieldname;
249                     }
250                 } else {
251                     if ( !empty($defaultValue) && !in_array($fieldname,$mappedFields)
252                                                     && !in_array($fieldname,$ignored_fields) )
253                     {
254                         if ( strtolower($fieldname) == strtolower($defaultValue)
255                             || strtolower($fieldname) == str_replace(" ","_",strtolower($defaultValue))
256                             || strtolower($displayname) == strtolower($defaultValue)
257                             || strtolower($displayname) == str_replace(" ","_",strtolower($defaultValue)) )
258                         {
259                             $selected = ' selected="selected" ';
260                             $defaultField = $fieldname;
261                             $mappedFields[] = $fieldname;
262                         }
263                     }
264                 }
265                 // get field type information
266                 $fieldtype = '';
267                 if ( isset($properties['type'])
268                         && isset($mod_strings['LBL_IMPORT_FIELDDEF_' . strtoupper($properties['type'])]) )
269                     $fieldtype = ' [' . $mod_strings['LBL_IMPORT_FIELDDEF_' . strtoupper($properties['type'])] . '] ';
270                 if ( isset($properties['comment']) )
271                     $fieldtype .= ' - ' . $properties['comment'];
272                 $options[$displayname.$fieldname] = '<option value="'.$fieldname.'" title="'. $displayname . htmlentities($fieldtype) . '"'
273                     . $selected . $req_class . '>' . $displayname . $req_mark . '</option>\n';
274             }
275
276             // get default field value
277             $defaultFieldHTML = '';
278             if ( !empty($defaultField) ) {
279                 $defaultFieldHTML = getControl(
280                     $_REQUEST['import_module'],
281                     $defaultField,
282                     $fields[$defaultField],
283                     ( isset($default_values[$defaultField]) ? $default_values[$defaultField] : '' )
284                     );
285             }
286
287             if ( isset($default_values[$defaultField]) )
288                 unset($default_values[$defaultField]);
289
290             // Bug 27046 - Sort the column name picker alphabetically
291             ksort($options);
292
293             // to be displayed in UTF-8 format
294             if (!empty($charset) && $charset != 'UTF-8') {
295                 if (isset($rows[1][$field_count])) {
296                     $rows[1][$field_count] = $locale->translateCharset($rows[1][$field_count], $charset);
297                 }
298             }
299
300             $cellOneData = isset($rows[0][$field_count]) ? $rows[0][$field_count] : '';
301             $cellTwoData = isset($rows[1][$field_count]) ? $rows[1][$field_count] : '';
302             $cellThreeData = isset($rows[2][$field_count]) ? $rows[2][$field_count] : '';
303             $columns[] = array(
304                 'field_choices' => implode('',$options),
305                 'default_field' => $defaultFieldHTML,
306                 'cell1'         => str_replace("&quot;",'', htmlspecialchars($cellOneData)),
307                 'cell2'         => str_replace("&quot;",'', htmlspecialchars($cellTwoData)),
308                 'cell3'         => str_replace("&quot;",'', htmlspecialchars($cellThreeData)),
309                 'show_remove'   => false,
310                 );
311         }
312
313         // add in extra defaulted fields if they are in the mapping record
314         if ( count($default_values) > 0 ) {
315             foreach ( $default_values as $field_name => $default_value ) {
316                 // build string of options
317                 $fields  = $this->bean->get_importable_fields();
318                 $options = array();
319                 $defaultField = '';
320                 foreach ( $fields as $fieldname => $properties ) {
321                     // get field name
322                     if (!empty ($properties['vname']))
323                         $displayname = str_replace(":","",translate($properties['vname'] ,$this->bean->module_dir));
324                     else
325                         $displayname = str_replace(":","",translate($properties['name'] ,$this->bean->module_dir));
326                     // see if this is required
327                     $req_mark  = "";
328                     $req_class = "";
329                     if ( array_key_exists($fieldname, $this->bean->get_import_required_fields()) ) {
330                         $req_mark  = ' ' . $app_strings['LBL_REQUIRED_SYMBOL'];
331                         $req_class = ' class="required" ';
332                     }
333                     // see if we have a match
334                     $selected = '';
335                     if ( strtolower($fieldname) == strtolower($field_name)
336                                                         && !in_array($fieldname,$mappedFields)
337                                                         && !in_array($fieldname,$ignored_fields) ) {
338                         $selected = ' selected="selected" ';
339                         $defaultField = $fieldname;
340                         $mappedFields[] = $fieldname;
341                     }
342                     // get field type information
343                     $fieldtype = '';
344                     if ( isset($properties['type'])
345                             && isset($mod_strings['LBL_IMPORT_FIELDDEF_' . strtoupper($properties['type'])]) )
346                         $fieldtype = ' [' . $mod_strings['LBL_IMPORT_FIELDDEF_' . strtoupper($properties['type'])] . '] ';
347                     if ( isset($properties['comment']) )
348                         $fieldtype .= ' - ' . $properties['comment'];
349                     $options[$displayname.$fieldname] = '<option value="'.$fieldname.'" title="'. $displayname . $fieldtype . '"' . $selected . $req_class . '>'
350                         . $displayname . $req_mark . '</option>\n';
351                 }
352
353                 // get default field value
354                 $defaultFieldHTML = '';
355                 if ( !empty($defaultField) ) {
356                     $defaultFieldHTML = getControl(
357                         $_REQUEST['import_module'],
358                         $defaultField,
359                         $fields[$defaultField],
360                         $default_value
361                         );
362                 }
363
364                 // Bug 27046 - Sort the column name picker alphabetically
365                 ksort($options);
366
367                 $columns[] = array(
368                     'field_choices' => implode('',$options),
369                     'default_field' => $defaultFieldHTML,
370                     'show_remove'   => true,
371                     );
372
373                 $ret_field_count++;
374             }
375         }
376
377         $this->ss->assign("COLUMNCOUNT",$ret_field_count);
378         $this->ss->assign("rows",$columns);
379
380         $this->ss->assign('datetimeformat', $GLOBALS['timedate']->get_cal_date_time_format());
381
382         // handle building index selector
383         global $dictionary, $current_language;
384
385         // show notes
386         if ( $this->bean instanceof Person )
387             $module_key = "LBL_CONTACTS_NOTE_";
388         elseif ( $this->bean instanceof Company )
389             $module_key = "LBL_ACCOUNTS_NOTE_";
390         else
391             $module_key = "LBL_".strtoupper($_REQUEST['import_module'])."_NOTE_";
392         $notetext = '';
393         for ($i = 1;isset($mod_strings[$module_key.$i]);$i++) {
394             $notetext .= '<li>' . $mod_strings[$module_key.$i] . '</li>';
395         }
396         $this->ss->assign("NOTETEXT",$notetext);
397         $this->ss->assign("HAS_HEADER",($has_header ? 'on' : 'off' ));
398
399         // get list of required fields
400         $required = array();
401         foreach ( array_keys($this->bean->get_import_required_fields()) as $name ) {
402             $properties = $this->bean->getFieldDefinition($name);
403             if (!empty ($properties['vname']))
404                 $required[$name] = str_replace(":","",translate($properties['vname'] ,$this->bean->module_dir));
405             else
406                 $required[$name] = str_replace(":","",translate($properties['name'] ,$this->bean->module_dir));
407         }
408         // include anything needed for quicksearch to work
409         require_once("include/TemplateHandler/TemplateHandler.php");
410         // Bug #46879 : createQuickSearchCode() function in IBM RTC call function getQuickSearchDefaults() to get instance and then getQSDLookup() function
411         // if we call this function as static it replaces context and use ImportViewStep3 as $this in getQSDLookup()
412         $template_handler = new TemplateHandler();
413         $quicksearch_js = $template_handler->createQuickSearchCode($fields,$fields,'importstep3');
414
415         $this->ss->assign("QS_JS", $quicksearch_js);
416         $this->ss->assign("JAVASCRIPT", $this->_getJS($required));
417
418         $this->ss->assign('required_fields',implode(', ',$required));
419         $this->ss->assign('CSS', $this->_getCSS());
420
421         $content = $this->ss->fetch($this->getCustomFilePathIfExists('modules/Import/tpls/step3.tpl'));
422         $this->ss->assign("CONTENT",$content);
423         $this->ss->display($this->getCustomFilePathIfExists('modules/Import/tpls/wizardWrapper.tpl'));
424
425     }
426
427
428     /**
429      * getMappingClassName
430      *
431      * This function returns the name of a mapping class used to generate the mapping of an import source.
432      * It first checks to see if an equivalent custom source map exists in custom/modules/Imports/maps directory
433      * and returns this class name if found.  Searches are made for sources with a ImportMapCustom suffix first
434      * and then ImportMap suffix.
435      *
436      * If no such custom file is found, the method then checks the modules/Imports/maps directory for a source
437      * mapping file.
438      *
439      * Lastly, if a source mapping file is still not located, it checks in
440      * custom/modules/Import/maps/ImportMapOther.php file exists, it uses the ImportMapOther class.
441      *
442      * @see display()
443      * @param string $source String name of the source mapping prefix
444      * @return string name of the mapping class name
445      */
446     protected function getMappingClassName($source)
447     {
448        // Try to see if we have a custom mapping we can use
449        // based upon the where the records are coming from
450        // and what module we are importing into
451        $name = 'ImportMap' . $source;
452        $customName = 'ImportMapCustom' . $source;
453
454        if (file_exists("custom/modules/Import/maps/{$customName}.php"))
455        {
456            require_once("custom/modules/Import/maps/{$customName}.php");
457            return $customName;
458        } else if (file_exists("custom/modules/Import/maps/{$name}.php")) {
459            require_once("custom/modules/Import/maps/{$name}.php");
460        } else if (file_exists("modules/Import/maps/{$name}.php")) {
461            require_once("modules/Import/maps/{$name}.php");
462        } else if (file_exists('custom/modules/Import/maps/ImportMapOther.php')) {
463            require_once('custom/modules/Import/maps/ImportMapOther.php');
464            return 'ImportMapOther';
465        }
466
467        return $name;
468     }
469
470
471     protected function getRequestDelimiter()
472     {
473         $delimiter = !empty($_REQUEST['custom_delimiter']) ? $_REQUEST['custom_delimiter'] : ",";
474
475         switch ($delimiter)
476         {
477             case "other":
478                 $delimiter = $_REQUEST['custom_delimiter_other'];
479                 break;
480             case '\t':
481                 $delimiter = "\t";
482                 break;
483         }       
484         return $delimiter;
485     }
486
487     protected function getImportColumns()
488     {
489         $importColumns = array();
490         foreach ($_REQUEST as $name => $value)
491         {
492             // only look for var names that start with "fieldNum"
493             if (strncasecmp($name, "colnum_", 7) != 0)
494                 continue;
495
496             // pull out the column position for this field name
497             $pos = substr($name, 7);
498
499                 // now mark that we've seen this field
500             $importColumns[$pos] = $value;
501         }
502
503         return $importColumns;
504     }
505
506     protected function _getCSS()
507     {
508         return <<<EOCSS
509             <style>
510                 textarea { width: 20em }
511                                 .detail tr td[scope="row"] {
512                                         text-align:left
513                                 }
514                 span.collapse{
515                     background: transparent url('index.php?entryPoint=getImage&themeName=Sugar&themeName=Sugar&imageName=sugar-yui-sprites.png') no-repeat 0 -90px;
516                     padding-left: 10px;
517                     cursor: pointer;
518                 }
519
520                 span.expand{
521                     background: transparent url('index.php?entryPoint=getImage&themeName=Sugar&themeName=Sugar&imageName=sugar-yui-sprites.png') no-repeat -0 -110px;
522                     padding-left: 10px;
523                      cursor: pointer;
524                 }
525                 .removeButton{
526                     border: none !important;
527                     background-image: none !important;
528                     background-color: transparent;
529                     padding: 0px;
530                 }
531
532                 #importNotes ul{
533                         margin: 0px;
534                         margin-top: 10px;
535                         padding-left: 20px;
536                 }
537
538             </style>
539 EOCSS;
540
541     }
542     /**
543      * Returns JS used in this view
544      *
545      * @param  array $required fields that are required for the import
546      * @return string HTML output with JS code
547      */
548     protected function _getJS($required)
549     {
550         global $mod_strings;
551
552         $print_required_array = "";
553         foreach ($required as $name=>$display) {
554             $print_required_array .= "required['$name'] = '". sanitize($display) . "';\n";
555         }
556         $sqsWaitImage = SugarThemeRegistry::current()->getImageURL('sqsWait.gif');
557
558         return <<<EOJAVASCRIPT
559
560     document.getElementById('goback').onclick = function()
561     {
562         document.getElementById('{$this->currentFormID}').action.value = '{$this->previousAction}';
563         //bug #48960: CSS didn't load when use click back in the step2 (external sources are selected for contacts)
564         //need to unset 'to_pdf' in extstep1.tpl
565         if (document.getElementById('{$this->currentFormID}').to_pdf)
566         {
567             document.getElementById('{$this->currentFormID}').to_pdf.value = '';
568         }
569         return true;
570     }
571
572 ImportView = {
573
574     validateMappings : function()
575     {
576         // validate form
577         clear_all_errors();
578         var form = document.getElementById('{$this->currentFormID}');
579         var hash = new Object();
580         var required = new Object();
581         $print_required_array
582         var isError = false;
583         for ( i = 0; i < form.length; i++ ) {
584             if ( form.elements[i].name.indexOf("colnum",0) == 0) {
585                 if ( form.elements[i].value == "-1") {
586                     continue;
587                 }
588                 if ( hash[ form.elements[i].value ] == 1) {
589                     isError = true;
590                     add_error_style('{$this->currentFormID}',form.elements[i].name,"{$mod_strings['ERR_MULTIPLE']}");
591                 }
592                 hash[form.elements[i].value] = 1;
593             }
594         }
595
596         // check for required fields
597         for(var field_name in required) {
598             // contacts hack to bypass errors if full_name is set
599             if (field_name == 'last_name' &&
600                     hash['full_name'] == 1) {
601                 continue;
602             }
603             if ( hash[ field_name ] != 1 ) {
604                 isError = true;
605                 add_error_style('{$this->currentFormID}',form.colnum_0.name,
606                     "{$mod_strings['ERR_MISSING_REQUIRED_FIELDS']} " + required[field_name]);
607             }
608         }
609
610         // return false if we got errors
611         if (isError == true) {
612             return false;
613         }
614
615
616         return true;
617
618     }
619
620 }
621
622 if( document.getElementById('gonext') )
623 {
624     document.getElementById('gonext').onclick = function(){
625
626         if( ImportView.validateMappings() )
627         {
628             // Move on to next step
629             document.getElementById('{$this->currentFormID}').action.value = '{$this->nextAction}';
630             return true;
631         }
632         else
633             return false;
634     }
635 }
636
637 // handle adding new row
638 document.getElementById('addrow').onclick = function(){
639
640     toggleDefaultColumnVisibility(false);
641     rownum = document.getElementById('{$this->currentFormID}').columncount.value;
642     newrow = document.createElement("tr");
643
644     column0 = document.getElementById('row_0_col_0').cloneNode(true);
645     column0.id = 'row_' + rownum + '_col_0';
646     for ( i = 0; i < column0.childNodes.length; i++ ) {
647         if ( column0.childNodes[i].name == 'colnum_0' ) {
648             column0.childNodes[i].name = 'colnum_' + rownum;
649             column0.childNodes[i].onchange = function(){
650                 var module    = document.getElementById('{$this->currentFormID}').import_module.value;
651                 var fieldname = this.value;
652                 var matches   = /colnum_([0-9]+)/i.exec(this.name);
653                 var fieldnum  = matches[1];
654                 if ( fieldname == -1 ) {
655                     document.getElementById('defaultvaluepicker_'+fieldnum).innerHTML = '';
656                     return;
657                 }
658                 document.getElementById('defaultvaluepicker_'+fieldnum).innerHTML = '<img src="{$sqsWaitImage}" />'
659                 YAHOO.util.Connect.asyncRequest('GET', 'index.php?module=Import&action=GetControl&import_module='+module+'&field_name='+fieldname,
660                     {
661                         success: function(o)
662                         {
663                                 document.getElementById('defaultvaluepicker_'+fieldnum).innerHTML = o.responseText;
664                             SUGAR.util.evalScript(o.responseText);
665                             enableQS(true);
666                         },
667                         failure: function(o) {/*failure handler code*/}
668                     });
669             }
670         }
671     }
672
673     var removeButton = document.createElement("button");
674     removeButton.title = "{$mod_strings['LBL_REMOVE_ROW']}";
675     removeButton.id = 'deleterow_' + rownum;
676     removeButton.className = "removeButton";
677     var imgButton = document.createElement("img");
678     imgButton.src = "index.php?entryPoint=getImage&themeName=Sugar&imageName=id-ff-remove.png";
679     removeButton.appendChild(imgButton);
680
681
682     if ( document.getElementById('row_0_header') ) {
683         column1 = document.getElementById('row_0_header').cloneNode(true);
684         column1.innerHTML = '&nbsp;';
685         column1.style.textAlign = "right";
686         newrow.appendChild(column1);
687         column1.appendChild(removeButton);
688     }
689
690     newrow.appendChild(column0);
691
692
693
694     column3 = document.createElement('td');
695     column3.className = 'tabDetailViewDL';
696     if ( !document.getElementById('row_0_header') ) {
697         column3.colSpan = 2;
698     }
699
700     newrow.appendChild(column3);
701
702     column2 = document.getElementById('defaultvaluepicker_0').cloneNode(true);
703     column2.id = 'defaultvaluepicker_' + rownum;
704     newrow.appendChild(column2);
705
706     document.getElementById('{$this->currentFormID}').columncount.value = parseInt(document.getElementById('{$this->currentFormID}').columncount.value) + 1;
707
708     document.getElementById('row_0_col_0').parentNode.parentNode.insertBefore(newrow,this.parentNode.parentNode);
709
710     document.getElementById('deleterow_' + rownum).onclick = function(){
711         this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);
712     }
713
714
715 }
716
717 function toggleDefaultColumnVisibility(hide)
718 {
719     if( typeof(hide) != 'undefined' && typeof(hide) == 'boolean')
720     {
721         var currentStyle = hide ? '' : 'none';
722     }
723     else
724     {
725         var currentStyle = YAHOO.util.Dom.getStyle('default_column_header_span', 'display');
726     }
727     if(currentStyle == 'none')
728     {
729         var newStyle = '';
730         var bgColor = '#eeeeee';
731         YAHOO.util.Dom.addClass('hide_default_link', 'collapse');
732         YAHOO.util.Dom.removeClass('hide_default_link', 'expand');
733         var col2Rowspan = "1";
734     }
735     else
736     {
737         var newStyle = 'none';
738         var bgColor = '#dddddd';
739         YAHOO.util.Dom.addClass('hide_default_link', 'expand');
740         YAHOO.util.Dom.removeClass('hide_default_link', 'collapse');
741         var col2Rowspan = "2";
742     }
743
744     YAHOO.util.Dom.setStyle('default_column_header_span', 'display', newStyle);
745     YAHOO.util.Dom.setStyle('default_column_header', 'backgroundColor', bgColor);
746
747     //Toggle all rows.
748     var columnCount = document.getElementById('{$this->currentFormID}').columncount.value;
749     for(i=0;i<columnCount;i++)
750     {
751         YAHOO.util.Dom.setStyle('defaultvaluepicker_' + i, 'display', newStyle);
752         YAHOO.util.Dom.setAttribute('row_'+i+'_col_2', 'colspan', col2Rowspan);
753     }
754 }
755
756 var notesEl = document.getElementById('toggleNotes');
757 if(notesEl)
758 {
759     notesEl.onclick = function() {
760         if (document.getElementById('importNotes').style.display == 'none'){
761             document.getElementById('importNotes').style.display = '';
762             document.getElementById('toggleNotes').value='{$mod_strings['LBL_HIDE_NOTES']}';
763         }
764         else {
765             document.getElementById('importNotes').style.display = 'none';
766             document.getElementById('toggleNotes').value='{$mod_strings['LBL_SHOW_NOTES']}';
767         }
768     }
769 }
770
771
772 YAHOO.util.Event.onDOMReady(function(){
773     toggleDefaultColumnVisibility();
774     YAHOO.util.Event.addListener('hide_default_link', "click", toggleDefaultColumnVisibility);
775
776     var selects = document.getElementsByTagName('select');
777     for (var i = 0; i < selects.length; ++i ){
778         if (selects[i].name.indexOf("colnum_") != -1 ) {
779             // fetch the field input control via ajax
780             selects[i].onchange = function(){
781                 var module    = document.getElementById('{$this->currentFormID}').import_module.value;
782                 var fieldname = this.value;
783                 var matches   = /colnum_([0-9]+)/i.exec(this.name);
784                 var fieldnum  = matches[1];
785                 if ( fieldname == -1 ) {
786                     document.getElementById('defaultvaluepicker_'+fieldnum).innerHTML = '';
787                     return;
788                 }
789
790                 document.getElementById('defaultvaluepicker_'+fieldnum).innerHTML = '<img src="{$sqsWaitImage}" />'
791                 YAHOO.util.Connect.asyncRequest('GET', 'index.php?module=Import&action=GetControl&import_module='+module+'&field_name='+fieldname,
792                     {
793                         success: function(o)
794                         {
795                             document.getElementById('defaultvaluepicker_'+fieldnum).innerHTML = o.responseText;
796                             SUGAR.util.evalScript(o.responseText);
797                             enableQS(true);
798                         },
799                         failure: function(o) {/*failure handler code*/}
800                     });
801             }
802         }
803     }
804     var inputs = document.getElementsByTagName('input');
805     for (var i = 0; i < inputs.length; ++i ){
806         if (inputs[i].id.indexOf("deleterow_") != -1 ) {
807             inputs[i].onclick = function(){
808                 this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);
809             }
810         }
811     }
812 });
813
814 enableQS(false);
815
816
817 EOJAVASCRIPT;
818     }
819 }