hellomoto Posted January 15, 2015 Share Posted January 15, 2015 Resources (Ryan's own): ImportPagesCSV FieldtypeMapMarker So I edit the accepted $fieldtypes on :76: /** * List of Fieldtypes that we support importing to * */ protected $fieldtypes = array( 'FieldtypePageTitle', 'FieldtypeText', 'FieldtypeTextarea', 'FieldtypeInteger', 'FieldtypeFloat', 'FieldtypeEmail', 'FieldtypeURL', 'FieldtypeCheckbox', 'FieldtypeFile', 'FieldtypePage', 'FieldtypeMapMarker', 'FieldtypePassword', 'FieldtypeRepeater' ); Page, MapMarker, Password and Repeater were added by me. Then alter importPageValue: /** * Assign a value to a page field * */ protected function importPageValue(Page $page, $name, $value) { $field = $this->fields->get($name); if($field->type instanceof FieldtypeFile) { $value = trim($value); // split delimeted data to an array $value = preg_split('/[\r\n\t|]+/', $value); if($field->maxFiles == 1) $value = array_shift($value); $data = $page->ImportPagesCSVData; $data[$name] = $value; $page->ImportPagesCSVData = $data; } elseif($field->type instanceof FieldtypePage) { $value = trim($value); if(wire("pages")->find("$name=$value")) $page->set($name, $value); } elseif($field->type instanceof FieldtypeMapMarker) { $value = trim($value); $page->set($name->address, $value); } elseif($field->type instanceof FieldtypeRepeater) { // } else { $page->set($name, $value); if($name == 'title') $page->name = $this->sanitizer->pageName($value, 2); // Sanitizer::translate elseif($name == 'fullname') { $page->name = $this->sanitizer->pageName($value, true); } } } Page import works with ID values, which was trivial to incorporate; passwords too. MapMarker and Repeater as you might guess do not. How can I save the map->address value? Hopefully it will update the corresponding map fields too but one thing at a time. As for the repeaters... LostKobrakai tipped me off to foreach($page->engines as $e) { foreach($e->fields as $field) { echo $field; echo $e->get($field); } } which works for their names and values, but in this function you're passed the field, and something like foreach($page->$field as $e) { foreach($e->fields as $field) { echo $field; echo $e->get($field); } } doesn't work... and what it would need to do inside anyway is check for a subfield whose name is equal to the column header (choose the repeater field itself e.g., engines in the select per repeater subfield value, e.g., engine_fueltype), then explode that cell value by pipes ('|'), and for each subvalue, populate the repeater#->subvalue... but before all that I need to be able to iterate through the subfields from the field in this function. Anyone have any ideas? Link to comment Share on other sites More sharing options...
hellomoto Posted January 15, 2015 Author Share Posted January 15, 2015 Or the repeater subfields could be added to the select list for the field connections directly... that would simplify the importPageValue part. But still... if I do /** * Build the "Step 2" form to connect the fields * */ protected function buildForm2() { $form = $this->modules->get("InputfieldForm"); $form->method = 'post'; $form->action = './'; $form->description = "Step 2: Connect the fields"; $form->value = "Below is a list of fields found in your CSV file. " . "For each of them, select the field it should import to. " . "Leave any fields you want to exclude blank. " . "Once finished, click 'Start Import' at the bottom of this page. " . "Note: any field names in your CSV file that match those in your site " . "will be automatically selected."; $fp = fopen($this->csvFilename, "r"); $data = fgetcsv($fp, 0, $this->session->csvDelimeter, $this->session->csvEnclosure); foreach($data as $key => $value) { $f = $this->modules->get("InputfieldSelect"); $f->name = "csv" . $key; $f->label = $value; $f->addOption(''); foreach($this->template->fieldgroup as $field) { $valid = false; foreach($this->fieldtypes as $ft) { if($field->type instanceof $ft) { $valid = true; break; } } if(!$valid) continue; if($field->type instanceof FieldtypeRepeater) { echo count($field->repeaterFields); foreach($field->repeaterFields as $item) { echo wire("fields")->get($item)->name . '<br/>'; //$label = wire("fields")->get($item); //$label = $item->name; //$f->addOption($item->name); } } $label = $field->name; $f->addOption($field->name, $label); if($field->name == $value) $f->attr('value', $field->name); } $form->add($f); } fclose($fp); $this->addSubmit($form, 'Start Import'); return $form; } That returns 8 for count($field->repeaterFields), which is correct. Yet, executing the next foreach statement echoes 23 iterations of name of each subfield. For example: repeater field = "engines", its repeaterFields = ["engine_field1", "engine_field2", "engine_field3", "engine_field4", "engine_field5", "engine_field6", "engine_field7", "engine_field8"] and each of those are echoed out together -- 23x. Should just be once, for a total of 8 lines, not 184... Link to comment Share on other sites More sharing options...
LostKobrakai Posted January 15, 2015 Share Posted January 15, 2015 The repeater field value should be a pageArray, with all the repeater pages. Problem with repeaters, you're only coping fields right now. But repeaters are own hidden pages, which have to be generated before you can copy over the fields. Have a look here how to handle repeaters from the api side: http://processwire.com/api/fieldtypes/repeaters/ } elseif($field->type instanceof FieldtypeRepeater) { foreach($value as $e){ … } } For the map marker: Did you take a look what's being returned by $value? I doubt it's a string so $value = trim($value); doesn't do a thing. Try this, as $value should carry address as part of it, after a quick look at the source of the module. $page->set($name, $value); Link to comment Share on other sites More sharing options...
hellomoto Posted January 17, 2015 Author Share Posted January 17, 2015 I know repeaters are pages... For my main template that I am trying to get this to work for primarily, I have a repeater field engines with the default ready set to 2. So I would assume that these are created nonetheless when creating a page of that template via the API... This is tricky. I think perhaps the individual repeater fields should be included in the fields list when matching them prior to actually importing and then separate the values into repeaters on import? Anyway I think I'll try to get the mapmarker working first. The $value in importPageValue isn't what's returned by MapMarker, it's the value you're setting for the field, from the CSV. Link to comment Share on other sites More sharing options...
hellomoto Posted January 17, 2015 Author Share Posted January 17, 2015 Teppo got me to realize that I can simply do $page->$field->address = $value. So now map marker address can be imported which means it's time to tackle the repeaters... oy. 1 Link to comment Share on other sites More sharing options...
hellomoto Posted January 18, 2015 Author Share Posted January 18, 2015 Actually I don't think repeaters really can be set in importPageValue, because the column header isn't passed to it. So it would be better to set them as options in build form 2 (and more direct). Link to comment Share on other sites More sharing options...
theoretic Posted July 22, 2015 Share Posted July 22, 2015 Great mod. But importing Map Marker didn't work for me. Could anyone help please?Also posted this here:https://processwire.com/talk/topic/383-module-import-pages-from-csv-file/page-9 Link to comment Share on other sites More sharing options...
adrian Posted July 23, 2015 Share Posted July 23, 2015 Great mod. But importing Map Marker didn't work for me. Could anyone help please? Also posted this here: https://processwire.com/talk/topic/383-module-import-pages-from-csv-file/page-9 I see that you aren't following either topic so not sure if you will see these responses, but I posted a detailed response about how you can use Batch Child Editor for importing CSV files into pages with MapMarker fields in response to your post in the other thread. Hope that helps. Link to comment Share on other sites More sharing options...
theoretic Posted July 23, 2015 Share Posted July 23, 2015 Reading docs may really help sometimes... Quote from the @hellomoto's code: elseif($field->type instanceof FieldtypeMapMarker) { $value = trim($value); $page->set($name->address, $value); } And now some code from Map Marker docs ( https://processwire.com/talk/topic/9711-map-marker-map/ ): $page->marker->address = 'Disney Land'; Now it's obvious that Hellomoto's code should be like this: elseif($field->type instanceof FieldtypeMapMarker) { $value = trim($value); $page->$name->address = $value; } Tried this, works like a charm. Lat and Lng subfields are generated automagically if the address is more or less correct. Thanks @Hellomoto for a great mod! @Ryan, maybe it's time to add this to Your original module? Link to comment Share on other sites More sharing options...
Albert Posted February 7, 2017 Share Posted February 7, 2017 code should be: elseif($field->type instanceof FieldtypeMapMarker) { $value = trim($value); //$page->set($name->address, $value); $page->$field->$name = $value; } Link to comment Share on other sites More sharing options...
hellomoto Posted April 15, 2017 Author Share Posted April 15, 2017 (edited) On 7/23/2015 at 4:26 PM, theoretic said: Reading docs may really help sometimes... Quote from the @hellomoto's code: elseif($field->type instanceof FieldtypeMapMarker) { $value = trim($value); $page->set($name->address, $value); } And now some code from Map Marker docs ( https://processwire.com/talk/topic/9711-map-marker-map/ ): $page->marker->address = 'Disney Land'; Now it's obvious that Hellomoto's code should be like this: elseif($field->type instanceof FieldtypeMapMarker) { $value = trim($value); $page->$name->address = $value; } Tried this, works like a charm. Lat and Lng subfields are generated automagically if the address is more or less correct. Thanks @Hellomoto for a great mod! @Ryan, maybe it's time to add this to Your original module? This is true, and is what I have, but it's not working in another custom import script I'm working on currently: function importCSV($filepath, $template, $parent_id = null, $grandparent_id = null) { $csv = array_map('str_getcsv', file($filepath)); array_walk($csv, function(&$a) use ($csv) { $a = array_combine($csv[0], $a); # set header keys }); array_shift($csv); # remove column header //echo '<pre>'; print_r($csv); echo '</pre>'; foreach($csv as $r) { $p = new Page(); $p->name = wire('sanitizer')->pageName($r['title']); $p->template = $template; if($parent_id !== 0||null) { $p->parent_id = $parent_id; } elseif($parent_id == 0||null) { //echo $r['parent'].' '; $parent = wire('sanitizer')->pageName($r['parent']); $parent = str_replace('---','-',$parent); //echo $parent.' ';//echo $grandparent_id.'gp '; $parent = wire('pages')->get('title=' . $r['parent'] . ', parent_id=' . $grandparent_id)->id; //echo $parent.'p '; $p->parent_id = $parent; unset($r['parent']); } $p->save(); $p->of(false); foreach($r as $k=>$v) { $v = trim($v); $fieldtype = wire('fields')->get('name='.$k)->type; if($fieldtype = 'FieldtypeImage') { $imgs = explode('|', $v); foreach($imgs as $i) { $p->$k = $i; } } elseif($fieldtype = 'FieldtypeMapMarker') { $p->set($k->address, $v); // $p->$k->address = $v; } else $p->$k = $v; } $p->save(); //echo '<br>'; } } I have tried the way you mention here that's commented out in my code as well, to no avail. Edit: It should be $p->$k->set('address', $v); Edited February 4 by hellomoto Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now