Skip to content
This repository has been archived by the owner on Apr 5, 2018. It is now read-only.

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
Bob Olde Hampsink committed Oct 23, 2015
2 parents e4d2e39 + 35cb33d commit d5dd55f
Show file tree
Hide file tree
Showing 13 changed files with 167 additions and 65 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
Changelog
=================
###0.8.27###
- Allow custom options for categories and users too,
- Set user pending when status field is pending, closing issue #53
- Use correct category fieldlayout, closing issue #61
- Adds the ability to import in a specific locale, closing issue #62
- Revert the validate content option, closing issue #64
- Adds the ability to import specific ID's, closing issue #65
- Fix redirect after importing in some cases, closing issue #78

###0.8.26###
- Added the "registerImportOptionPaths" hook (thanks to @lindseydiloreto)
- Replace "sourceId" with "folderId" criteria when linking an asset field (thanks to @damiani)
Expand Down
2 changes: 1 addition & 1 deletion ImportPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function getName()
*/
public function getVersion()
{
return '0.8.26';
return '0.8.27';
}

/**
Expand Down
81 changes: 76 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Step 1. Select import options
- Delete Data — Will delete data for existing matched categories, entries, or users.

Step 2. Map CSV data
- Map the destination fields for the csv data.
- Map the destination fields for the CSV data.
- Select which fields will be used as criteria to match existing records to replace (update) or delete data.

And import!
Expand All @@ -27,20 +27,22 @@ Features
- Map CSV columns onto Fields
- Append, replace or delete data
- When replacing or deleting, you can build your own criteria for finding
- Has a hook "registerImportOperation" to parse special FieldType inputs if you want.
- Has events "onImportFinish" and "onBeforeImportDelete"
- Has a hook "registerImportOperation" to parse special field type inputs if you want.
- Has a hook "registerImportOptionPaths" to allow special field types to have a custom option (or options) in the mapping select menu.
- Has a hook "modifyImportRow" to allow special field types to customize data just before it gets imported.
- Has events "onImportFinish" and "onBeforeImportDelete"
- These will notify you when the import finishes or wants to delete an element
- Uses the Task service to import while you work on.
- Automatically detects CSV delimiters
- Will connect Entries (also Structures), Categories, Users and Assets by searching for them
- Will send a summary email when the task if finished
- View your import history
- Ability to revert imports

###Roadmap###
- Import more ElementTypes (Tags, Globals, Assets?) (0.8)
- Support JSON and XML (0.9)

Important:
=================
The plugin's folder should be named "import"
Expand Down Expand Up @@ -71,3 +73,72 @@ Upload (users)

Map fields
![Map](https://raw.githubusercontent.com/boboldehampsink/CraftImportPlugin/gh-pages/images/map.png)

Hooks
=================
### modifyImportRow

Manipulate the data as the import is running. You'll be able to tweak your data just before it goes into the database.

This code example is a good starting point:

```php
/**
* Modify data just before importing
*
* @param BaseElementModel $element The current element receiving import data.
* @param array $map Mapping of data between CSV -> Craft fields.
* @param array $data Raw data provided for this row.
*/
public function modifyImportRow($element, $map, $data)
{
// Map data to fields
$fields = array_combine($map, $data);

// Initialize content array
$content = array();

// Arrange your content in a way that makes sense for your plugin
foreach ($fields as $handle => $value) {
$content[$handle] = $value;
}

// Set modified content
$element->setContentFromPost($content);
}
```

The `foreach` loop is probably where you'll do the most customizing. However, feel free to edit any (or all) of this method to achieve your desired results.

### registerImportOptionPaths

Prep the field mapping before the import is run. This allows you to customize the `<select>` menu option(s) for your field.

When you are mapping your CSV columns to Craft fields, Import let's you choose which field you want to assign your data to. There is a `<select>` menu with a list of Craft fields, and you select the destination for each column.

The purpose of this hook is to give you the opportunity to replace the standard `<option>` tag with something custom. In essence, you are providing a template which contains a custom `<option>` (or multiple options) to handle the data mapping in a way that is more preferable for your field type.

Put this in your main MyPlugin.php file, and edit accordingly:

```php
/**
* For custom field types, replace default <option> with custom HTML
*
* @return array Mapping between custom field type -> custom <option> template
*/
public function registerImportOptionPaths()
{
return array(
'MyPlugin_MyFieldType' => 'myplugin/customImportOption.html',
);
}
```

You are being given the opportunity to say "for fields of this type, use my custom template in place of the default `<option>` tag". Make sure your `customImportOption.html` template outputs one or more `<option>` tags... They will be injected into the field select dropdown menu.

In summary:

1. Create a short template to replace the default `<option>`
2. Map that template to your field type with this hook

If you want to dig in the code a little more and see how it works in even greater detail, [check out this chunk of code here...](https://github.com/boboldehampsink/import/blob/00818471336c92d9461e174096a14f3d30b68697/templates/types/entry/_map.twig#L50-L58)
4 changes: 2 additions & 2 deletions controllers/ImportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,11 @@ public function actionImport()
craft()->userSession->setNotice(Craft::t('Import process started.'));

// Redirect to history
$this->redirect('import/history?task='.$task->id);
$this->redirect(UrlHelper::getCpUrl('import/history', array('task' => $task->id)));
} else {

// Redirect to history
$this->redirect('import/history');
$this->redirect(UrlHelper::getCpUrl('import/history'));
}
}
}
4 changes: 3 additions & 1 deletion models/Import_ElementModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
class Import_ElementModel extends BaseModel
{
const HandleId = 'id';
const HandleLocale = 'locale';
const HandleTitle = 'title';
const HandleAuthor = 'authorId';
const HandlePostDate = 'postDate';
Expand All @@ -29,6 +31,6 @@ class Import_ElementModel extends BaseModel
const HandleLastname = 'lastName';
const HandleEmail = 'email';
const HandleStatus = 'status';
const HandleLocale = 'preferredLocale';
const HandlePrefLocale = 'preferredLocale';
const HandlePassword = 'newPassword';
}
22 changes: 17 additions & 5 deletions services/Import_CategoryService.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,21 @@ public function delete(array $elements)
*/
public function prepForElementModel(array &$fields, BaseElementModel $element)
{
// Set ID
$id = Import_ElementModel::HandleId;
if (isset($fields[$id])) {
$element->$id = $fields[$id];
unset($fields[$id]);
}

// Set locale
$locale = Import_ElementModel::HandleLocale;
if (isset($fields[$locale])) {
$element->$locale = $fields[$locale];
$element->localeEnabled = true;
unset($fields[$locale]);
}

// Set slug
$slug = Import_ElementModel::HandleSlug;
if (isset($fields[$slug])) {
Expand Down Expand Up @@ -124,11 +139,8 @@ public function prepForElementModel(array &$fields, BaseElementModel $element)
*/
public function save(BaseElementModel &$element, $settings)
{
if ($settings->validate) {
return craft()->categories->saveCategory($element);
} else {
return craft()->elements->saveElement($element, false);
}
// Save category
return craft()->categories->saveCategory($element);
}

/**
Expand Down
26 changes: 17 additions & 9 deletions services/Import_EntryService.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,21 @@ public function delete(array $elements)
*/
public function prepForElementModel(array &$fields, BaseElementModel $element)
{
// Set ID
$id = Import_ElementModel::HandleId;
if (isset($fields[$id])) {
$element->$id = $fields[$id];
unset($fields[$id]);
}

// Set locale
$locale = Import_ElementModel::HandleLocale;
if (isset($fields[$locale])) {
$element->$locale = $fields[$locale];
$element->localeEnabled = true;
unset($fields[$locale]);
}

// Set author
$author = Import_ElementModel::HandleAuthor;
if (isset($fields[$author])) {
Expand Down Expand Up @@ -233,15 +248,8 @@ public function prepForElementModel(array &$fields, BaseElementModel $element)
*/
public function save(BaseElementModel &$element, $settings)
{
// Save element
if ($settings->validate) {
$result = craft()->entries->saveEntry($element);
} else {
$result = craft()->elements->saveElement($element, false);
}

// Save version
if ($result) {
// Save user
if (craft()->entries->saveEntry($element)) {

// If entry revisions are supported
if (craft()->getEdition() == Craft::Pro) {
Expand Down
30 changes: 16 additions & 14 deletions services/Import_UserService.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ public function delete(array $elements)
*/
public function prepForElementModel(array &$fields, BaseElementModel $element)
{
// Set ID
$id = Import_ElementModel::HandleId;
if (isset($fields[$id])) {
$element->$id = $fields[$id];
unset($fields[$id]);
}

// Set username
$username = Import_ElementModel::HandleUsername;
Expand Down Expand Up @@ -158,14 +164,17 @@ public function prepForElementModel(array &$fields, BaseElementModel $element)
$status = Import_ElementModel::HandleStatus;
if (isset($fields[$status])) {
$element->$status = $fields[$status];
if ($element->$status == UserStatus::Pending) {
$element->pending = true;
}
unset($fields[$status]);
}

// Set locale
$locale = Import_ElementModel::HandleLocale;
if (isset($fields[$locale])) {
$element->$locale = $fields[$locale];
unset($fields[$locale]);
// Set preferred locale
$preflocale = Import_ElementModel::HandlePrefLocale;
if (isset($fields[$preflocale])) {
$element->$preflocale = $fields[$preflocale];
unset($fields[$preflocale]);
}

// Set password
Expand All @@ -189,15 +198,8 @@ public function prepForElementModel(array &$fields, BaseElementModel $element)
*/
public function save(BaseElementModel &$element, $settings)
{
// Save element
if ($settings->validate) {
$result = craft()->users->saveUser($element);
} else {
$result = craft()->elements->saveElement($element, false);
}

// Save usergroup
if ($result) {
// Save user
if (craft()->users->saveUser($element)) {

// Assign to groups
craft()->userGroups->assignUserToGroups($element->id, $settings['elementvars']['groups']);
Expand Down
3 changes: 1 addition & 2 deletions tasks/ImportTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ protected function defineSettings()
'type' => AttributeType::String,
'elementvars' => array(AttributeType::Mixed, 'default' => array()),
'behavior' => array(AttributeType::Name, 'default' => ImportModel::BehaviorAppend),
'validate' => array(AttributeType::Bool, 'default' => true),
'email' => array(AttributeType::Bool, 'default' => false),
'email' => AttributeType::Email,
'backup' => array(AttributeType::Bool, 'default' => false),
'history' => AttributeType::Number,
);
Expand Down
20 changes: 0 additions & 20 deletions templates/index.twig
Original file line number Diff line number Diff line change
Expand Up @@ -101,26 +101,6 @@
</div>
</td>
</tr>
<tr class="importValidate">
<td>
<div class="field">
<div class="heading">
<label>{{ "Validate content"|t }}</label>
<div class="instructions">
<p>{{ "Enable field validation when importing."|t }}</p>
</div>
</div>
</div>
</td>
<td>
<div class="field">
<div class="input">
<input type="hidden" name="import[validate]" value="0">
<input type="checkbox" name="import[validate]" value="1" id="validate" checked />
</div>
</div>
</td>
</tr>
<tr class="importEmail">
<td>
<div class="field">
Expand Down
19 changes: 15 additions & 4 deletions templates/types/category/_map.twig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% set fieldLayout = craft.fields.getLayoutByType(import.type) %}
{% set categoryGroup = craft.categoryGroups.getGroupById(import.elementvars.group) %}

<p>{{ 'Choose the destination fields for your imported data. "Title" is always required.'|t }}</p>
{% if import.behavior != 'append' %}
Expand Down Expand Up @@ -32,15 +32,26 @@
<div class="select mapper">
<select name="fields[{{ column }}]" class="importFields">
<option value="dont">{{ "Don't import"|t }}</option>
<option value="id"{% if column|lower == 'id' %} selected{% endif %}>{{ "ID"|t }}</option>
<option value="title"{% if column|lower == 'title' or column|lower == 'name' %} selected{% endif %}>{{ "Title"|t }} *</option>
<option value="slug"{% if column|lower == 'slug' %} selected{% endif %}>{{ "Slug"|t }}</option>
<option value="parentId"{% if column|lower == 'parent' %} selected{% endif %}>{{ "Parent Entry"|t }}</option>
<option value="ancestors"{% if column|lower == 'ancestors' %} selected{% endif %}>{{ "Ancestors"|t }}</option>
<option value="enabled"{% if column|lower == 'enabled' %} selected{% endif %}>{{ "Enabled"|t }}</option>
{% for field in fieldLayout.getFields() %}
<option value="locale"{% if column|lower == 'locale' %} selected{% endif %}>{{ "Locale"|t }}</option>
{% for tab in craft.fields.getLayoutById(categoryGroup.fieldLayoutId).getTabs() %}
<optgroup label="{{ tab.name }}">
{% for field in tab.getFields() %}
{% set f = field.getField() %}
<option value="{{ f.handle }}"{% if column|lower == f.name|lower or column|lower == f.handle|lower %} selected{% endif %}>{{ f.name }}{% if f.required %} *{% endif %}</option>
{% set customOption = craft.import.customOption(f.type) %}
{% if customOption %}
{% include customOption ignore missing %}
{% else %}
<option value="{{ f.handle }}"{% if column|lower == f.name|lower or column|lower == f.handle|lower %} selected{% endif %}>{{ f.name }}{% if f.required %} *{% endif %}</option>
{% endif %}
{% endfor %}
</optgroup>
{% endfor %}
</select>
</div>
</div>
Expand All @@ -53,7 +64,7 @@
instructions: "Criterium for finding existing data."|t,
name: "unique[" ~ column ~ "]",
class: "unique",
checked: loop.first
checked: loop.first or column|lower == 'locale'
}) }}
</td>
{% endif %}
Expand Down
4 changes: 3 additions & 1 deletion templates/types/entry/_map.twig
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<option value="dont">{{ "Don't import"|t }}</option>
{% for entrytype in entrytypes %}
{% if loop.first %}
<option value="id"{% if column|lower == 'id' %} selected{% endif %}>{{ "ID"|t }}</option>
<option value="title"{% if column|lower == 'title' or column|lower == 'name' or column|lower == entrytype.titleLabel|lower %} selected{% endif %}>{{ entrytype.titleLabel }} *</option>
<option value="slug"{% if column|lower == 'slug' %} selected{% endif %}>{{ "Slug"|t }}</option>
<option value="parentId"{% if column|lower == 'parent' %} selected{% endif %}>{{ "Parent Entry"|t }}</option>
Expand All @@ -44,6 +45,7 @@
<option value="postDate"{% if column|lower == 'postdate' or column|lower == 'date' %} selected{% endif %}>{{ "Post Date"|t }}</option>
<option value="expiryDate"{% if column|lower == 'expirydate' or column|lower == 'enddate' %} selected{% endif %}>{{ "Expiry Date"|t }}</option>
<option value="enabled"{% if column|lower == 'enabled' %} selected{% endif %}>{{ "Enabled"|t }}</option>
<option value="locale"{% if column|lower == 'locale' %} selected{% endif %}>{{ "Locale"|t }}</option>
{% endif %}
{% for tab in craft.fields.getLayoutById(entrytype.fieldLayoutId).getTabs() %}
<optgroup label="{{ tab.name }}">
Expand Down Expand Up @@ -71,7 +73,7 @@
instructions: "Criterium for finding existing data."|t,
name: "unique[" ~ column ~ "]",
class: "unique",
checked: loop.first
checked: loop.first or column|lower == 'locale'
}) }}
</td>
{% endif %}
Expand Down
Loading

0 comments on commit d5dd55f

Please sign in to comment.