Skip to content

Commit

Permalink
- initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
le0m committed May 4, 2018
0 parents commit d5c69f3
Show file tree
Hide file tree
Showing 12 changed files with 733 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# phpstorm project files
.idea

# composer vendor dir
/vendor

# composer
composer.lock
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
1.0.0, 4 May 2018
-------------------

- initial release
11 changes: 11 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Copyright 2018 Leo Mainardi

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
118 changes: 118 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
Yii2 Importer
------------

This extension helps you import data from files like CSV or JSON into your application.

Installation
------------

The preferred way to install this extension is through [composer](http://getcomposer.org/download/).

Either run

```
composer require le0m/yii2-import
```

or add

```
"le0m/yii2-import": "*"
```

to the require section of your composer.json.


Usage
-----

This extension provide support to import data from files to data structures like array or ActiveRecord.

First you must create an `Importer`, which needs a `reader` and an `importStrategy` to work, then you can import:

```php
$importer = new Importer([
// this can be an array of strings to use as column names for the imported data,
// `true` if the column names can be extracted from the file itself (the 'how' is specific to the implementation)
// or `false` to disable and not use column names (default).
'columnNames' => [...],

// see below for how to setup this
'reader' => [
'class' => '\common\components\importer\CsvReader',
],

// see below for how to setup this
'importStrategy' => [
'class' => '\common\components\importer\ARImportStrategy',
]
]);

// get the imported data
$data = $importer->import();
```

The importer will read the file using the chosen `reader` implementation, passing each element to the chosen `importStrategy` implementation. The returning value is an array of imported data.

If the `importStrategy` return `false` on a single element, the `Importer` will ignore it.

By default this extension provides two reader (CSV and JSON) and two import strategy (to array and to ActiveRecord) implementations to choose from, but you can add your own by implementing the appropriate interface.


**Import a CSV file**

The `CsvReader` accepts the following properties:

```php
'reader' => [
'class' => '\common\components\importer\CsvReader',

// limit the max length of a single line to read from file
// 0 means no limit
'lineLength' => 0,

// character used to separate values on a single line
'valueDelimiter' => ",",

// character used to enclose values
'valueEnclosure' => '"',

// character used as escape in the values
'escapeCharacter' => "\\",
]
```


**Import a JSON**

The `JsonImporter` has no particular properties:

```php
'reader' => [
'class' => '\common\components\importer\JsonReader',
]
```


**Import to ActiveRecord**

The `ARImportStrategy` accepts the following properties:

```php
'importStrategy' => [
'class' => '\common\components\importer\ARImportStrategy',

// name of the ActiveRecord class to use for the import
'className' => '...',

// if you need custom code to handle loading data read from the file to the AR
// (ex. column names from the file are different than property names from the AR
// this function will be called for each element in the original file,
// return false to not import the current element ([[Importer]] ignores false elements)
'loadProperties' => function ($model, $data) { ... },

// whether to automatically save the AR at the end of the import
// AR with validation errors are returned anyway
'saveRecord' => true,
]
```
27 changes: 27 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "le0m/yii2-import",
"description": "An extension for the Yii2 framework to import data from files",
"keywords": [
"yii2",
"import",
"csv",
"activerecord",
"json"
],
"type": "yii2-extension",
"license": "BSD-3-Clause",
"authors": [
{
"name": "Leo Mainardi",
"email": "mainardi.leo@gmail.com"
}
],
"require": {
"yiisoft/yii2": "~2.0.0"
},
"autoload": {
"psr-4": {
"le0m\\import\\": "src/"
}
}
}
105 changes: 105 additions & 0 deletions src/ARImportStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php

namespace le0m\import;

use yii\base\Object;
use yii\base\InvalidConfigException;


class ARImportStrategy extends Object implements ImportStrategyInterface
{
/**
* @var string ActiveRecord class to use for the import
*/
public $className;

/**
* @var bool Whether to save the record after import and
* calling {@link $afterImport} or not
*/
public $saveRecord = true;

/**
* @var \Closure|null Optional function to handle loading
* property values in the AR model.
*
* This is useful if the column names differ from the AR
* property names.
* The signature of the function must match this:
*
* ```php
* function ($model, $data) {}
* ```
*
* where "$model" is the new AR instance and "$data" is
* the imported values.
*/
public $loadProperties;


/**
* @var array Optional column names
*/
private $_columnNames = null;


/**
* {@inheritdoc}
*
* @throws \yii\base\InvalidConfigException
*/
public function __construct(array $config = [])
{
if (!isset($config['className'])) {
throw new InvalidConfigException("ActiveRecord class name not set");
}

parent::__construct($config);
}

/**
* {@inheritdoc}
*/
public function setColumnNames($columns)
{
$this->_columnNames = $columns;
}

/**
* {@inheritdoc}
*/
public function getColumnNames()
{
return $this->_columnNames;
}

/**
* {@inheritdoc}
*
* @throws \yii\base\InvalidConfigException
*/
public function import($data)
{
if ($this->_columnNames === null) {
throw new InvalidConfigException("Can't import, column names not set.");
}

$data = array_combine($this->_columnNames, $data);
$class = $this->className;
/** @var \yii\db\ActiveRecord $record */
$record = new $class();

if ($this->loadProperties instanceof \Closure) {
$record = call_user_func_array($this->loadProperties, [$record, $data]);
} else {
$record->load($data, '');
}

if ($this->saveRecord) {
// if validation fails, return the model anyway
$record->save();
}

return $record;
}
}
41 changes: 41 additions & 0 deletions src/ArrayImportStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace le0m\import;

use yii\base\Object;


class ArrayImportStrategy extends Object implements ImportStrategyInterface
{
/** @var array Optional column names */
private $_columnNames = null;


/**
* {@inheritdoc}
*/
public function setColumnNames($columns)
{
$this->_columnNames = $columns;
}

/**
* {@inheritdoc}
*/
public function getColumnNames()
{
return $this->_columnNames;
}

/**
* {@inheritdoc}
*/
public function import($data)
{
if ($this->_columnNames !== null) {
$data = array_combine($this->_columnNames, $data);
}

return $data;
}
}
Loading

0 comments on commit d5c69f3

Please sign in to comment.