├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── examples ├── import_step1.jpg └── import_step2.jpg ├── phpunit.xml ├── public ├── css │ ├── bootstrap-theme.css │ ├── bootstrap-theme.min.css │ ├── bootstrap.css │ ├── bootstrap.min.css │ └── default.css ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff └── js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── jquery-1.10.2.min.js │ └── jquery-1.10.2.min.map ├── src ├── Jacopo │ └── LaravelImportExport │ │ ├── LaravelImportExportServiceProvider.php │ │ ├── Models │ │ ├── DatabaseSchemaManager.php │ │ ├── Exceptions │ │ │ ├── ClassNotFoundException.php │ │ │ ├── FileNotFoundException.php │ │ │ ├── HeadersNotSetException.php │ │ │ ├── NoDataException.php │ │ │ └── UnalignedArrayException.php │ │ ├── InputWrapper.php │ │ ├── ParseCsv │ │ │ ├── CsvFile.php │ │ │ ├── CsvFileBuilder.php │ │ │ ├── CsvFileHandler.php │ │ │ ├── CsvLine.php │ │ │ ├── DbFileBuilder.php │ │ │ ├── File.php │ │ │ └── ParseCsv.php │ │ ├── RuntimeModel.php │ │ ├── StateHandling │ │ │ ├── Export │ │ │ │ ├── ExportCompleteState.php │ │ │ │ ├── GeneralState.php │ │ │ │ ├── GetTableConfig.php │ │ │ │ ├── GetTableName.php │ │ │ │ └── StateHandler.php │ │ │ ├── GeneralState.php │ │ │ ├── Import │ │ │ │ ├── GeneralState.php │ │ │ │ ├── GetCsvState.php │ │ │ │ ├── GetTableState.php │ │ │ │ ├── ImportCompleteState.php │ │ │ │ └── StateHandler.php │ │ │ ├── StateArray.php │ │ │ ├── StateHandler.php │ │ │ └── StateInterface.php │ │ ├── TemporaryModel.php │ │ └── ValidatorFormInputModel.php │ │ ├── routes.php │ │ └── start.php ├── config │ ├── baseconf.php │ └── database.php ├── controllers │ ├── BaseController.php │ ├── ExportController.php │ ├── HomeController.php │ └── ImportController.php ├── migrations │ └── 2013_09_25_222039__laravel_import_export_temporary_table.php └── views │ ├── home │ └── index.blade.php │ └── layouts │ └── default.blade.php └── tests ├── .gitkeep └── unit ├── TestCsvFile.php ├── TestCsvFileBuilder.php ├── TestCsvFileHandler.php ├── TestCsvLine.php ├── TestDbFileBuilder.php ├── TestFile.php ├── TestGeneralState.php ├── TestGetCsvState.php ├── TestGetTableConfig.php ├── TestGetTableName.php ├── TestGetTableState.php ├── TestParseCsv.php ├── TestRuntimeModel.php ├── TestStateHandler.php ├── TestTemporaryModel.php └── TestValidatorFormInputModel.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | composer.phar 3 | composer.lock 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | - 5.5 7 | 8 | before_script: 9 | - curl -s http://getcomposer.org/installer | php 10 | - php composer.phar install --dev 11 | 12 | script: phpunit -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, jacopo 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Laravel-Import-Export 2 | 3 | Import-Export is a package to import and export data from various format into a database. 4 | 5 | - **Author**: Jacopo Beschi 6 | - **Version**: 0.1.0 7 | 8 | [![Build Status](https://travis-ci.org/intrip/laravel-import-export.png)](https://travis-ci.org/intrip/laravel-import-export) 9 | 10 | 11 | 12 | ## This package is no longer supported: either any bugfix or any new feature will be added. Install at your own risk! 13 | 14 | ##Features 15 | 16 | - Import and export data from Csv file into database 17 | - Multi DBMS: works with all DBMS supported by Laravel ORM 18 | - Create database schema: allow you to create database schema when importing data 19 | 20 | ##Under the box: features incoming in 0.2.0 21 | 22 | - Import and export an arbitrary number of lines 23 | - Import and export JSON and XML 24 | - Database access configurabile with a GUI 25 | 26 | ## Requirements 27 | 28 | - PHP >= 5.3.7 29 | - Composer 30 | - Laravel framework 4+ 31 | - DBMS that support transactions and supported by Laravel ORM 32 | 33 | ##Installation with Composer 34 | 35 | To install Import-Export with Composer, add this line to your composer.json file in the `require field: 36 | 37 | ```json 38 | "jacopo/laravel-import-export": "dev-master" 39 | ``` 40 | Also remember to set the minimum-stability to "dev" in your composer.json file 41 | 42 | Then open `app/config/app.php` and add the following line in the `providers` array: 43 | 44 | ```php 45 | 'providers' => array( 46 | 'Jacopo\LaravelImportExport\LaravelImportExportServiceProvider', 47 | ) 48 | ``` 49 | 50 | After you need to execute the following commands: 51 | 52 | ```php 53 | php artisan config:publish jacopo/laravel-import-export 54 | php artisan asset:publish jacopo/laravel-import-export 55 | ``` 56 | Now you have under `app/config/packages/jacopo/laravel-import-export` the package configuration files. At this point you need to configure the database access. Open the file `app/config/packages/jacopo/laravel-import-export/database.php` and update it with the database access information. When done run the following command to initialize ImportExport database. 57 | 58 | ```php 59 | php artisan migrate --package="jacopo/laravel-import-export" --database="import" 60 | ``` 61 | This command will create a `_import_export_temporary_table` in the db, you can change the name of the table editing the the key: `table_prefix` under the file `app/config/packages/jacopo/laravel-import-export/baseconf.php`. 62 | 63 | Congratulations! Now you can view the application at the url: `http://url-of-your-baseapp/importer`. If needed you can change the base route editing the the key: `base_application_route` under the file `app/config/packages/jacopo/laravel-import-export/baseconf.php`. 64 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jacopo/laravel-import-export", 3 | "description": "A package to import and export data in csv for Laravel", 4 | "version" : "0.1.0", 5 | "keywords": ["import","export","csv","database","laravel"], 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Jacopo Beschi", 10 | "email": "beschi.jacopo@gmail.com" 11 | } 12 | ], 13 | "require": { 14 | "php": ">=5.3.0", 15 | "illuminate/support": "~4", 16 | "jacopo/bootstrap-3-table-generator": "dev-master" 17 | }, 18 | "require-dev": { 19 | "laravel/framework": "~4", 20 | "mockery/mockery": "dev-master" 21 | }, 22 | "autoload": { 23 | "classmap": [ 24 | "src/controllers" 25 | ], 26 | "psr-0": { 27 | "Jacopo\\LaravelImportExport": "src/" 28 | } 29 | }, 30 | "minimum-stability": "stable" 31 | } 32 | -------------------------------------------------------------------------------- /examples/import_step1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intrip/laravel-import-export/2e6963778a0214c9123d0c51a0d01d8127e1e935/examples/import_step1.jpg -------------------------------------------------------------------------------- /examples/import_step2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intrip/laravel-import-export/2e6963778a0214c9123d0c51a0d01d8127e1e935/examples/import_step2.jpg -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests/unit 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /public/css/bootstrap-theme.css: -------------------------------------------------------------------------------- 1 | .btn-default, 2 | .btn-primary, 3 | .btn-success, 4 | .btn-info, 5 | .btn-warning, 6 | .btn-danger { 7 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); 8 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); 9 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); 10 | } 11 | 12 | .btn-default:active, 13 | .btn-primary:active, 14 | .btn-success:active, 15 | .btn-info:active, 16 | .btn-warning:active, 17 | .btn-danger:active, 18 | .btn-default.active, 19 | .btn-primary.active, 20 | .btn-success.active, 21 | .btn-info.active, 22 | .btn-warning.active, 23 | .btn-danger.active { 24 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 25 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 26 | } 27 | 28 | .btn:active, 29 | .btn.active { 30 | background-image: none; 31 | } 32 | 33 | .btn-default { 34 | text-shadow: 0 1px 0 #fff; 35 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#e6e6e6)); 36 | background-image: -webkit-linear-gradient(top, #ffffff, 0%, #e6e6e6, 100%); 37 | background-image: -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%); 38 | background-image: linear-gradient(to bottom, #ffffff 0%, #e6e6e6 100%); 39 | background-repeat: repeat-x; 40 | border-color: #e0e0e0; 41 | border-color: #ccc; 42 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); 43 | } 44 | 45 | .btn-default:active, 46 | .btn-default.active { 47 | background-color: #e6e6e6; 48 | border-color: #e0e0e0; 49 | } 50 | 51 | .btn-primary { 52 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); 53 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); 54 | background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); 55 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); 56 | background-repeat: repeat-x; 57 | border-color: #2d6ca2; 58 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); 59 | } 60 | 61 | .btn-primary:active, 62 | .btn-primary.active { 63 | background-color: #3071a9; 64 | border-color: #2d6ca2; 65 | } 66 | 67 | .btn-success { 68 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); 69 | background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); 70 | background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); 71 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 72 | background-repeat: repeat-x; 73 | border-color: #419641; 74 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 75 | } 76 | 77 | .btn-success:active, 78 | .btn-success.active { 79 | background-color: #449d44; 80 | border-color: #419641; 81 | } 82 | 83 | .btn-warning { 84 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); 85 | background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); 86 | background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 87 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 88 | background-repeat: repeat-x; 89 | border-color: #eb9316; 90 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 91 | } 92 | 93 | .btn-warning:active, 94 | .btn-warning.active { 95 | background-color: #ec971f; 96 | border-color: #eb9316; 97 | } 98 | 99 | .btn-danger { 100 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); 101 | background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); 102 | background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); 103 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 104 | background-repeat: repeat-x; 105 | border-color: #c12e2a; 106 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 107 | } 108 | 109 | .btn-danger:active, 110 | .btn-danger.active { 111 | background-color: #c9302c; 112 | border-color: #c12e2a; 113 | } 114 | 115 | .btn-info { 116 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); 117 | background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); 118 | background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 119 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 120 | background-repeat: repeat-x; 121 | border-color: #2aabd2; 122 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 123 | } 124 | 125 | .btn-info:active, 126 | .btn-info.active { 127 | background-color: #31b0d5; 128 | border-color: #2aabd2; 129 | } 130 | 131 | .thumbnail, 132 | .img-thumbnail { 133 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 134 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 135 | } 136 | 137 | .dropdown-menu > li > a:hover, 138 | .dropdown-menu > li > a:focus, 139 | .dropdown-menu > .active > a, 140 | .dropdown-menu > .active > a:hover, 141 | .dropdown-menu > .active > a:focus { 142 | background-color: #357ebd; 143 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); 144 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); 145 | background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); 146 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 147 | background-repeat: repeat-x; 148 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 149 | } 150 | 151 | .navbar { 152 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#f8f8f8)); 153 | background-image: -webkit-linear-gradient(top, #ffffff, 0%, #f8f8f8, 100%); 154 | background-image: -moz-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); 155 | background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%); 156 | background-repeat: repeat-x; 157 | border-radius: 4px; 158 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); 159 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); 160 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); 161 | } 162 | 163 | .navbar .navbar-nav > .active > a { 164 | background-color: #f8f8f8; 165 | } 166 | 167 | .navbar-brand, 168 | .navbar-nav > li > a { 169 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); 170 | } 171 | 172 | .navbar-inverse { 173 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222)); 174 | background-image: -webkit-linear-gradient(top, #3c3c3c, 0%, #222222, 100%); 175 | background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%); 176 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%); 177 | background-repeat: repeat-x; 178 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); 179 | } 180 | 181 | .navbar-inverse .navbar-nav > .active > a { 182 | background-color: #222222; 183 | } 184 | 185 | .navbar-inverse .navbar-brand, 186 | .navbar-inverse .navbar-nav > li > a { 187 | text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 188 | } 189 | 190 | .navbar-static-top, 191 | .navbar-fixed-top, 192 | .navbar-fixed-bottom { 193 | border-radius: 0; 194 | } 195 | 196 | .alert { 197 | text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2); 198 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); 199 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); 200 | } 201 | 202 | .alert-success { 203 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc)); 204 | background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #c8e5bc, 100%); 205 | background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); 206 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); 207 | background-repeat: repeat-x; 208 | border-color: #b2dba1; 209 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); 210 | } 211 | 212 | .alert-info { 213 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0)); 214 | background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #b9def0, 100%); 215 | background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%); 216 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); 217 | background-repeat: repeat-x; 218 | border-color: #9acfea; 219 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); 220 | } 221 | 222 | .alert-warning { 223 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0)); 224 | background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #f8efc0, 100%); 225 | background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); 226 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); 227 | background-repeat: repeat-x; 228 | border-color: #f5e79e; 229 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); 230 | } 231 | 232 | .alert-danger { 233 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3)); 234 | background-image: -webkit-linear-gradient(top, #f2dede, 0%, #e7c3c3, 100%); 235 | background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); 236 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); 237 | background-repeat: repeat-x; 238 | border-color: #dca7a7; 239 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); 240 | } 241 | 242 | .progress { 243 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f5f5f5)); 244 | background-image: -webkit-linear-gradient(top, #ebebeb, 0%, #f5f5f5, 100%); 245 | background-image: -moz-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); 246 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); 247 | background-repeat: repeat-x; 248 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); 249 | } 250 | 251 | .progress-bar { 252 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); 253 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); 254 | background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); 255 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); 256 | background-repeat: repeat-x; 257 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); 258 | } 259 | 260 | .progress-bar-success { 261 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); 262 | background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); 263 | background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); 264 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); 265 | background-repeat: repeat-x; 266 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); 267 | } 268 | 269 | .progress-bar-info { 270 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); 271 | background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); 272 | background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); 273 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); 274 | background-repeat: repeat-x; 275 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); 276 | } 277 | 278 | .progress-bar-warning { 279 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); 280 | background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); 281 | background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); 282 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); 283 | background-repeat: repeat-x; 284 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); 285 | } 286 | 287 | .progress-bar-danger { 288 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); 289 | background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); 290 | background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); 291 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); 292 | background-repeat: repeat-x; 293 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); 294 | } 295 | 296 | .list-group { 297 | border-radius: 4px; 298 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 299 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); 300 | } 301 | 302 | .list-group-item.active, 303 | .list-group-item.active:hover, 304 | .list-group-item.active:focus { 305 | text-shadow: 0 -1px 0 #3071a9; 306 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3)); 307 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #3278b3, 100%); 308 | background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%); 309 | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); 310 | background-repeat: repeat-x; 311 | border-color: #3278b3; 312 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); 313 | } 314 | 315 | .panel { 316 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 317 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); 318 | } 319 | 320 | .panel-default > .panel-heading { 321 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8)); 322 | background-image: -webkit-linear-gradient(top, #f5f5f5, 0%, #e8e8e8, 100%); 323 | background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); 324 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); 325 | background-repeat: repeat-x; 326 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); 327 | } 328 | 329 | .panel-primary > .panel-heading { 330 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); 331 | background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); 332 | background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); 333 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); 334 | background-repeat: repeat-x; 335 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); 336 | } 337 | 338 | .panel-success > .panel-heading { 339 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6)); 340 | background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #d0e9c6, 100%); 341 | background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); 342 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); 343 | background-repeat: repeat-x; 344 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); 345 | } 346 | 347 | .panel-info > .panel-heading { 348 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3)); 349 | background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #c4e3f3, 100%); 350 | background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); 351 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); 352 | background-repeat: repeat-x; 353 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); 354 | } 355 | 356 | .panel-warning > .panel-heading { 357 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc)); 358 | background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #faf2cc, 100%); 359 | background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); 360 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); 361 | background-repeat: repeat-x; 362 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); 363 | } 364 | 365 | .panel-danger > .panel-heading { 366 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc)); 367 | background-image: -webkit-linear-gradient(top, #f2dede, 0%, #ebcccc, 100%); 368 | background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%); 369 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); 370 | background-repeat: repeat-x; 371 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); 372 | } 373 | 374 | .well { 375 | background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(#f5f5f5)); 376 | background-image: -webkit-linear-gradient(top, #e8e8e8, 0%, #f5f5f5, 100%); 377 | background-image: -moz-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); 378 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); 379 | background-repeat: repeat-x; 380 | border-color: #dcdcdc; 381 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); 382 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); 383 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); 384 | } -------------------------------------------------------------------------------- /public/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | .btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,0%,#e6e6e6,100%);background-image:-moz-linear-gradient(top,#fff 0,#e6e6e6 100%);background-image:linear-gradient(to bottom,#fff 0,#e6e6e6 100%);background-repeat:repeat-x;border-color:#e0e0e0;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0)}.btn-default:active,.btn-default.active{background-color:#e6e6e6;border-color:#e0e0e0}.btn-primary{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;border-color:#2d6ca2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.btn-primary:active,.btn-primary.active{background-color:#3071a9;border-color:#2d6ca2}.btn-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;border-color:#419641;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.btn-success:active,.btn-success.active{background-color:#449d44;border-color:#419641}.btn-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;border-color:#eb9316;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.btn-warning:active,.btn-warning.active{background-color:#ec971f;border-color:#eb9316}.btn-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;border-color:#c12e2a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.btn-danger:active,.btn-danger.active{background-color:#c9302c;border-color:#c12e2a}.btn-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;border-color:#2aabd2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.btn-info:active,.btn-info.active{background-color:#31b0d5;border-color:#2aabd2}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.navbar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#f8f8f8));background-image:-webkit-linear-gradient(top,#fff,0%,#f8f8f8,100%);background-image:-moz-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff8f8f8',GradientType=0);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar .navbar-nav>.active>a{background-color:#f8f8f8}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-gradient(linear,left 0,left 100%,from(#3c3c3c),to(#222));background-image:-webkit-linear-gradient(top,#3c3c3c,0%,#222,100%);background-image:-moz-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c',endColorstr='#ff222222',GradientType=0)}.navbar-inverse .navbar-nav>.active>a{background-color:#222}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#c8e5bc));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#c8e5bc,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffc8e5bc',GradientType=0)}.alert-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#b9def0));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#b9def0,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffb9def0',GradientType=0)}.alert-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#f8efc0));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#f8efc0,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fff8efc0',GradientType=0)}.alert-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#e7c3c3));background-image:-webkit-linear-gradient(top,#f2dede,0%,#e7c3c3,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffe7c3c3',GradientType=0)}.progress{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#ebebeb,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff5f5f5',GradientType=0)}.progress-bar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.progress-bar-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.progress-bar-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.progress-bar-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.progress-bar-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3278b3));background-image:-webkit-linear-gradient(top,#428bca,0%,#3278b3,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3278b3',GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5,0%,#e8e8e8,100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#d0e9c6));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#d0e9c6,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffd0e9c6',GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#c4e3f3));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#c4e3f3,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffc4e3f3',GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#faf2cc));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#faf2cc,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fffaf2cc',GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#ebcccc));background-image:-webkit-linear-gradient(top,#f2dede,0%,#ebcccc,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffebcccc',GradientType=0)}.well{background-image:-webkit-gradient(linear,left 0,left 100%,from(#e8e8e8),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#e8e8e8,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} -------------------------------------------------------------------------------- /public/css/default.css: -------------------------------------------------------------------------------- 1 | body 2 | { 3 | padding-top: 70px; 4 | } 5 | 6 | .fill-screen 7 | { 8 | max-width: 100%; 9 | } 10 | 11 | /******* Bootstrap Icons **********/ 12 | .icon-large{font-size:60px} 13 | .icon-medium{font-size:30px} 14 | .icon-small{font-size:20px} 15 | 16 | /********** Layouts ***********/ 17 | .bottom-10{margin-bottom:10px} 18 | .top-10{margin-top:10px} 19 | 20 | /*********** Custom Bootstrap colors ***********/ 21 | .jumbotron 22 | { 23 | /*background-color: #5a5a5a;*/ 24 | } 25 | 26 | /*********** Table ***********/ 27 | table 28 | { 29 | table-layout: fixed; 30 | word-wrap: break-word; 31 | font-size: 0.9em; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intrip/laravel-import-export/2e6963778a0214c9123d0c51a0d01d8127e1e935/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intrip/laravel-import-export/2e6963778a0214c9123d0c51a0d01d8127e1e935/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intrip/laravel-import-export/2e6963778a0214c9123d0c51a0d01d8127e1e935/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /public/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * bootstrap.js v3.0.0 by @fat and @mdo 3 | * Copyright 2013 Twitter Inc. 4 | * http://www.apache.org/licenses/LICENSE-2.0 5 | */ 6 | if(!jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(window.jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(window.jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(window.jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(window.jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(window.jQuery); -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/LaravelImportExportServiceProvider.php: -------------------------------------------------------------------------------- 1 | package('jacopo/laravel-import-export'); 27 | 28 | $this->registerImportState(); 29 | $this->registerExportState(); 30 | } 31 | 32 | /** 33 | * Get the services provided by the provider. 34 | * 35 | * @return array 36 | */ 37 | public function provides() 38 | { 39 | return array(); 40 | } 41 | 42 | public function boot() 43 | { 44 | // include start.php 45 | include_once __DIR__ . '/start.php'; 46 | 47 | // Use custom package database configuration 48 | $this->app['config']['database.connections'] = array_merge( 49 | $this->app['config']['database.connections'], 50 | \Config::get('laravel-import-export::database.connections') 51 | ); 52 | } 53 | 54 | protected function registerImportState(ImportHandler $handler = null) 55 | { 56 | $this->app['import_csv_handler'] = $this->app->share(function($app) 57 | { 58 | $handler = new ImportHandler(); 59 | $handler->initializeState(); 60 | 61 | return $handler; 62 | }); 63 | } 64 | 65 | protected function registerExportState(ExportHandler $handler = null) 66 | { 67 | $this->app['export_csv_handler'] = $this->app->share(function($app) 68 | { 69 | $handler = new ExportHandler(); 70 | $handler->initializeState(); 71 | 72 | return $handler; 73 | }); 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/DatabaseSchemaManager.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Illuminate\Support\Facades\DB; 9 | use Illuminate\Support\Facades\Config; 10 | use Illuminate\Support\Facades\Schema; 11 | 12 | class DatabaseSchemaManager 13 | { 14 | protected $manager; 15 | /** 16 | * Name of the connection to use 17 | * @var String 18 | */ 19 | protected $connection; 20 | 21 | public function __construct() 22 | { 23 | $this->connection = Config::get('laravel-import-export::baseconf.connection_name'); 24 | $this->manager = DB::connection($this->connection)->getDoctrineSchemaManager(); 25 | } 26 | 27 | public function getTableList() 28 | { 29 | $tables = $this->manager->listTableNames(); 30 | 31 | return $tables; 32 | } 33 | 34 | public function getTableColumns($table_name) 35 | { 36 | $columns = $this->manager->listTableColumns($table_name); 37 | 38 | return $columns; 39 | } 40 | 41 | /** 42 | * Create a table schme with the given columns 43 | * 44 | * @param $name table name 45 | * @param Array $columns "type" => "name" 46 | * @param $safe_create if is enabled doesnt create a table if already exists 47 | * 48 | */ 49 | public function createTable($name, Array $columns, $safe_create = false) 50 | { 51 | if( (! $safe_create) || ($safe_create && ! Schema::connection($this->connection)->hasTable('users')) ) 52 | { 53 | // dtop table if exists 54 | if (Schema::connection($this->connection)->hasTable($name)) 55 | { 56 | Schema::connection($this->connection)->drop($name); 57 | } 58 | 59 | Schema::connection($this->connection)->create($name, function($table) use ($columns) 60 | { 61 | foreach($columns as $name => $type) 62 | { 63 | $table->$type($name); 64 | } 65 | }); 66 | } 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/Exceptions/ClassNotFoundException.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Illuminate\Support\Facades\Input; 9 | 10 | class InputWrapper 11 | { 12 | 13 | public function get($params, $default_value = null) 14 | { 15 | return Input::get($params,$default_value); 16 | } 17 | 18 | public function post($params, $default_value = null) 19 | { 20 | return Input::post($params,$default_value); 21 | } 22 | 23 | public function all() 24 | { 25 | return Input::all(); 26 | } 27 | } -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/ParseCsv/CsvFile.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | class CsvFile extends \ArrayIterator 10 | { 11 | protected $csv_headers = array(); 12 | 13 | public function getCsvHeader() 14 | { 15 | return $this->csv_headers; 16 | } 17 | 18 | public function setCsvHeader($value) 19 | { 20 | $this->csv_headers = $value; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/ParseCsv/CsvFileBuilder.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | class CsvFileBuilder 8 | { 9 | 10 | protected $config_file_parse; 11 | protected $config_model; 12 | protected $csv_file; 13 | protected $csv_parser; 14 | /** 15 | * 'first_line_headers' if first line of the file contains data headers 16 | * @var Array 17 | */ 18 | protected $config; 19 | 20 | /** 21 | * 22 | * @param $config_model configuration for the RuntimeModel 23 | * @param $config_file_parse configuration for the csv file parser 24 | * @param $config configuration for the builder 25 | * @param $csv_file instance of CsvFile 26 | * @param $csv_parser istance of ParseCsv 27 | */ 28 | public function __construct(array $config_model = array(), array $config_file_parse = array(), $config = array(), CsvFile $csv_file = null, ParseCsv $csv_parser = null) 29 | { 30 | $this->config_model = $config_model; 31 | $this->config_file_parse = $config_file_parse; 32 | $this->config = $config; 33 | $this->csv_file = $csv_file ? $csv_file : new CsvFile; 34 | $this->csv_parser = $csv_parser ? $csv_parser : new ParseCsv; 35 | } 36 | 37 | public function setConfigModel($config) 38 | { 39 | $this->config_model = $config; 40 | } 41 | public function setConfigFileParse($config) 42 | { 43 | $this->config_file_parse = $config; 44 | } 45 | public function setConfig($config) 46 | { 47 | $this->config = $config; 48 | } 49 | /** 50 | * This method build the CsvFile from a csv file 51 | * 52 | * @throws FileNotFoundException 53 | * @throws InvalidArgumentException 54 | * @throws UnalignedArrayException 55 | * @throws DomainException 56 | */ 57 | public function buildFromCsv(CsvLine $csv_line_base = null) 58 | { 59 | $this->csv_line_base = $csv_line_base ? $csv_line_base : new CsvLine; 60 | $this->csv_parser->setConfig($this->config_file_parse); 61 | $this->csv_line_base->setConfig($this->config_model); 62 | 63 | $this->updateCsvHeader(); 64 | 65 | // Csv loop 66 | while ( ($csv_line_array = $this->csv_parser->parseCsvFile()) != false ) 67 | { 68 | if( count($csv_line_array) && (! ( (count($csv_line_array) == 1) && is_null($csv_line_array[0]) ) ) ) 69 | { 70 | // create csv_line 71 | $csv_line = clone $this->csv_line_base; 72 | $csv_line->forceSetAttributes($csv_line_array); 73 | $this->appendLine($csv_line); 74 | } 75 | } 76 | } 77 | 78 | public function getCsvFile() 79 | { 80 | return $this->csv_file; 81 | } 82 | 83 | protected function appendLine(CsvLine $line) 84 | { 85 | $this->csv_file->append($line); 86 | } 87 | 88 | /** 89 | * Update the csv header with first row of the file 90 | * if "first_line_headers" is enabled 91 | */ 92 | protected function updateCsvHeader() 93 | { 94 | if( $this->config['first_line_headers'] ) 95 | { 96 | $csv_line_array = $this->csv_parser->parseCsvFile(); 97 | $this->csv_file->setCsvHeader($csv_line_array); 98 | } 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/ParseCsv/CsvFileHandler.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Jacopo\LaravelImportExport\Models\ParseCsv\CsvFileBuilder; 9 | use Jacopo\LaravelImportExport\Models\ParseCsv\CsvFile; 10 | use Jacopo\LaravelImportExport\Models\ParseCsv\DbFileBuilder; 11 | use Jacopo\LaravelImportExport\Models\FileHandlerInterface; 12 | use Jacopo\LaravelImportExport\Models\Exceptions\HeadersNotSetException; 13 | use Jacopo\LaravelImportExport\Models\Exceptions\UnalignedArrayException; 14 | use Jacopo\LaravelImportExport\Models\TemporaryModel; 15 | use Jacopo\LaravelImportExport\Models\Exceptions\NoDataException; 16 | use Illuminate\Support\Facades\DB; 17 | use Illuminate\Support\Facades\Config; 18 | use Illuminate\Filesystem\FileSystem; 19 | use Jacopo\LaravelImportExport\Models\DatabaseSchemaManager as DBM; 20 | 21 | class CsvFileHandler 22 | { 23 | protected $csv_file; 24 | 25 | /** 26 | * Get data from the temporary table 27 | * 28 | * @return Mixed $data 29 | * @throws Exception 30 | */ 31 | public function getTemporary() 32 | { 33 | // disable query logging 34 | $connection_name = Config::get('laravel-import-export::baseconf.connection_name'); 35 | DB::connection($connection_name)->disableQueryLog(); 36 | $temporary = TemporaryModel::whereRaw("1")->orderBy("id","DESC")->first(); 37 | if($temporary) 38 | { 39 | $this->csv_file = $temporary->file_object; 40 | return $this->csv_file; 41 | } 42 | return false; 43 | } 44 | 45 | /** 46 | * Put data in the temporary table 47 | * 48 | * @return Boolean $success 49 | * @throws Exception 50 | */ 51 | public function saveTemporary($csv_file = null, $temporary_model = null) 52 | { 53 | $csv_file = $csv_file ? $csv_file : $this->csv_file; 54 | if( $csv_file ) 55 | { 56 | $temporary_model = ($temporary_model) ? $temporary_model : new TemporaryModel(); 57 | $temporary_model->fill(array("file_object"=>$csv_file)); 58 | // disable query logging 59 | $connection_name = Config::get('laravel-import-export::baseconf.connection_name'); 60 | DB::connection($connection_name)->disableQueryLog(); 61 | return $temporary_model->save(); 62 | } 63 | else 64 | { 65 | return false; 66 | } 67 | } 68 | 69 | /** 70 | * Update headers of the csv_file 71 | * 72 | * @param CsvFile $csv_line 73 | * @param Array $columns $key=column name, $value=column index 74 | * @param Sring $table_name name of the table 75 | * @throws UnalignedArrayException 76 | */ 77 | public function updateHeaders(CsvFile $csv_file, array $columns, $table_name) 78 | { 79 | $this->csv_file = $csv_file ? $csv_file : $this->csv_file; 80 | 81 | foreach($this->csv_file as $csv_line) 82 | { 83 | $this->updateHeader($csv_line, $columns, $table_name); 84 | } 85 | } 86 | 87 | /** 88 | * Update headers of the csv_line 89 | * 90 | * @param CsvLine $csv_line 91 | * @param Array $columns $key=column name, $value=column index 92 | * @param Sring $table_name name of the table 93 | * @return Boolean 94 | * @throws UnalignedArrayException 95 | */ 96 | protected function updateHeader(CsvLine $csv_line, array $columns, $table_name) 97 | { 98 | $model_attributes = $csv_line->getAttributes(); 99 | $new_attributes = array(); 100 | foreach($columns as $key_column => $column) 101 | { 102 | if( isset($model_attributes[$key_column]) ) 103 | { 104 | // append data to new attributes 105 | $new_attributes = array_merge($new_attributes,array($column => $model_attributes[$key_column])); 106 | unset($model_attributes[$key_column]); 107 | } 108 | else 109 | { 110 | throw new UnalignedArrayException; 111 | } 112 | } 113 | 114 | // update data 115 | $csv_line->resetAttributes(); 116 | foreach($new_attributes as $key_attribute => $attribute) 117 | { 118 | $csv_line->forceSetAttribute($key_attribute,$attribute); 119 | } 120 | 121 | $table = array("table" => $table_name); 122 | $csv_line->setConfig( $table ); 123 | 124 | return true; 125 | } 126 | 127 | /** 128 | * @throws HeadersNotSetException 129 | * @throws PDOException 130 | */ 131 | public function saveToDb(Array $columns_type) 132 | { 133 | $csv_file = $this->csv_file; 134 | 135 | // create schema if not exists 136 | if( ! empty($columns_type)) 137 | { 138 | $line = $csv_file[0]; 139 | $dbm = new DBM(); 140 | $dbm->createTable($line->getTableName(), $columns_type); 141 | } 142 | 143 | // disable query logging 144 | $connection_name = Config::get('laravel-import-export::baseconf.connection_name'); 145 | DB::connection($connection_name)->disableQueryLog(); 146 | // start transaction 147 | DB::connection($connection_name)->transaction(function() use($csv_file) 148 | { 149 | foreach($csv_file as $csv_line) 150 | { 151 | if($csv_line->canSaveToDb()) 152 | { 153 | $csv_line->save(); 154 | } 155 | else 156 | { 157 | throw new HeadersNotSetException; 158 | } 159 | } 160 | }); 161 | 162 | return true; 163 | } 164 | 165 | /** 166 | * This method build the CsvFile from a csv file 167 | * 168 | * @param $config 169 | * 'model' for RunTimeModel 170 | * 'file' for ParseCsv 171 | * 'builder' for CsvFileBuilder 172 | * 173 | * @throws FileNotFoundException 174 | * @throws InvalidArgumentException 175 | * @throws NoDataException 176 | * @throws UnalignedArrayException 177 | * @throws DomainException 178 | * @return CsvFile 179 | */ 180 | public function openFromCsv(array $config, CsvFileBuilder $builder = null) 181 | { 182 | $builder = $builder ? $builder : new CsvFileBuilder(); 183 | $builder->setConfigModel($config["model"]); 184 | $builder->setConfigFileParse($config["file_parse"]); 185 | $builder->setConfig($config["builder"]); 186 | 187 | $builder->buildFromCsv(); 188 | $this->csv_file = $builder->getCsvFile(); 189 | if( ! count($this->csv_file)) 190 | throw new NoDataException(); 191 | 192 | return $this->getCsvFile(); 193 | } 194 | 195 | /** 196 | * Build the csvFile from Db 197 | * 198 | * @throws Exception 199 | * @throws PDOException 200 | * @return CsvFile 201 | */ 202 | public function openFromDb(array $config, DbFileBuilder $builder = null) 203 | { 204 | $builder = $builder ? $builder : new DbFileBuilder(); 205 | $builder->setConfig($config); 206 | 207 | $builder->build(); 208 | $this->csv_file = $builder->getCsvFile(); 209 | 210 | return $this->getCsvFile(); 211 | } 212 | 213 | /** 214 | * Get the max lenght of a csv_line 215 | * @return Integer 216 | */ 217 | public function getMaxLength($csv_file = null) 218 | { 219 | $csv_file = $csv_file ? $csv_file : $this->csv_file; 220 | 221 | $sizes = array(0); 222 | if( ! $csv_file ) 223 | { 224 | throw new NoDataException(); 225 | } 226 | 227 | foreach($csv_file as $line) 228 | { 229 | $sizes[]=count($line->getElements() ); 230 | } 231 | 232 | return max($sizes); 233 | } 234 | 235 | /** 236 | * Create the csv string rappresenting the CsvFile 237 | * 238 | * @return String $csv 239 | * @throws NoDataException 240 | */ 241 | public function getCsvString($separator, CsvFile $csv_file = null) 242 | { 243 | $csv_file = $csv_file ? $csv_file : $this->csv_file; 244 | $csv = ''; 245 | if( ! isset($csv_file) ) 246 | { 247 | throw new NoDataException; 248 | } 249 | else 250 | { 251 | foreach($csv_file as $key => $csv_line) 252 | { 253 | if($key == 0) 254 | { 255 | $csv.=$csv_line->getCsvHeader($separator); 256 | } 257 | $csv.=$csv_line->getCsvString($separator); 258 | } 259 | } 260 | 261 | return $csv; 262 | } 263 | 264 | public function getCsvFile() 265 | { 266 | return $this->csv_file; 267 | } 268 | 269 | 270 | public function saveCsvFile($path, $separator = ",") 271 | { 272 | $file = new FileSystem(); 273 | return $file->put($path, $this->getCsvString($separator) ); 274 | } 275 | 276 | } 277 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/ParseCsv/CsvLine.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | use Jacopo\LaravelImportExport\Models\RuntimeModel; 10 | use Illuminate\Support\Facades\Config; 11 | 12 | class CsvLine extends RuntimeModel 13 | { 14 | public function __construct() 15 | { 16 | $this->connection = Config::get('laravel-import-export::baseconf.connection_name'); 17 | return parent::__construct( func_get_args() ); 18 | } 19 | 20 | public function getElements() 21 | { 22 | return $this->toArray(); 23 | } 24 | 25 | public function getCsvString($separator) 26 | { 27 | $attributes = $this->toArray(); 28 | return $this->arrayToCsv($attributes, $separator); 29 | } 30 | 31 | public function getCsvHeader($separator) 32 | { 33 | $attributes_keys = array_keys( $this->toArray() ); 34 | return $this->arrayToCsv($attributes_keys, $separator); 35 | } 36 | 37 | protected function arrayToCsv($attributes, $separator) 38 | { 39 | $str = ''; 40 | $attribute_size = count($attributes); 41 | $current_item = 1; 42 | foreach($attributes as $key => $attribute) 43 | { 44 | $str.="{$attribute}"; 45 | if( $current_item++ < $attribute_size) 46 | { 47 | $str.= $separator; 48 | } 49 | } 50 | $str.= "\n"; 51 | 52 | return $str; 53 | } 54 | } -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/ParseCsv/DbFileBuilder.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Illuminate\Support\Facades\DB; 9 | use Illuminate\Support\Facades\Config; 10 | 11 | class DbFileBuilder 12 | { 13 | protected $csv_file; 14 | /** 15 | * Import configuration: 16 | * columns: key (db name) value (export name) 17 | * table: table name 18 | * @var Array 19 | */ 20 | protected $config; 21 | 22 | public function __construct(array $config = null, $csv_file = null) 23 | { 24 | $this->config = $config; 25 | $this->csv_file = $csv_file ? $csv_file : new CsvFile; 26 | } 27 | 28 | /** 29 | * Build the CsvFile 30 | * 31 | * @throws Exception 32 | * @throws PDOException 33 | */ 34 | public function build(CsvLine $csv_line_base = null) 35 | { 36 | $csv_line_base = $csv_line_base ? $csv_line_base : new CsvLine; 37 | $stdclass_lines = $this->getAttributesFromDb(); 38 | foreach($stdclass_lines as $key => $line) 39 | { 40 | $csv_line = clone $csv_line_base; 41 | $csv_line->forceSetAttributes((Array)$line); 42 | $this->appendLine($csv_line); 43 | } 44 | } 45 | 46 | /** 47 | * Get the data from db 48 | * 49 | * @return Array 50 | */ 51 | protected function getAttributesFromDb() 52 | { 53 | $connection_name = Config::get('laravel-import-export::baseconf.connection_name'); 54 | return DB::connection($connection_name) 55 | ->table($this->config["table"]) 56 | ->select($this->createSelect() ) 57 | ->get(); 58 | } 59 | 60 | /** 61 | * Create select to make the CsvFile attributes 62 | * to export 63 | * 64 | * @return String 65 | */ 66 | protected function createSelect($config = null) 67 | { 68 | $config = $config ? $config : $this->config; 69 | $select = array(); 70 | if( ($columns = $config["columns"]) ) 71 | { 72 | foreach($columns as $db_key => $export_key) 73 | { 74 | $select[]= "{$db_key} as {$export_key}"; 75 | } 76 | } 77 | return $select; 78 | } 79 | 80 | protected function appendLine(CsvLine $line) 81 | { 82 | $this->csv_file->append($line); 83 | } 84 | 85 | public function setConfig($value) 86 | { 87 | $this->config = $value; 88 | } 89 | 90 | public function getCsvFile() 91 | { 92 | return $this->csv_file; 93 | } 94 | } -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/ParseCsv/File.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Jacopo\LaravelImportExport\Models\Exceptions\FileNotFoundException; 9 | 10 | class File 11 | { 12 | 13 | /** 14 | * @throws FileNotFoundException 15 | * @return Handle file handler 16 | */ 17 | public function openFile($file_path) 18 | { 19 | if( $file_path && file_exists($file_path) ) 20 | { 21 | return fopen($file_path, "r"); 22 | } 23 | else 24 | { 25 | throw new FileNotFoundException; 26 | } 27 | } 28 | 29 | public function closeFile($file) 30 | { 31 | return fclose($file); 32 | } 33 | 34 | public function readCsv($file,$max_length,$separator) 35 | { 36 | return fgetcsv($file,$max_length,$separator); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/ParseCsv/ParseCsv.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | Class ParseCsv 9 | { 10 | /** 11 | * Attributes: 12 | * file_path 13 | * separator 14 | */ 15 | protected $config; 16 | protected $csvFile; 17 | protected $file; 18 | protected $file_wrapper; 19 | 20 | public function __construct(array $config=null, File $file_wrapper = null) 21 | { 22 | if($config) 23 | { 24 | $this->config=$config; 25 | } 26 | 27 | $this->file_wrapper = $file_wrapper ?: new File; 28 | 29 | } 30 | 31 | 32 | public function parseCsvFile() 33 | { 34 | if( ! isset($this->file) ) 35 | { 36 | $this->openFile(); 37 | } 38 | 39 | $separator = (isset($this->config["separator"])) ? $this->config["separator"] : ","; 40 | $csv_line_array = $this->file_wrapper->readCsv($this->file,0,$separator); 41 | 42 | if( (! $csv_line_array) && (! is_null($csv_line_array)) ) 43 | { 44 | $this->closeFile(); 45 | } 46 | 47 | return $csv_line_array; 48 | } 49 | 50 | private function closeFile() 51 | { 52 | if( isset($this->file)) 53 | { 54 | $this->file_wrapper->closeFile($this->file); 55 | unset($this->file); 56 | } 57 | } 58 | 59 | /** 60 | * Open csv file 61 | * @return Handle file 62 | * @throws FileNotFoundException 63 | */ 64 | private function openFile() 65 | { 66 | $file_path = isset( $this->config["file_path"] ) ? $this->config["file_path"] : null; 67 | 68 | $this->file = $this->file_wrapper->openFile($file_path); 69 | } 70 | 71 | public function setConfig(array $value) 72 | { 73 | $this->config=$value; 74 | } 75 | } -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/RuntimeModel.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Illuminate\Database\Eloquent\Model; 9 | use Illuminate\Support\Facades\Config; 10 | 11 | class RuntimeModel extends Model 12 | { 13 | // validation rules 14 | protected $rules; 15 | 16 | protected static $unguarded = true; 17 | 18 | public $timestamps = false; 19 | 20 | protected $connection; 21 | 22 | public function __construc() 23 | { 24 | $args = func_get_args(); 25 | $this->connection = Config::get('laravel-import-export::baseconf.connection_name'); 26 | 27 | return parent::__construct($args); 28 | } 29 | 30 | /** 31 | * set parameters of the object 32 | * @param array $config 33 | * @throws InvalidArgumentException 34 | */ 35 | public function setConfig(array $configs) 36 | { 37 | foreach($configs as $config_key => $config_value) 38 | { 39 | if( property_exists(get_class($this), $config_key) ) 40 | { 41 | $this->$config_key = $config_value; 42 | } 43 | else 44 | { 45 | throw new \InvalidArgumentException; 46 | } 47 | } 48 | } 49 | 50 | public function forceSetAttribute($key, $value) 51 | { 52 | $this->attributes[$key]=$value; 53 | } 54 | 55 | public function forceSetAttributes(array $attributes) 56 | { 57 | foreach($attributes as $key => $value) 58 | { 59 | $this->attributes[$key]=$value; 60 | } 61 | } 62 | 63 | public function resetAttributes() 64 | { 65 | $this->attributes = array(); 66 | } 67 | 68 | public function canSavetoDb() 69 | { 70 | return ( isset($this->table) && static::isAssoc($this->attributes) ); 71 | } 72 | 73 | public static function isAssoc($array) { 74 | 75 | return (bool)count(array_filter(array_keys($array), 'is_string')); 76 | } 77 | 78 | public function getTableName() 79 | { 80 | return $this->table; 81 | } 82 | 83 | } -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/Export/ExportCompleteState.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Illuminate\Support\Facades\URL; 9 | use Illuminate\Support\Facades\Session; 10 | 11 | class ExportCompleteState extends GeneralState { 12 | 13 | /** 14 | * Return the form that needs to be processed 15 | */ 16 | protected function printFormNew(){ 17 | $str = parent::printFormNew(); 18 | 19 | $reset_url = $this->getResetUrl(); 20 | $download_path = Session::get($this->exchange_key); 21 | 22 | $str.=<< 24 |
25 | Download File 26 | Make a new Export 27 |
28 | 29 | STR; 30 | 31 | 32 | return $str; 33 | } 34 | 35 | public function printFormOld(){} 36 | public function processForm(){} 37 | public function fillFormInput(){} 38 | } 39 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/Export/GeneralState.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Jacopo\LaravelImportExport\Models\StateHandling\GeneralState as GeneralStateBase; 9 | 10 | abstract class GeneralState extends GeneralStateBase { 11 | 12 | protected $process_action = "Jacopo\LaravelImportExport\ExportController@postProcessForm"; 13 | protected $reset_state = "Jacopo\LaravelImportExport\ExportController@getResetState"; 14 | protected $exchange_key = 'export_state_exchange'; 15 | protected $errors_key = 'errors_export'; 16 | } 17 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/Export/GetTableConfig.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Illuminate\Support\Facades\Form; 9 | use Illuminate\Support\Facades\Session; 10 | use Jacopo\LaravelImportExport\Models\Exceptions\NoDataException; 11 | use Jacopo\LaravelImportExport\Models\ValidatorFormInputModel; 12 | use Jacopo\LaravelImportExport\Models\ParseCsv\CsvFileHandler; 13 | use Jacopo\LaravelImportExport\Models\InputWrapper as Input; 14 | 15 | class GetTableConfig extends GeneralState { 16 | 17 | protected $next_state_class = "Jacopo\LaravelImportExport\Models\StateHandling\Export\ExportCompleteState"; 18 | protected $csv_path = "download.csv"; 19 | protected $rules = array(); 20 | 21 | /** 22 | * Return the form that needs to be processed 23 | */ 24 | protected function printFormNew(){ 25 | $prev_data = Session::get($this->exchange_key); 26 | $str = parent::printFormNew(); 27 | $str.= "

Step2: fill save settings

". 28 | $prev_data["preview"]; 29 | // config form 30 | $str.="

Fill the form below:

"; 31 | $str.= Form::open(array( 'url' => $this->getProcessUrl(), "role" => "form", "class" => "form-horizontal") ); 32 | $str.= "
Write the name of each column to export (\"__empty\"=don't export)
"; 33 | $columns = $prev_data["column_names"]; 34 | foreach( $columns as $key => $column) 35 | { 36 | $str.= "
". 37 | Form::label("{$column}", "{$column}: ", array("class"=>"control-label col-lg-2")). 38 | "
". 39 | Form::text("{$column}", $column ,array("class"=>"form-control") ). 40 | "
". 41 | "
"; 42 | } 43 | $str.= "
". 44 | "
". 45 | Form::submit('Export' , array('class'=>'btn btn-success') ). 46 | "
". 47 | "
"; 48 | $str.= Form::close(); 49 | 50 | return $str; 51 | } 52 | 53 | /** 54 | * Return the form that has already been processed 55 | */ 56 | protected function printFormOld(){ 57 | $str = << 59 |
60 | Export table: completed succesfully! 61 |
62 |
63 | 64 | STR; 65 | return $str; 66 | } 67 | 68 | /** 69 | * Process the form 70 | * 71 | * @return Boolean $is_executed if the state is executed successfully 72 | */ 73 | public function processForm(array $input = null, $validator = null, CsvFileHandler $handler = null) 74 | { 75 | if($input) 76 | { 77 | $this->form_input = $input; 78 | } 79 | else 80 | { 81 | $this->fillFormInput(); 82 | } 83 | 84 | $validator = ($validator) ? $validator : new ValidatorFormInputModel($this); 85 | $handler = $handler ? $handler : new CsvFileHandler(); 86 | 87 | if ( $validator->validateInput() ) 88 | { 89 | $builder_config = array( 90 | "columns" => $this->form_input["attributes"], 91 | "table" => $this->form_input["table_name"], 92 | ); 93 | try 94 | { 95 | $handler->openFromDb($builder_config); 96 | } 97 | catch(\PDOException $e) 98 | { 99 | $this->appendError("DbException" , $e->getMessage() ); 100 | return $this->getIsExecuted(); 101 | } 102 | catch(\Exception $e) 103 | { 104 | $this->appendError("DbException" , $e->getMessage() ); 105 | return $this->getIsExecuted(); 106 | } 107 | try 108 | { 109 | $exchange_data = Session::get($this->exchange_key); 110 | $separator = $exchange_data["separator"]; 111 | $success = $handler->saveCsvFile($this->csv_path,$separator); 112 | if($success) 113 | { 114 | Session::put($this->exchange_key,$this->csv_path); 115 | $this->is_executed = true; 116 | } 117 | else 118 | { 119 | $this->appendError("Permission" , "Cannot save temporary data: please set write permission on public folder"); 120 | return $this->getIsExecuted(); 121 | } 122 | } 123 | catch(NoDataException $e) 124 | { 125 | $this->appendError("NoData" , "No data to save"); 126 | return $this->getIsExecuted(); 127 | } 128 | } 129 | else 130 | { 131 | $this->appendError("fileEmpty" , "No data found in the file" ); 132 | } 133 | 134 | return $this->getIsExecuted(); 135 | } 136 | 137 | public function fillFormInput($input = null) 138 | { 139 | $input = $input ? $input : new Input(); 140 | 141 | $prev_data = Session::get($this->exchange_key); 142 | 143 | $this->form_input["table_name"] = $prev_data["table_name"]; 144 | $columns = $prev_data["column_names"]; 145 | $this->form_input["attributes"] = array(); 146 | foreach( $columns as $key => $column) 147 | { 148 | $this->form_input["attributes"][$column] = $input->get($column); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/Export/GetTableName.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Illuminate\Support\Facades\Form; 9 | use Illuminate\Support\Facades\DB; 10 | use Illuminate\Support\Facades\Config; 11 | use Illuminate\Support\Facades\Session; 12 | use Jacopo\Bootstrap3Table\BootstrapTable as Table; 13 | use Jacopo\LaravelImportExport\Models\ValidatorFormInputModel; 14 | use Jacopo\LaravelImportExport\Models\DatabaseSchemaManager as DBM; 15 | use Jacopo\LaravelImportExport\Models\InputWrapper as Input; 16 | use Jacopo\LaravelImportExport\Models\Exceptions\NoDataException; 17 | 18 | class GetTableName extends GeneralState { 19 | 20 | protected $next_state_class = "Jacopo\LaravelImportExport\Models\StateHandling\Export\GetTableConfig"; 21 | 22 | protected $rules = array( 23 | "table_name" => "required", 24 | "max_rows" => "required|integer" 25 | ); 26 | 27 | /** 28 | * Return the form that needs to be processed 29 | */ 30 | protected function printFormNew(){ 31 | $str = parent::printFormNew(); 32 | $str .= 33 | "
\n". 34 | "
\n". 35 | "

Step1: get table data

\n". 36 | "\n". 37 | Form::open(array( 'url' => $this->getProcessUrl(), 'role' => 'form'))."\n". 38 | $this->createSelectTables(). 39 | "
". 40 | Form::label('separator','Type of separator: '). 41 | Form::select('separator' , array( ','=>'comma ,' , ';'=>'semicolon ;' ) , ',', array("class" => "form-control") ). 42 | "
". 43 | "
\n". 44 | Form::label('max_rows','Max number of lines to show in preview: ')."\n". 45 | Form::select('max_rows' , array('10'=>'10', '50'=>'50', '100'=>'100', '150'=>'150') , '10', array("class"=> "form-control") )."\n". 46 | "
\n". 47 | Form::submit('Open' , array('class'=>'btn btn-success'))."\n". 48 | Form::close(). 49 | "
\n". // form-group 50 | "
\n". // col 51 | "\n". // row 52 | "
\n"; 53 | 54 | return $str; 55 | } 56 | 57 | /** 58 | * Return the form that has already been processed 59 | */ 60 | protected function printFormOld(){ 61 | $reset_url = $this->getResetUrl(); 62 | 63 | $str=<< 65 |
66 | Reset Export 67 |
68 | 69 |
70 |
71 |
72 | Open table: completed succesfully! 73 |
74 |
75 |
76 | STR; 77 | return $str; 78 | } 79 | 80 | /** 81 | * Process the form 82 | * 83 | * @return Boolean $is_executed if the state is executed successfully 84 | */ 85 | public function processForm(array $input = null, $validator = null) 86 | { 87 | if($input) 88 | { 89 | $this->form_input = $input; 90 | } 91 | else 92 | { 93 | $this->fillFormInput(); 94 | } 95 | 96 | $validator = ($validator) ? $validator : new ValidatorFormInputModel($this); 97 | 98 | if ( $validator->validateInput() ) 99 | { 100 | try 101 | { 102 | $table_preview = $this->getDataTable(); 103 | } 104 | catch(BadMethodCallException $e) 105 | { 106 | $this->appendError("BadMethod" , "Invalid input data: cannot show the table." ); 107 | return $this->getIsExecuted(); 108 | } 109 | catch(NoDataException $e) 110 | { 111 | $this->appendError("NoData" , "The table is empty." ); 112 | return $this->getIsExecuted(); 113 | } 114 | $exchange_data = array( 115 | "preview" => $table_preview, 116 | "table_name" => $this->form_input["table_name"], 117 | "form_input" => $this->form_input, 118 | "column_names" => $this->getTableHeader(), 119 | "separator" => $this->form_input["separator"] 120 | ); 121 | $this->is_executed = true; 122 | // save data for next state 123 | Session::put($this->exchange_key, $exchange_data); 124 | } 125 | else 126 | { 127 | $this->appendError("fileEmpty" , "No data found in the file" ); 128 | } 129 | 130 | return $this->getIsExecuted(); 131 | } 132 | 133 | public function fillFormInput(Input $input = null) 134 | { 135 | $input = $input ? $input : new Input(); 136 | $this->form_input['table_name'] = $input->get('table_name'); 137 | $this->form_input['max_rows'] = $input->get('max_rows'); 138 | $this->form_input['separator'] = $input->get('separator'); 139 | } 140 | 141 | protected function createSelectTables() 142 | { 143 | $table_list = $this->getTableValuesSelect(); 144 | 145 | if($table_list) 146 | { 147 | $select = "
\n". 148 | Form::label('table_name','Table name to open:')."\n". 149 | Form::select('table_name' , $table_list , reset($table_list) , array("class"=> "form-control") )."\n". 150 | "
\n"; 151 | } 152 | else 153 | { 154 | $this->appendError("NoTables" , "No tables found in the db" ); 155 | $select = ''; 156 | } 157 | 158 | return $select; 159 | } 160 | 161 | /** 162 | * Return value with table names for a select 163 | * @return Array 164 | */ 165 | protected function getTableValuesSelect($dbm = null) 166 | { 167 | $dbm = $dbm ? $dbm : new DBM; 168 | $table_raw = $dbm->getTableList(); 169 | 170 | return $table_raw ? array_combine(array_values($table_raw), array_values($table_raw) ) : false; 171 | } 172 | 173 | /** 174 | * Return the table for the preview 175 | * @return String $table 176 | */ 177 | protected function getDataTable() 178 | { 179 | $data = $this->getTableData(); 180 | $header = $this->getTableHeader(); 181 | 182 | $table = new Table(); 183 | // set the configuration 184 | $table->setConfig(array( 185 | "table-hover"=>true, 186 | "table-condensed"=>false, 187 | "table-responsive" => true, 188 | "table-striped" => true, 189 | )); 190 | // set header 191 | $table->setHeader( $header ); 192 | // set data 193 | foreach($data as $val) 194 | { 195 | $table->addRows( get_object_vars($val) ); 196 | } 197 | 198 | return $table->getHtml(); 199 | } 200 | 201 | /** 202 | * Get the data from the db for the preview 203 | * 204 | * @throws BadMethodCallException 205 | * @throws NoDataException 206 | * @return Array $data 207 | */ 208 | protected function getTableData() 209 | { 210 | $data = array(); 211 | $form_input = $this->getFormInput(); 212 | 213 | if( $form_input['table_name'] && $form_input['max_rows'] ) 214 | { 215 | $connection_name = Config::get('laravel-import-export::baseconf.connection_name'); 216 | $temp_data = DB::connection($connection_name) 217 | ->table($this->form_input['table_name']) 218 | ->select("*") 219 | ->take($this->form_input['max_rows']); 220 | if( $temp_data->exists() ) 221 | { 222 | $data = $temp_data->get(); 223 | } 224 | else 225 | { 226 | throw new NoDataException; 227 | } 228 | } 229 | else 230 | { 231 | throw new \BadMethodCallException; 232 | } 233 | 234 | return $data; 235 | } 236 | 237 | /** 238 | * Get the header for the preview 239 | * 240 | * @throws BadMethodCallException 241 | * @return Array $columns 242 | */ 243 | protected function getTableHeader($dbm = null) 244 | { 245 | $dbm = $dbm ? $dbm : new DBM; 246 | $columns = array(); 247 | $form_input = $this->getFormInput(); 248 | 249 | if( $form_input['table_name'] ) 250 | { 251 | $dbal_columns = $dbm->getTableColumns($this->form_input['table_name']); 252 | foreach($dbal_columns as $column) 253 | { 254 | $array_columns = $column->toArray(); 255 | $columns[] = $array_columns["name"]; 256 | } 257 | } 258 | else 259 | { 260 | throw new \BadMethodCallException; 261 | } 262 | 263 | return $columns; 264 | } 265 | 266 | } 267 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/Export/StateHandler.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Illuminate\Support\Facades\Config; 9 | use Illuminate\Support\Facades\Session; 10 | use Illuminate\Support\Facades\Response; 11 | use Jacopo\LaravelImportExport\Models\StateHandling\StateHandler as StateHandlerBase; 12 | 13 | class StateHandler extends StateHandlerBase 14 | { 15 | protected $session_key; 16 | protected $initial_state = "Jacopo\LaravelImportExport\Models\StateHandling\Export\GetTableName"; 17 | 18 | public function __construct() 19 | { 20 | $this->session_key = Config::get('laravel-import-export::baseconf.session_export_key','export_state'); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/GeneralState.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Jacopo\LaravelImportExport\Models\StateHandling\StateInterface; 9 | use Illuminate\Support\Facades\Config; 10 | use Illuminate\Support\Facades\URL; 11 | use Illuminate\Support\Facades\Session; 12 | use Illuminate\Support\MessageBag; 13 | use Jacopo\LaravelImportExport\Models\Exceptions\ClassNotFoundException; 14 | 15 | abstract class GeneralState implements StateInterface { 16 | 17 | /** 18 | * Name of the next state class 19 | * @var String 20 | */ 21 | protected $next_state_class; 22 | /** 23 | * Name of the action to process the form 24 | * @var String 25 | */ 26 | protected $process_action; 27 | /** 28 | * if the status has already been executed with success 29 | * @var boolean 30 | */ 31 | /** 32 | * Name of the action to reset current state 33 | * @var string 34 | */ 35 | protected $reset_state; 36 | /** 37 | * If the state has been executed 38 | * @var boolean 39 | */ 40 | protected $is_executed = false; 41 | /** 42 | * The imput given from the form 43 | * @var Mixed 44 | */ 45 | protected $form_input; 46 | /** 47 | * Validation rules 48 | * @var Array 49 | */ 50 | protected $rules; 51 | /** 52 | * Validation erorrs 53 | * @var Array 54 | */ 55 | protected $errors; 56 | /** 57 | * key of the session used to exchange data between states 58 | * @var string 59 | */ 60 | protected $exchange_key; 61 | /** 62 | * Return the form 63 | */ 64 | /** 65 | * Name of session key which store errors 66 | * @var String 67 | */ 68 | protected $errors_key; 69 | 70 | public function getForm(){ 71 | 72 | if( ! $this->getIsExecuted() ) 73 | { 74 | return $this->printFormNew(); 75 | } 76 | else 77 | { 78 | return $this->printFormOld(); 79 | } 80 | } 81 | 82 | protected function getProcessUrl() 83 | { 84 | return URL::action($this->process_action); 85 | } 86 | 87 | /** 88 | * Return the next state 89 | * 90 | * @throws Jacopo\LaravelImportExport\Exception\ClassNotFoundException 91 | * @return ImportState 92 | */ 93 | public function getNextState() 94 | { 95 | if( $this->getIsExecuted() ) 96 | { 97 | if ( class_exists( $next = $this->getNextStateClass() ) ) 98 | { 99 | return (new $next ); 100 | } 101 | else 102 | { 103 | throw new ClassNotFoundException; 104 | } 105 | } 106 | else 107 | { 108 | return $this; 109 | } 110 | } 111 | 112 | /** 113 | * Print the form errors if exists 114 | * 115 | * @return String|null 116 | */ 117 | public function getErrorHeader() 118 | { 119 | $err_str = ''; 120 | $error_class = $this->getErrors(); 121 | $error_session = Session::get($this->errors_key); 122 | 123 | if( $error_class ) 124 | { 125 | foreach ($error_class->all() as $error_key => $error) { 126 | $err_str.="
{$error}
"; 127 | } 128 | } 129 | 130 | if( $error_session) 131 | { 132 | foreach ($error_session->all() as $error_key => $error) { 133 | $err_str.="
{$error}
"; 134 | } 135 | } 136 | 137 | $this->resetErrors(); 138 | 139 | return $err_str; 140 | } 141 | 142 | public function getRules() 143 | { 144 | return $this->rules; 145 | } 146 | 147 | public function getErrors() 148 | { 149 | return $this->errors; 150 | } 151 | 152 | public function setErrors($value) 153 | { 154 | $this->errors = $value; 155 | } 156 | 157 | public function getFormInput() 158 | { 159 | return $this->form_input; 160 | } 161 | 162 | public function getIsExecuted() 163 | { 164 | return $this->is_executed; 165 | } 166 | 167 | public function getNextStateClass() 168 | { 169 | return $this->next_state_class; 170 | } 171 | 172 | /** 173 | * Return the form that needs to be processed 174 | */ 175 | protected function printFormNew() 176 | { 177 | return $this->getErrorHeader(); 178 | } 179 | /** 180 | * Return the form that has already been processed 181 | */ 182 | protected abstract function printFormOld(); 183 | 184 | /** 185 | * Process the form and update the current state 186 | * @return ImportState 187 | */ 188 | public abstract function processForm(); 189 | 190 | public abstract function fillFormInput(); 191 | 192 | function __sleep() 193 | { 194 | $serialize_fields = array(); 195 | 196 | $serialize_fields[] = 'next_state_class'; 197 | $serialize_fields[] = 'is_executed'; 198 | $serialize_fields[] = 'process_action'; 199 | $serialize_fields[] = 'reset_state'; 200 | $serialize_fields[] = 'rules'; 201 | $serialize_fields[] = 'errors'; 202 | 203 | return $serialize_fields; 204 | } 205 | 206 | /** 207 | * Append error to the MessageBag 208 | */ 209 | public function appendError($error_key, $error_string) 210 | { 211 | if($this->getErrors()) 212 | { 213 | // append 214 | $this->errors->add( $error_key, $error_string ); 215 | } 216 | else 217 | { 218 | // new MessageBag 219 | $this->errors = new MessageBag( array($error_key => $error_string) ); 220 | } 221 | } 222 | 223 | protected function getResetUrl() 224 | { 225 | return \URL::action($this->reset_state); 226 | } 227 | 228 | /** 229 | * Clean all errors 230 | */ 231 | protected function resetErrors() 232 | { 233 | Session::forget($this->errors_key); 234 | $this->errors = array(); 235 | } 236 | 237 | } 238 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/Import/GeneralState.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Jacopo\LaravelImportExport\Models\StateHandling\GeneralState as GeneralStateBase; 9 | 10 | abstract class GeneralState extends GeneralStateBase { 11 | 12 | protected $process_action = "Jacopo\LaravelImportExport\ImportController@postProcessForm"; 13 | protected $reset_state = "Jacopo\LaravelImportExport\ImportController@getResetState"; 14 | protected $exchange_key = 'import_state_exchange'; 15 | protected $errors_key = 'errors_import'; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/Import/GetCsvState.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Exception; 9 | use Illuminate\Support\Facades\Form; 10 | use Illuminate\Support\Facades\Input; 11 | use Illuminate\Support\Facades\Session; 12 | use Jacopo\LaravelImportExport\Models\ValidatorFormInputModel; 13 | use Jacopo\LaravelImportExport\Models\ParseCsv\CsvFileHandler; 14 | use Jacopo\LaravelImportExport\Models\Exceptions\FileNotFoundException; 15 | use Jacopo\LaravelImportExport\Models\Exceptions\InvalidArgumentException; 16 | use Jacopo\LaravelImportExport\Models\Exceptions\NoDataException; 17 | use Jacopo\LaravelImportExport\Models\Exceptions\UnalignedArrayException; 18 | use Jacopo\LaravelImportExport\Models\Exceptions\DomainException; 19 | 20 | class GetCsvState extends GeneralState { 21 | 22 | protected $next_state_class = "Jacopo\LaravelImportExport\Models\StateHandling\Import\GetTableState"; 23 | 24 | protected $rules = array( 25 | "file_csv" => "required", 26 | ); 27 | 28 | /** 29 | * Return the form that needs to be processed 30 | */ 31 | protected function printFormNew(){ 32 | $str = parent::printFormNew(); 33 | $str .= 34 | "
". 35 | "
". 36 | "

Step1: Upload file

". 37 | // "". 38 | Form::open(array( 'url' => $this->getProcessUrl(), 'files' => true , 'role' => 'form')). 39 | "
". 40 | Form::label('file_csv', 'Select file to upload (CSV only for now) *'). 41 | Form::file('file_csv'). 42 | "
". 43 | "
". 44 | Form::label('separator','Type of separator: '). 45 | Form::select('separator' , array( ','=>'comma ,' , ';'=>'semicolon ;' ) , ',', array("class" => "form-control") ). 46 | "
". 47 | "
". 48 | Form::label('max_lines','Max number of lines to show in preview: '). 49 | Form::select('max_lines' , array('10'=>'10', '50'=>'50', '100'=>'100', '150'=>'150') , '10', array("class"=> "form-control") ). 50 | "
". 51 | "
". 52 | "". 56 | "
". 57 | "
". 58 | "". 62 | "
". 63 | "
". 64 | Form::submit('Load' , array('class'=>'btn btn-success')). 65 | Form::close(). 66 | "
". // form-group 67 | "
". // col 68 | "
". // row 69 | "
"; 70 | 71 | return $str; 72 | } 73 | 74 | /** 75 | * Return the form that has already been processed 76 | */ 77 | protected function printFormOld(){ 78 | $reset_url = $this->getResetUrl(); 79 | 80 | $str=<< 82 |
83 | Reset Import 84 |
85 | 86 |
87 |
88 |
89 | Upload file: completed succesfully! 90 |
91 |
92 |
93 | STR; 94 | return $str; 95 | } 96 | 97 | /** 98 | * Process the form 99 | * 100 | * @return Boolean $is_executed if the state is executed successfully 101 | */ 102 | public function processForm(array $input = null, $validator = null, $csv_handler = null) 103 | { 104 | if($input) 105 | { 106 | $this->form_input = $input; 107 | } 108 | else 109 | { 110 | $this->fillFormInput(); 111 | } 112 | 113 | $validator = ($validator) ? $validator : new ValidatorFormInputModel($this); 114 | $csv_handler = ($csv_handler) ? $csv_handler : new CsvFileHandler(); 115 | 116 | if ( $validator->validateInput() && $this->checkInputCsv() ) 117 | { 118 | // process data 119 | $config = $this->getConfigFromInput(); 120 | $success = true; 121 | // big try catch to set errors 122 | try 123 | { 124 | $csv_file = $csv_handler->openFromCsv($config); 125 | } 126 | catch(FileNotFoundException $e) 127 | { 128 | $this->appendError("NotFound", "File not found." ); 129 | $success = false; 130 | } 131 | catch(InvalidArgumentException $e) 132 | { 133 | $this->appendError("InvalidArgument", "Invalid argument." ); 134 | $success = false; 135 | } 136 | catch(DomainException $e) 137 | { 138 | $this->appendError("Domain", "Invalid temporary data." ); 139 | $success = false; 140 | } 141 | catch(UnalignedArrayException $e) 142 | { 143 | $this->appendError("UnalignedArray", "Unaligned data." ); 144 | $success = false; 145 | } 146 | catch(NoDataException $e) 147 | { 148 | $this->appendError("NoData", "No data found in the file." ); 149 | $success = false; 150 | } 151 | 152 | // save temporary 153 | if($success) 154 | { 155 | $saved = false; 156 | 157 | try 158 | { 159 | $saved = $csv_handler->saveTemporary(); 160 | } 161 | catch( Exception $e) 162 | { 163 | $this->appendError("SaveTemporary" , "Cannot save temporary data: check database access configuration." ); 164 | } 165 | 166 | if($saved) 167 | { 168 | $this->is_executed = true; 169 | // add if want to create table to session 170 | $exchange_data = array( 171 | "max_lines" => $this->form_input['max_lines'], 172 | "create_table" => $this->form_input['create_table'] 173 | ); 174 | // save data for next state 175 | Session::put($this->exchange_key,$exchange_data); 176 | } 177 | } 178 | } 179 | 180 | return $this->getIsExecuted(); 181 | } 182 | 183 | public function fillFormInput() 184 | { 185 | if(Input::hasFile('file_csv')) 186 | { 187 | $this->form_input['file_csv'] = Input::file('file_csv'); 188 | }else 189 | { 190 | $this->form_input['file_csv'] = ''; 191 | } 192 | $this->form_input['separator'] = Input::get('separator'); 193 | $this->form_input['headers'] = Input::get('headers'); 194 | $this->form_input['max_lines'] = Input::get('max_lines'); 195 | $this->form_input['create_table'] = Input::get('create_table'); 196 | } 197 | 198 | protected function checkInputCsv() 199 | { 200 | $valid = false; 201 | 202 | $input = $this->form_input['file_csv']; 203 | if( ! empty($input) ) 204 | { 205 | $name = $this->form_input['file_csv']->getClientOriginalName(); 206 | if(strstr($name,".")) 207 | { 208 | $name = explode(".",$name); 209 | $extension = end($name); 210 | if(strcasecmp($extension,"csv") == 0) 211 | $valid = true; 212 | } 213 | } 214 | 215 | if( ! $valid ) 216 | { 217 | $this->appendError("Invalid_extension", "The input file must be .csv" ); 218 | } 219 | 220 | return $valid; 221 | } 222 | 223 | // get the config from form input 224 | protected function getConfigFromInput() 225 | { 226 | $config_file_parse['separator'] = $this->form_input['separator']; 227 | $config_file_parse['file_path'] = $this->form_input['file_csv']->getRealPath(); 228 | $config["file_parse"] = $config_file_parse; 229 | 230 | $config_builder['first_line_headers'] = ( $this->form_input['headers'] != '' ); 231 | $config["builder"] = $config_builder; 232 | 233 | $config_model = array(); 234 | $config["model"] = $config_model; 235 | 236 | return $config; 237 | } 238 | 239 | } 240 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/Import/GetTableState.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Illuminate\Support\Facades\Form; 9 | use Illuminate\Support\Facades\Session; 10 | use Jacopo\LaravelImportExport\Models\InputWrapper as Input; 11 | use Jacopo\LaravelImportExport\Models\ParseCsv\CsvFileHandler; 12 | use Jacopo\LaravelImportExport\Models\ParseCsv\CsvFile; 13 | use Jacopo\LaravelImportExport\Models\ValidatorFormInputModel; 14 | use Jacopo\LaravelImportExport\Models\Exceptions\UnalignedArrayException; 15 | use Jacopo\LaravelImportExport\Models\Exceptions\NoDataException; 16 | use Jacopo\LaravelImportExport\Models\Exceptions\HeadersNotSetException; 17 | use Jacopo\Bootstrap3Table\BootstrapTable as Table; 18 | use Exception; 19 | 20 | class GetTableState extends GeneralState { 21 | 22 | protected $next_state_class = "Jacopo\LaravelImportExport\Models\StateHandling\Import\ImportCompleteState"; 23 | 24 | protected $rules = array( 25 | "table_name" => "required" 26 | ); 27 | 28 | /** 29 | * Return the form that needs to be processed 30 | */ 31 | protected function printFormNew(){ 32 | 33 | $str = parent::printFormNew(); 34 | 35 | $csv_handler = new CsvFileHandler(); 36 | $csv_file = $csv_handler->getTemporary(); 37 | 38 | $str.= "
". 39 | "
". 40 | "

Step2: Configure import data

". 41 | "
Sample data from csv file:
"; 42 | try 43 | { 44 | $str.= $this->getCsvTableStr($csv_handler, $csv_file); 45 | } 46 | catch(NoDataException $e) 47 | { 48 | } 49 | 50 | $str.= "

Fill the form below:

"; 51 | $exchange_data = Session::get($this->exchange_key); 52 | $setSchema = $exchange_data["create_table"]; 53 | $str.= $this->getConfigForm($csv_handler, $csv_file, $setSchema); 54 | 55 | $str.= "
". // col-md-12 56 | "
"; // row 57 | 58 | return $str; 59 | } 60 | 61 | /** 62 | * Return the form that has already been processed 63 | */ 64 | protected function printFormOld(){ 65 | 66 | $str=<< 68 |
69 | Save file: completed succesfully! 70 |
71 |
72 | 73 | 74 | STR; 75 | return $str; 76 | } 77 | 78 | protected function getConfigForm(CsvFileHandler $csv_handler, CsvFile $csv_file, $setSchema = false) 79 | { 80 | $str = Form::open(array( 'url' => $this->getProcessUrl(), "role" => "form", "class" => "form-horizontal") ); 81 | 82 | // table name 83 | $str.= "
". 84 | Form::label("table_name", "Table name to save: *", array("class"=>"control-label col-lg-2")). 85 | "
". 86 | Form::text("table_name","table" ,array("class"=>"form-control") ). 87 | "
". 88 | "
"; 89 | 90 | // column names 91 | $str.= "
Write the name of each column to save into the DB, the index number are the same as the column number in the sample data(\"__empty\"=don't save)
"; 92 | $num_cols = $csv_handler->getMaxLength(); 93 | $header = $csv_file->getCsvHeader(); 94 | foreach( range(0,$num_cols-1) as $key) 95 | { 96 | $default_value = isset($header[$key]) ? $header[$key] : "__empty"; 97 | $str.= "
". 98 | Form::label("column_{$key}", "Column".($key+1).": ", array("class"=>"control-label col-lg-2") ). 99 | "
". 100 | Form::text("column_{$key}", $default_value ,array("class"=>"form-control bottom-10") ). 101 | "
"; 102 | if($setSchema) 103 | { 104 | $str.= $this->getSelectSchema("column_type_{$key}"); 105 | $str.= Form::hidden('create_schema','1'); 106 | } 107 | $str.="
"; 108 | } 109 | $str.= Form::hidden("num_cols",$num_cols); 110 | $str.= "
". 111 | "
". 112 | Form::submit('Import' , array('class'=>'btn btn-success') ). 113 | "
". 114 | "
"; 115 | 116 | $str.= Form::close(); 117 | 118 | return $str; 119 | 120 | } 121 | 122 | /** 123 | * Return a select for the type of data to create 124 | * 125 | * @param $name select name and id 126 | * @return String $select 127 | */ 128 | protected function getSelectSchema($name) 129 | { 130 | $data_types = array( 131 | "string" => "string", 132 | "integer" => "integer", 133 | "increments" => "increments", 134 | "bigIncrements" => "bigIncrements", 135 | "bigInteger" => "bigInteger", 136 | "smallInteger" => "smallInteger", 137 | "float" => "float", 138 | "double" => "double", 139 | "decimal" => "decimal", 140 | "boolean" => "boolean", 141 | "date" => "date", 142 | "dateTime" => "dateTime", 143 | "time" => "time", 144 | "blob" => "binary", 145 | ); 146 | 147 | $select =Form::label($name,'Type: ', array("class"=>"control-label col-lg-2") ). 148 | "
". 149 | Form::select($name , $data_types, '', array("class" => "form-control") ). 150 | "
"; 151 | 152 | return $select; 153 | } 154 | 155 | /** 156 | * Return the table rappresenting the csv data 157 | * 158 | * @throws NoDataException 159 | * @return String $table 160 | */ 161 | protected function getCsvTableStr(CsvFileHandler $csv_handler, CsvFile $csv_file) 162 | { 163 | if(! $csv_file) 164 | { 165 | throw new NoDataException(); 166 | } 167 | 168 | $table = new Table(); 169 | // set the configuration 170 | $table->setConfig(array( 171 | "table-hover"=>true, 172 | "table-condensed"=>false, 173 | "table-responsive" => true, 174 | "table-striped" => true, 175 | )); 176 | 177 | // set header 178 | if( $csv_header = $csv_file->getCsvHeader() ) 179 | { 180 | $table->setHeader( $csv_header ); 181 | } 182 | 183 | // set content 184 | $exchange_data = Session::get($this->exchange_key); 185 | $max_num_lines = $exchange_data["max_lines"]; 186 | foreach( $csv_file as $csv_line_key => $csv_line) 187 | { 188 | if($csv_line_key >= $max_num_lines) 189 | break; 190 | 191 | // add data table row 192 | $table->addRows( $csv_line->getElements() ); 193 | } 194 | 195 | 196 | 197 | return $table->getHtml(); 198 | } 199 | 200 | /** 201 | * Process the form and return the next state 202 | * @return Boolean $is_executed 203 | */ 204 | public function processForm(array $input = null, $validator = null, $csv_handler = null) 205 | { 206 | if($input) 207 | { 208 | $this->form_input = $input; 209 | } 210 | else 211 | { 212 | $this->fillFormInput(); 213 | } 214 | 215 | $validator = ($validator) ? $validator : new ValidatorFormInputModel($this); 216 | $csv_handler = ($csv_handler) ? $csv_handler : new CsvFileHandler(); 217 | 218 | if ( $validator->validateInput() && $this->checkColumns() ) 219 | { 220 | // process form 221 | $csv_file = $csv_handler->getTemporary(); 222 | if($csv_file) 223 | { 224 | try 225 | { 226 | $csv_handler->updateHeaders($csv_file, $this->form_input["columns"], $this->form_input["table_name"]); 227 | } 228 | catch(UnalignedArrayException $e) 229 | { 230 | $this->appendError("No_temporary", "Invalid Column names." ); 231 | return $this->getIsExecuted(); 232 | } 233 | 234 | try 235 | { 236 | $csv_handler->saveToDb($this->form_input['types']); 237 | $this->is_executed = true; 238 | } 239 | catch( HeadersNotSetException $e) 240 | { 241 | $this->appendError("Save_err", "Cannot save data: check if dmbs support transaction."); 242 | } 243 | catch( PDOException $e) 244 | { 245 | $this->appendError("Save_err", $e->getMessage() ); 246 | } 247 | catch( Exception $e) 248 | { 249 | $this->appendError("Save_err", $e->getMessage() ); 250 | } 251 | } 252 | else 253 | { 254 | $this->appendError("No_temporary","No data available to save"); 255 | } 256 | } 257 | return $this->getIsExecuted(); 258 | } 259 | 260 | public function fillFormInput(Input $input = null) 261 | { 262 | $input = $input ? $input : new Input(); 263 | $this->form_input['table_name'] = $input->get('table_name'); 264 | $num_cols = $input->get('num_cols'); 265 | if($num_cols) 266 | { 267 | $array_cols = array(); 268 | $array_type = array(); 269 | // if need to create schema 270 | $this->form_input['create_schema'] = $input->get('create_schema'); 271 | foreach( range(0,$num_cols-1) as $key) 272 | { 273 | $column_name = $input->get("column_{$key}"); 274 | if( $column_name != '__empty') 275 | { 276 | $array_cols = array_merge($array_cols , array( $key => $column_name) ); 277 | $column_type = $input->get("column_type_{$key}"); 278 | $array_type = array_merge($array_type , array( $column_name => $column_type) ); 279 | } 280 | } 281 | $this->form_input['types'] = $array_type; 282 | $this->form_input['columns'] = $array_cols; 283 | } 284 | } 285 | 286 | /** 287 | * Check the column field if atleast one exists 288 | * @return Boolean $success 289 | */ 290 | protected function checkColumns() 291 | { 292 | $success = false; 293 | 294 | if ( ! empty($this->form_input['columns']) ) 295 | { 296 | $success = true; 297 | } 298 | else 299 | { 300 | $this->appendError("No_columns","No column name setted: you need to fill atleast one \"column_\" field"); 301 | } 302 | 303 | return $success; 304 | } 305 | 306 | } 307 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/Import/ImportCompleteState.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | class ImportCompleteState extends GeneralState { 9 | 10 | /** 11 | * Return the form that needs to be processed 12 | */ 13 | protected function printFormNew(){ 14 | 15 | $str = parent::printFormNew(); 16 | 17 | $reset_url = $this->getResetUrl(); 18 | 19 | $str.=<< 21 | 24 | 25 | STR; 26 | 27 | 28 | return $str; 29 | } 30 | 31 | public function printFormOld(){} 32 | public function processForm(){} 33 | public function fillFormInput(){} 34 | } 35 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/Import/StateHandler.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Illuminate\Support\Facades\Config; 9 | use Illuminate\Support\Facades\DB; 10 | use Jacopo\LaravelImportExport\Models\StateHandling\StateHandler as StateHandlerBase; 11 | 12 | class StateHandler extends StateHandlerBase 13 | { 14 | protected $session_key; 15 | protected $initial_state = "Jacopo\LaravelImportExport\Models\StateHandling\Import\GetCsvState"; 16 | 17 | public function __construct() 18 | { 19 | $this->session_key = Config::get('laravel-import-export::baseconf.session_import_key','import_state'); 20 | } 21 | 22 | /** 23 | * Reset the session_array state 24 | */ 25 | public function resetState() 26 | { 27 | parent::resetState(); 28 | 29 | // clean temporary db 30 | $table_name = Config::get('laravel-import-export::baseconf.table_prefix'); 31 | $connection_name = Config::get('laravel-import-export::baseconf.connection_name'); 32 | DB::connection($connection_name)->table($table_name)->truncate(); 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/StateArray.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use \ArrayIterator; 9 | 10 | class StateArray extends ArrayIterator {} 11 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/StateHandler.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Illuminate\Support\Facades\Session; 9 | use Illuminate\Support\Facades\DB; 10 | use Illuminate\Support\Facades\Config; 11 | use Illuminate\Support\MessageBag; 12 | use Jacopo\LaravelImportExport\Models\Exceptions\NoDataException; 13 | use Jacopo\LaravelImportExport\Models\Exceptions\ClassNotFoundException; 14 | 15 | class StateHandler 16 | { 17 | protected $session_key; 18 | protected $initial_state; 19 | protected $state_array; 20 | 21 | /** 22 | * Initialize starting import state from session 23 | */ 24 | public function initializeState() 25 | { 26 | if (Session::has($this->session_key)) 27 | { 28 | $this->setStateArray( Session::get($this->session_key) ); 29 | } 30 | else 31 | { 32 | $this->resetState(); 33 | } 34 | return $this->getStateArray(); 35 | } 36 | 37 | /** 38 | * Reset the session_array state 39 | */ 40 | public function resetState() 41 | { 42 | // clean states 43 | $this->setStateArray( new StateArray() ); 44 | $state_array = $this->getStateArray(); 45 | $state_array->append( new $this->initial_state ); 46 | Session::put($this->session_key,$state_array); 47 | } 48 | 49 | /** 50 | * Fill layout content with forms 51 | */ 52 | public function setContent($layout) 53 | { 54 | $content = ''; 55 | 56 | $state_array = $this->getStateArray(); 57 | foreach($state_array as $state_key => $state) 58 | { 59 | $content.=$state->getForm(); 60 | } 61 | $layout->content = $content; 62 | } 63 | 64 | /** 65 | * Process the current form 66 | * @return $executed if success 67 | * @throws ClassNotFoundException 68 | */ 69 | public function processForm() 70 | { 71 | $current_state = $this->getCurrent(); 72 | $executed_process = $current_state->processForm(); 73 | // set next state 74 | $executed_next_state = $this->setNextState($current_state,$executed_process); 75 | // return success 76 | return ( $executed_process && $executed_next_state ); 77 | } 78 | 79 | /** 80 | * Set the next state 81 | * 82 | * @return Boolean $success 83 | */ 84 | protected function setNextState($current_state, $executed) 85 | { 86 | try 87 | { 88 | $next_state = $current_state->getNextState(); 89 | } 90 | catch(ClassNotFoundException $e) 91 | { 92 | Session::put('Errors', new MessageBag( array("Class" => "Class not found") ) ); 93 | return false; 94 | } 95 | 96 | if($executed) 97 | { 98 | // append next state 99 | $this->append($next_state); 100 | } 101 | else 102 | { 103 | // replace current state 104 | $this->replaceCurrent($next_state); 105 | } 106 | 107 | return true; 108 | } 109 | 110 | protected function append($value) 111 | { 112 | $this->state_array->append($value); 113 | } 114 | 115 | public function getCurrent() 116 | { 117 | return $this->getLastState(); 118 | } 119 | 120 | /** 121 | * Replace the current state 122 | */ 123 | public function replaceCurrent($value) 124 | { 125 | $key = $this->getLastKey(); 126 | if($key >= 0) 127 | { 128 | $this->getStateArray()->offsetSet($key,$value); 129 | } 130 | else 131 | { 132 | throw new NoDataException; 133 | } 134 | } 135 | 136 | public function getLastState() 137 | { 138 | $key = $this->getLastKey(); 139 | if($key >= 0) 140 | { 141 | $state_array = $this->getStateArray(); 142 | return $state_array[$key]; 143 | } 144 | else 145 | { 146 | throw new NoDataException; 147 | } 148 | } 149 | 150 | public function getLastKey() 151 | { 152 | return ( count($this->state_array) - 1 ); 153 | } 154 | 155 | public function getStateArray() 156 | { 157 | return $this->state_array; 158 | } 159 | 160 | public function setStateArray($value) 161 | { 162 | $this->state_array = $value; 163 | } 164 | 165 | } 166 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/StateHandling/StateInterface.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Illuminate\Database\Eloquent\Model; 9 | use Illuminate\Support\Facades\Config; 10 | 11 | class TemporaryModel extends Model { 12 | 13 | protected $table; 14 | 15 | protected $fillable = array('file_object','id'); 16 | 17 | public $timestamps = false; 18 | 19 | protected $connection; 20 | 21 | // test model saving and getting 22 | public function __construct() 23 | { 24 | $this->table = Config::get('laravel-import-export::baseconf.table_prefix'); 25 | $this->connection = Config::get('laravel-import-export::baseconf.connection_name'); 26 | 27 | $params = func_get_args(); 28 | 29 | return parent::__construct($params); 30 | } 31 | 32 | // encode object for saving 33 | public function setFileObjectAttribute($value) 34 | { 35 | $this->attributes['file_object'] = base64_encode( serialize($value) ); 36 | } 37 | 38 | // decode object for saving 39 | public function getFileObjectAttribute() 40 | { 41 | return unserialize( base64_decode( $this->attributes['file_object'] ) ); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/Models/ValidatorFormInputModel.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use Illuminate\Support\Facades\Validator; 9 | use Illuminate\Database\Eloquent\Model; 10 | 11 | class ValidatorFormInputModel extends Model { 12 | 13 | protected $model; 14 | 15 | public function __construct($model) 16 | { 17 | $this->model = $model; 18 | } 19 | 20 | /** 21 | * Validate form_input with $rules 22 | * @return Boolean 23 | */ 24 | public function validateInput() 25 | { 26 | $v = Validator::make ( $this->model->getFormInput() , $this->model->getRules() ); 27 | 28 | $success = true; 29 | if ( $v->fails() ) 30 | { 31 | $this->model->setErrors( $v->messages() ); 32 | $success = false; 33 | } 34 | 35 | return $success; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/Jacopo/LaravelImportExport/routes.php: -------------------------------------------------------------------------------- 1 | "_import_export_temporary_table", 5 | "default_title" => "Laravel-Import-Export", 6 | "session_import_key" => "import_state", 7 | "session_export_key" => "export_state", 8 | "base_application_route" => "importer", 9 | "connection_name" => "import", 10 | ); -------------------------------------------------------------------------------- /src/config/database.php: -------------------------------------------------------------------------------- 1 | array( 5 | 6 | 'import' => array( 7 | 'driver' => 'mysql', //sqlite | mysql | pgsql | sqlsrv 8 | 'host' => 'localhost', 9 | 'database' => 'laravel_import_export', 10 | 'username' => 'root', 11 | 'password' => 'root', 12 | 'charset' => 'utf8', 13 | 'collation' => 'utf8_unicode_ci', 14 | 'prefix' => '', 15 | ), 16 | ), 17 | ); -------------------------------------------------------------------------------- /src/controllers/BaseController.php: -------------------------------------------------------------------------------- 1 | layout)) 22 | { 23 | $this->layout = View::make($this->layout); 24 | // set menu index 25 | $this->layout->menu_index = $this->menu_index; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/controllers/ExportController.php: -------------------------------------------------------------------------------- 1 | setContent($this->layout); 13 | } 14 | 15 | public function getResetState() 16 | { 17 | \App::make('export_csv_handler')->resetState(); 18 | 19 | return \Redirect::action('Jacopo\LaravelImportExport\ExportController@getIndex'); 20 | } 21 | 22 | public function postProcessForm() 23 | { 24 | $success =\App::make('export_csv_handler')->processForm(); 25 | 26 | return \Redirect::action('Jacopo\LaravelImportExport\ExportController@getIndex'); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /src/controllers/HomeController.php: -------------------------------------------------------------------------------- 1 | layout->nest('content','laravel-import-export::home/index'); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /src/controllers/ImportController.php: -------------------------------------------------------------------------------- 1 | setContent($this->layout); 13 | } 14 | 15 | public function getResetState() 16 | { 17 | \App::make('import_csv_handler')->resetState(); 18 | 19 | return \Redirect::action('Jacopo\LaravelImportExport\ImportController@getIndex'); 20 | } 21 | 22 | public function postProcessForm() 23 | { 24 | $success =\App::make('import_csv_handler')->processForm(); 25 | 26 | return \Redirect::action('Jacopo\LaravelImportExport\ImportController@getIndex'); 27 | } 28 | } -------------------------------------------------------------------------------- /src/migrations/2013_09_25_222039__laravel_import_export_temporary_table.php: -------------------------------------------------------------------------------- 1 | getTableName(); 16 | Schema::create($table_name, function($table) 17 | { 18 | $table->increments('id'); 19 | }); 20 | DB::statement('ALTER TABLE `'.$table_name.'` ADD `file_object` LONGBLOB NOT NULL'); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | $table_name = $this->getTableName(); 31 | 32 | Schema::drop($table_name); 33 | } 34 | 35 | private function getTableName() 36 | { 37 | return Config::get('laravel-import-export::baseconf.table_prefix'); 38 | } 39 | 40 | private function getConnectionName() 41 | { 42 | return Config::get('laravel-import-export::baseconf.connection_name'); 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/views/home/index.blade.php: -------------------------------------------------------------------------------- 1 |
2 |

Welcome

3 |

Welcome to laravel import-export package. This software is built to import and export data from various format file to an sql database.

4 |

What are you waiting for?

5 |

6 | Start importing » 7 |

8 |
-------------------------------------------------------------------------------- /src/views/layouts/default.blade.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {{(isset($title)) ? $title : Config::get('laravel-import-export::baseconf.default_title')}} 12 | 13 | {{-- loading css --}} 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 41 | 42 |
43 | 44 | {{isset($content) ? $content : ''}} 45 | 46 |
47 | 48 | 49 | {{-- loading javascript --}} 50 | {{ HTML::script(asset('packages/jacopo/laravel-import-export/js/jquery-1.10.2.min.js') ) }} 51 | {{ HTML::script(asset('packages/jacopo/laravel-import-export/js/bootstrap.js') ) }} 52 | 53 | 54 | -------------------------------------------------------------------------------- /tests/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intrip/laravel-import-export/2e6963778a0214c9123d0c51a0d01d8127e1e935/tests/.gitkeep -------------------------------------------------------------------------------- /tests/unit/TestCsvFile.php: -------------------------------------------------------------------------------- 1 | csv_file = new CsvFile(); 12 | } 13 | 14 | //@todo write tests 15 | public function testToMakePass() 16 | {} 17 | } -------------------------------------------------------------------------------- /tests/unit/TestCsvFileBuilder.php: -------------------------------------------------------------------------------- 1 | makePartial(); 25 | $mock->shouldReceive('parseCsvFile') 26 | ->times(4) 27 | ->andReturn($mocked_csv_data[0],$mocked_csv_data[1],$mocked_csv_data[2],$mocked_csv_data[3]); 28 | $this->mockConfig(); 29 | 30 | $builder = new CsvFileBuilder(array(),array(),array("first_line_headers"=>false),null,$mock); 31 | $builder->buildFromCsv(); 32 | 33 | $csv_file = $builder->getCsvFile(); 34 | 35 | $this->assertInstanceOf('Jacopo\LaravelImportExport\Models\ParseCsv\CsvFile', $csv_file); 36 | 37 | // check headers 38 | $this->assertEmpty($csv_file->getCsvHeader()); 39 | 40 | // check data 41 | foreach($csv_file as $key_csv_line => $csv_line) 42 | { 43 | $this->assertInstanceOf('Jacopo\LaravelImportExport\Models\ParseCsv\CsvLine', $csv_line); 44 | $this->assertSame($mocked_csv_data[$key_csv_line], $csv_line->getAttributes()); 45 | } 46 | } 47 | 48 | public function testBuildCreateFileFromCsvSuccessWithHeaders() 49 | { 50 | $mocked_csv_data = array( 51 | array("name","surname"), 52 | array("Jacopo","Beschi"), 53 | false, 54 | ); 55 | $mock = \Mockery::mock('Jacopo\LaravelImportExport\Models\ParseCsv\ParseCsv')->makePartial(); 56 | $mock->shouldReceive('parseCsvFile') 57 | ->times(3) 58 | ->andReturn($mocked_csv_data[0],$mocked_csv_data[1],$mocked_csv_data[2]); 59 | 60 | $builder = new CsvFileBuilder(array(),array(),array("first_line_headers"=>true),null,$mock); 61 | $builder->buildFromCsv(); 62 | 63 | $csv_file = $builder->getCsvFile(); 64 | 65 | $this->assertInstanceOf('Jacopo\LaravelImportExport\Models\ParseCsv\CsvFile', $csv_file); 66 | 67 | // check headers 68 | $csv_file->rewind(); 69 | $this->assertSame($mocked_csv_data[0],$csv_file->getCsvHeader()); 70 | 71 | // check values 72 | $second = $csv_file->current(); 73 | $this->assertInstanceOf('Jacopo\LaravelImportExport\Models\ParseCsv\CsvLine', $second); 74 | $this->assertSame($mocked_csv_data[1], $second->getAttributes()); 75 | } 76 | 77 | protected function mockConfig() 78 | { 79 | $app = m::mock('AppMock'); 80 | $app->shouldReceive('instance')->once()->andReturn($app); 81 | 82 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 83 | Illuminate\Support\Facades\Config::swap($config = m::mock('ConfigMock')); 84 | 85 | $config->shouldReceive('get') 86 | ->andReturn(true); 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /tests/unit/TestCsvFileHandler.php: -------------------------------------------------------------------------------- 1 | csv_file_handler = m::mock('Jacopo\LaravelImportExport\Models\ParseCsv\CsvFileHandler')->makePartial(); 16 | } 17 | 18 | public function tearDown() 19 | { 20 | m::close(); 21 | } 22 | 23 | public function testOpenFromCsvSuccess() 24 | { 25 | $mock = m::mock('Jacopo\LaravelImportExport\Models\ParseCsv\CsvFileBuilder')->makePartial(); 26 | $mock->shouldReceive('buildFromCsv','getCsvFile') 27 | ->andReturn(true,true); 28 | 29 | $config = array( 30 | "model" => 1, 31 | "file_parse" => 2, 32 | "builder" => 3, 33 | ); 34 | 35 | $result = $this->csv_file_handler->openFromCsv($config,$mock); 36 | 37 | $this->assertSame(true,$result); 38 | } 39 | 40 | public function testSaveTemporarySuccess() 41 | { 42 | $this->mockConfig(); 43 | $this->mockDbConnection(); 44 | $temporary_stub = new TemporaryModelStub(); 45 | $csv_file = new CsvFile(); 46 | 47 | $success = $this->csv_file_handler->saveTemporary($csv_file,$temporary_stub); 48 | 49 | $this->assertTrue($success); 50 | $this->assertTrue($_SERVER['__temporary.saved']); 51 | } 52 | 53 | public function testGetMaxLength() 54 | { 55 | $csv_line1 = new CsvLine(); 56 | $csv_line1->first = 1; 57 | $csv_line1->second = 2; 58 | $csv_line2 = new CsvLine(); 59 | 60 | $csv_file = new CsvFile(array($csv_line1, $csv_line2)); 61 | 62 | $expected_length = 2; 63 | $length = $this->csv_file_handler->getMaxLength($csv_file); 64 | 65 | $this->assertEquals($expected_length, $length); 66 | } 67 | 68 | /** 69 | * @expectedException Jacopo\LaravelImportExport\Models\Exceptions\NoDataException 70 | */ 71 | public function testGetMaxLengthThrowsNoDataException() 72 | { 73 | $this->csv_file_handler->getMaxLength(); 74 | } 75 | 76 | /** 77 | * @expectedException Jacopo\LaravelImportExport\Models\Exceptions\UnalignedArrayException 78 | */ 79 | public function testUpdateHeadersThrowsUnalignedArrayException() 80 | { 81 | $line1 = new CsvLine(); 82 | $line1->setAttribute("0", "first"); 83 | $line1->setAttribute("1", "second"); 84 | $line2 = new CsvLine(); 85 | $line2->setAttribute("0", "first"); 86 | $csv_file = new CsvFile( array($line1, $line2) ); 87 | 88 | $columns = array( 89 | "first" => 0, 90 | "second" => 1 91 | ); 92 | 93 | $table_name = "table"; 94 | 95 | $this->csv_file_handler->updateHeaders($csv_file, $columns, $table_name); 96 | } 97 | 98 | public function testUpdateHeadersSuccess() 99 | { 100 | $line1 = new CsvLine(); 101 | $line1->setAttribute("0", "first"); 102 | $line1->setAttribute("1", "second"); 103 | $line2 = new CsvLine(); 104 | $line2->setAttribute("0", "first"); 105 | $line2->setAttribute("1", "second"); 106 | $csv_file = new CsvFile( array($line1, $line2) ); 107 | 108 | $columns = array( 109 | 0 => "first", 110 | 1 => "second", 111 | ); 112 | 113 | $table_name = "table"; 114 | 115 | $this->csv_file_handler->updateHeaders($csv_file, $columns, $table_name); 116 | $csv_file_updated = $this->csv_file_handler->getCsvFile(); 117 | 118 | $line_1_expected = new CsvLine(); 119 | $line_1_expected->setAttribute("first", "first"); 120 | $line_1_expected->setAttribute("second", "second"); 121 | $line_1_expected->setConfig( array("table" => "table") ); 122 | $line_2_expected = new CsvLine(); 123 | $line_2_expected->setAttribute("first", "first"); 124 | $line_2_expected->setAttribute("second", "second"); 125 | $line_2_expected->setConfig( array("table" => "table") ); 126 | $csv_file_expected = new CsvFile( array($line_1_expected, $line_2_expected) ); 127 | 128 | $this->assertEquals($csv_file_expected, $csv_file_updated); 129 | } 130 | 131 | public function testGetCsvStringSuccess() 132 | { 133 | $mock_line = m::mock('CsvLine')->makePartial(); 134 | $mock_line->shouldReceive(array( 135 | 'getCsvHeader' => "header\n", 136 | 'getCsvString' => "string\n" 137 | )); 138 | 139 | $csv_file = new CsvFile(); 140 | $csv_file->append($mock_line); 141 | 142 | $expected_str="header\nstring\n"; 143 | $csv_str = $this->csv_file_handler->getCsvString(',', $csv_file); 144 | 145 | $this->assertEquals($expected_str, $csv_str); 146 | } 147 | 148 | /** 149 | * @expectedException Jacopo\LaravelImportExport\Models\Exceptions\NoDataException 150 | */ 151 | public function testGetCsvStringThrowsNoDataException() 152 | { 153 | $this->csv_file_handler->getCsvString(","); 154 | } 155 | 156 | protected function mockConfig() 157 | { 158 | $app = m::mock('AppMock'); 159 | $app->shouldReceive('instance')->andReturn($app); 160 | 161 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 162 | Illuminate\Support\Facades\Config::swap($config = m::mock('ConfigMock')); 163 | 164 | $config->shouldReceive('get') 165 | ->andReturn('import'); 166 | } 167 | 168 | protected function mockDbConnection() 169 | { 170 | $app = m::mock('AppMock'); 171 | $app->shouldReceive('instance')->andReturn($app); 172 | 173 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 174 | Illuminate\Support\Facades\DB::swap($db = m::mock('DBMock')); 175 | 176 | $mock_connection = m::mock("StdClass"); 177 | $mock_connection->shouldReceive('disableQueryLog'); 178 | 179 | $db->shouldReceive('connection') 180 | ->andReturn($mock_connection); 181 | } 182 | 183 | } 184 | 185 | class TemporaryModelStub extends Illuminate\Database\Eloquent\Model { 186 | protected static $unguarded = true; 187 | 188 | public function save(array $options = array()) 189 | { 190 | $_SERVER['__temporary.saved'] = true; 191 | 192 | return true; 193 | } 194 | } -------------------------------------------------------------------------------- /tests/unit/TestCsvLine.php: -------------------------------------------------------------------------------- 1 | csv_line = new CsvLine(); 10 | } 11 | 12 | public function testgetElementsSuccess() 13 | { 14 | $this->csv_line->name = "name"; 15 | $attrs = $this->csv_line->getElements(); 16 | $expected = array("name"=>"name"); 17 | 18 | $this->assertEquals($expected,$attrs); 19 | } 20 | 21 | public function testgetCsvHeader() 22 | { 23 | $headers = array( 24 | "first" => 1, 25 | "second" => 2 26 | ); 27 | $this->csv_line->forceSetAttributes($headers); 28 | 29 | $expected_header = "first,second\n"; 30 | $csv_header = $this->csv_line->getCsvHeader(","); 31 | 32 | $this->assertEquals($expected_header,$csv_header); 33 | } 34 | 35 | public function testgetCsvString() 36 | { 37 | $headers = array( 38 | "first" => 1, 39 | "second" => 2 40 | ); 41 | $this->csv_line->forceSetAttributes($headers); 42 | 43 | $expected_string = "1,2\n"; 44 | $csv_string = $this->csv_line->getCsvString(","); 45 | 46 | $this->assertEquals($expected_string, $csv_string); 47 | } 48 | } -------------------------------------------------------------------------------- /tests/unit/TestDbFileBuilder.php: -------------------------------------------------------------------------------- 1 | builder = m::mock("Jacopo\LaravelImportExport\Models\ParseCsv\DbFileBuilder")->makePartial(); 19 | } 20 | 21 | public function testCreateSelect() 22 | { 23 | $config = array( 24 | "columns" => array( 25 | "db1" => "csv1", 26 | "db2" => "csv2" 27 | ) 28 | ); 29 | $select = $this->builder->createSelect($config); 30 | $expected_select = array( 31 | "db1 as csv1", 32 | "db2 as csv2", 33 | ); 34 | $this->assertEquals($select,$expected_select); 35 | } 36 | 37 | public function testBuildSuccess() 38 | { 39 | $builder = new DbBuilderStub(); 40 | $this->mockConfig(); 41 | 42 | $expected_line = new CsvLine(); 43 | $expected_line->forceSetAttributes(array("csv1"=>"data")); 44 | 45 | $builder->build(); 46 | $csv_file = $builder->getCsvFile(); 47 | 48 | $this->assertInstanceOf('Jacopo\LaravelImportExport\Models\ParseCsv\CsvFile', $csv_file); 49 | foreach($csv_file as $csv_line) 50 | { 51 | $this->assertEquals($expected_line->getAttributes(), $csv_line->getAttributes()); 52 | } 53 | } 54 | 55 | protected function mockConfig() 56 | { 57 | $app = m::mock('AppMock'); 58 | $app->shouldReceive('instance')->andReturn($app); 59 | 60 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 61 | Illuminate\Support\Facades\Config::swap($config = m::mock('ConfigMock')); 62 | 63 | $config->shouldReceive('get') 64 | ->andReturn('import'); 65 | } 66 | } 67 | 68 | class DbBuilderStub extends DbFileBuilder 69 | { 70 | protected function getAttributesFromDb() 71 | { 72 | return array( array("csv1" => "data") ); 73 | } 74 | } -------------------------------------------------------------------------------- /tests/unit/TestFile.php: -------------------------------------------------------------------------------- 1 | file_wrapper = new File(); 12 | } 13 | 14 | /** 15 | *@expectedException Jacopo\LaravelImportExport\Models\Exceptions\FileNotFoundException 16 | */ 17 | public function testOpenFileThrowsFileNotFoundException() 18 | { 19 | $path = "notfound.csv"; 20 | 21 | $this->file_wrapper->openFile($path); 22 | } 23 | } -------------------------------------------------------------------------------- /tests/unit/TestGeneralState.php: -------------------------------------------------------------------------------- 1 | mockSessionMessageBag(); 17 | $error_all_mock = m::mock('StdClass'); 18 | $error_all_mock->shouldReceive('all') 19 | ->once() 20 | ->andReturn(array('Error1')); 21 | 22 | $mock = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\GeneralState')->makePartial(); 23 | $mock->shouldReceive('getErrors') 24 | ->once() 25 | ->andReturn($error_all_mock); 26 | 27 | $header = $mock->getErrorHeader(); 28 | $this->assertSame("
Error1
". 29 | "
Class not found
", $header); 30 | } 31 | 32 | public function testgetErrorHeaderNotExists() 33 | { 34 | $this->mockSessionEmpty(); 35 | $mock = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\GeneralState')->makePartial(); 36 | $mock->shouldReceive('getErrors') 37 | ->once() 38 | ->andReturn(null); 39 | 40 | $header = $mock->getErrorHeader(); 41 | $this->assertSame("", $header); 42 | } 43 | 44 | public function testGetNextStateExist() 45 | { 46 | $mock = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\Import\GetCsvState')->makePartial(); 47 | $mock->shouldReceive('getIsExecuted') 48 | ->andReturn(true); 49 | 50 | $next_state = $mock->getNextState(); 51 | $this->assertInstanceOf('Jacopo\LaravelImportExport\Models\StateHandling\Import\GetTableState', $next_state); 52 | } 53 | 54 | public function testGetNextStateNotExists() 55 | { 56 | $mock = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\Import\GetCsvState')->makePartial(); 57 | $mock->shouldReceive('getIsExecuted') 58 | ->andReturn(false); 59 | 60 | $next_state = $mock->getNextState(); 61 | $this->assertInstanceOf('Jacopo\LaravelImportExport\Models\StateHandling\Import\GetCsvState', $next_state); 62 | } 63 | 64 | /** 65 | *@expectedException Jacopo\LaravelImportExport\Models\Exceptions\ClassNotFoundException 66 | */ 67 | public function testGetNextStateThrowsClassNotFoundException() 68 | { 69 | $mock = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\Import\GetCsvState')->makePartial(); 70 | $mock->shouldReceive(array( 71 | 'getIsExecuted' => true, 72 | 'getNextStateClass' => 'invalid__class___name____' 73 | )); 74 | 75 | $next_state = $mock->getNextState(); 76 | } 77 | 78 | public function testAppendErrorAppend() 79 | { 80 | $csv_state = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\GeneralState')->makePartial(); 81 | 82 | $error_key = "Error1"; 83 | $error_string = "1"; 84 | 85 | $csv_state->appendError($error_key, $error_string); 86 | 87 | $this->assertInstanceOf( 'Illuminate\Support\MessageBag' , $csv_state->getErrors() ); 88 | $this->assertSame( array("1"), $csv_state->getErrors()->all() ); 89 | } 90 | 91 | public function testAppendErrorCreateNew() 92 | { 93 | $csv_state = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\GeneralState')->makePartial(); 94 | 95 | $error = array("Error1" => "1"); 96 | $csv_state->setErrors(new MessageBag($error)); 97 | $csv_state->appendError("Error2", "1"); 98 | 99 | $this->assertInstanceOf( 'Illuminate\Support\MessageBag' , $csv_state->getErrors() ); 100 | $this->assertSame( array("1","1"), $csv_state->getErrors()->all() ); 101 | } 102 | 103 | protected function mockSessionMessageBag() 104 | { 105 | $app = m::mock('AppMock'); 106 | $app->shouldReceive('instance')->once()->andReturn($app); 107 | 108 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 109 | Illuminate\Support\Facades\Session::swap($session = m::mock('SessionMock')); 110 | 111 | $session->shouldReceive('get','forget') 112 | ->andReturn(new MessageBag( array("Class" => "Class not found") ), true ); 113 | } 114 | 115 | protected function mockSessionEmpty() 116 | { 117 | $app = m::mock('AppMock'); 118 | $app->shouldReceive('instance')->once()->andReturn($app); 119 | 120 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 121 | Illuminate\Support\Facades\Session::swap($session = m::mock('SessionMock')); 122 | 123 | $session->shouldReceive('get','forget') 124 | ->andReturn(false,true); 125 | } 126 | } -------------------------------------------------------------------------------- /tests/unit/TestGetCsvState.php: -------------------------------------------------------------------------------- 1 | state = new GetCsvState; 14 | } 15 | 16 | public function tearDown() 17 | { 18 | m::close(); 19 | } 20 | 21 | public function testProcessFormSuccess() 22 | { 23 | $mock_validator = m::mock('Jacopo\LaravelImportExport\Models\ValidatorFormInputModel'); 24 | $mock_validator->shouldReceive('validateInput') 25 | ->once() 26 | ->andReturn(true); 27 | $this->mockSessionPut(); 28 | 29 | $mock_file = m::mock('StdClass'); 30 | $mock_file->shouldReceive(array( 31 | 'getRealPath' => 'path/path', 32 | 'getClientOriginalName' => 'test.csv', 33 | )); 34 | 35 | $form_input = array( 36 | 'separator' => ';', 37 | 'file_csv' => $mock_file, 38 | 'headers' => false, 39 | 'max_lines' => 1, 40 | 'create_table' => true, 41 | ); 42 | 43 | $mock_csv_handler = m::mock('Jacopo\LaravelImportExport\Models\ParseCsv\CsvFileHandler'); 44 | $mock_csv_handler->shouldReceive(array( 45 | 'openFromCsv' => true, 46 | 'saveTemporary' => true, 47 | )); 48 | 49 | $executed = $this->state->processForm($form_input,$mock_validator,$mock_csv_handler); 50 | $this->assertSame(true,$executed); 51 | } 52 | 53 | public function testProcessFormFailsValidation() 54 | { 55 | $mock_file = m::mock('StdClass'); 56 | $mock_file->shouldReceive(array( 57 | 'getRealPath' => 'path/path', 58 | 'getClientOriginalName' => 'test.csv', 59 | )); 60 | 61 | $form_input = array( 62 | 'separator' => ';', 63 | 'file_csv' => $mock_file, 64 | 'headers' => false, 65 | ); 66 | 67 | $mock_temporary_model = m::mock('Jacopo\LaravelImportExport\Models\TemporaryModel'); 68 | 69 | $mock_validator = m::mock('Jacopo\LaravelImportExport\Models\ValidatorFormInputModel'); 70 | $mock_validator->shouldReceive('validateInput') 71 | ->once() 72 | ->andReturn(false); 73 | 74 | $executed = $this->state->processForm($form_input,$mock_validator,null); 75 | $this->assertSame(false,$executed); 76 | 77 | } 78 | 79 | protected function mockSessionPut() 80 | { 81 | $app = m::mock('AppMock'); 82 | $app->shouldReceive('instance')->once()->andReturn($app); 83 | 84 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 85 | Illuminate\Support\Facades\Session::swap($input = m::mock('SessionMock')); 86 | 87 | $input->shouldReceive('put')->once()->andReturn(true); 88 | } 89 | } -------------------------------------------------------------------------------- /tests/unit/TestGetTableConfig.php: -------------------------------------------------------------------------------- 1 | state = new GetTableConfig; 17 | } 18 | 19 | public function tearDown() 20 | { 21 | m::close(); 22 | } 23 | 24 | public function testProcessFormSuccess() 25 | { 26 | $form_input = array( 27 | "attributes" => '', 28 | 'table_name' => '' 29 | ); 30 | $mock_handler = m::mock('Jacopo\LaravelImportExport\Models\ParseCsv\CsvFileHandler') 31 | ->shouldReceive(array( 32 | 'openFromDb' => true, 33 | "saveCsvFile" => true, 34 | )) 35 | ->getMock(); 36 | $mock_validator = m::mock('StdClass') 37 | ->shouldReceive('validateInput') 38 | ->andReturn(true) 39 | ->getMock(); 40 | 41 | $this->mockSessionGetPut(); 42 | $success = $this->state->processForm($form_input, $mock_validator, $mock_handler); 43 | 44 | $this->assertTrue($success); 45 | } 46 | 47 | public function testProcessFormFailsValidation() 48 | { 49 | $form_input = array( 50 | "attributes" => '', 51 | 'table_name' => '' 52 | ); 53 | $mock_validator = m::mock('StdClass') 54 | ->shouldReceive('validateInput') 55 | ->andReturn(true) 56 | ->getMock(); 57 | 58 | $success = $this->state->processForm($form_input, $mock_validator); 59 | 60 | $this->assertFalse($success); 61 | } 62 | 63 | protected function mockSessionGetPut() 64 | { 65 | $app = m::mock('AppMock'); 66 | $app->shouldReceive('instance')->once()->andReturn($app); 67 | 68 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 69 | Illuminate\Support\Facades\Session::swap($session = m::mock('ConfigMock')); 70 | 71 | $session->shouldReceive('get','put'); 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /tests/unit/TestGetTableName.php: -------------------------------------------------------------------------------- 1 | state = new GetTableName(); 15 | } 16 | 17 | public function tearDown() 18 | { 19 | m::close(); 20 | } 21 | 22 | public function testFillFormInput() 23 | { 24 | $input_mock = m::mock('Jacopo\LaravelImportExport\Models\InputWrapper'); 25 | $input_mock->shouldReceive( 26 | 'get', 27 | 'get', 28 | 'get' 29 | )->andReturn( 30 | 'table_name', 31 | '50', 32 | ',' 33 | ); 34 | $this->state->fillFormInput($input_mock); 35 | $form_input = $this->state->getFormInput(); 36 | 37 | $this->assertEquals('table_name', $form_input["table_name"]); 38 | $this->assertEquals('50', $form_input["max_rows"]); 39 | $this->assertEquals(',', $form_input["separator"]); 40 | } 41 | 42 | public function testGetTableValuesSelect() 43 | { 44 | $expected_tables = array( 45 | "first" => "first", 46 | "second" => "second", 47 | ); 48 | $mock_dbm = m::mock('Jacopo\LaravelImportExport\Models\DatabaseSchemaManager'); 49 | $mock_dbm->shouldReceive('getTableList') 50 | ->once() 51 | ->andReturn(array("first","second")); 52 | $mock_state = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\Export\GetTableName')->makePartial(); 53 | 54 | $table_list = $mock_state->getTableValuesSelect($mock_dbm); 55 | $this->assertEquals($expected_tables, $table_list); 56 | } 57 | 58 | public function testGetTableHeader() 59 | { 60 | $mock_cols = m::mock("StdClass") 61 | ->shouldReceive('toArray') 62 | ->andReturn(array("name"=>"name")) 63 | ->getMock(); 64 | $array_mock_cols = array($mock_cols); 65 | 66 | $mock_dbm = m::mock('Jacopo\LaravelImportExport\Models\DatabaseSchemaManager'); 67 | $mock_dbm->shouldReceive('getTableColumns') 68 | ->once() 69 | ->andReturn($array_mock_cols); 70 | 71 | $mock_state = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\Export\GetTableName')->makePartial(); 72 | $mock_state->shouldReceive('getFormInput') 73 | ->once() 74 | ->andReturn(array("table_name"=>1)); 75 | $expected_columns = array("name"); 76 | 77 | $columns = $mock_state->getTableHeader($mock_dbm); 78 | $this->assertEquals($expected_columns,$columns); 79 | } 80 | 81 | public function testProcessFormSuccess() 82 | { 83 | $mock_validator = m::mock('Jacopo\LaravelImportExport\Models\ValidatorFormInputModel'); 84 | $mock_validator->shouldReceive('validateInput') 85 | ->once() 86 | ->andReturn(true); 87 | $this->mockSessionPut(); 88 | 89 | $form_input = array( 90 | 'table_name' => 'table', 91 | 'max_rows' => '50', 92 | 'separator' => ',' 93 | ); 94 | 95 | $state_stub = new GetTableNameStub; 96 | 97 | $executed = $state_stub->processForm($form_input,$mock_validator); 98 | $this->assertSame(true,$executed); 99 | } 100 | 101 | public function testProcessFormFails() 102 | { 103 | $mock_validator = m::mock('Jacopo\LaravelImportExport\Models\ValidatorFormInputModel'); 104 | $mock_validator->shouldReceive('validateInput') 105 | ->once() 106 | ->andReturn(false); 107 | 108 | $form_input = array( 109 | 'table_name' => 'table', 110 | 'max_rows' => '50', 111 | 112 | ); 113 | 114 | 115 | $executed = $this->state->processForm($form_input,$mock_validator); 116 | $this->assertSame(false,$executed); 117 | } 118 | 119 | protected function mockSessionPut() 120 | { 121 | $app = m::mock('AppMock'); 122 | $app->shouldReceive('instance')->once()->andReturn($app); 123 | 124 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 125 | Illuminate\Support\Facades\Session::swap($input = m::mock('SessionMock')); 126 | 127 | $input->shouldReceive('put')->once()->andReturn(true); 128 | } 129 | 130 | } 131 | 132 | class GetTableNameStub extends GetTableName 133 | { 134 | protected function getDataTable() 135 | { 136 | return true; 137 | } 138 | 139 | protected function getTableHeader($dbm = null) 140 | { 141 | return array("column1"); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /tests/unit/TestGetTableState.php: -------------------------------------------------------------------------------- 1 | state = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\Import\GetTableState')->makePartial(); 15 | } 16 | 17 | public function tearDown() 18 | { 19 | m::close(); 20 | } 21 | 22 | public function testFillFormInput() 23 | { 24 | $input_mock = m::mock('Jacopo\LaravelImportExport\Models\InputWrapper'); 25 | $input_mock->shouldReceive(//array("get"=>2,"get"=>2,"get"=>2,"get"=>2)); 26 | 'get', 27 | 'get', 28 | 'get', 29 | 'get', 30 | 'get', 31 | 'get', 32 | 'get' 33 | )->andReturn( 34 | 'table_name', 35 | '2', 36 | '1', 37 | 'first', 38 | 'string', 39 | 'second', 40 | 'string' 41 | ); 42 | $this->state->fillFormInput($input_mock); 43 | $form_input = $this->state->getFormInput(); 44 | 45 | $this->assertEquals('table_name', $form_input["table_name"]); 46 | $expected_vals = array( 47 | 0 => 'first', 48 | 1 => 'second' 49 | ); 50 | $this->assertEquals($expected_vals, $form_input["columns"]); 51 | $expected_types = array( 52 | 'first' => 'string', 53 | 'second' => 'string', 54 | ); 55 | $this->assertEquals($expected_types, $form_input["types"]); 56 | } 57 | 58 | public function testProcessFormSuccess() 59 | { 60 | $mock_validator = m::mock('Jacopo\LaravelImportExport\Models\ValidatorFormInputModel'); 61 | $mock_validator->shouldReceive('validateInput') 62 | ->once() 63 | ->andReturn(true); 64 | 65 | $form_input = array( 66 | 'table_name' => 'table', 67 | 'columns' => array( 68 | "first" => 0, 69 | "second" => 1 70 | ), 71 | 'types' => array(), 72 | ); 73 | 74 | $mock_csv_handler = m::mock('Jacopo\LaravelImportExport\Models\ParseCsv\CsvFileHandler'); 75 | $mock_csv_handler->shouldReceive(array( 76 | 'getTemporary' => new CsvFile(), 77 | 'updateHeaders' => true, 78 | 'saveToDb' => true 79 | )); 80 | 81 | $executed = $this->state->processForm($form_input,$mock_validator,$mock_csv_handler); 82 | $this->assertSame(true,$executed); 83 | } 84 | 85 | } -------------------------------------------------------------------------------- /tests/unit/TestParseCsv.php: -------------------------------------------------------------------------------- 1 | parse_csv = new ParseCsv(); 11 | } 12 | 13 | public function tearDown() 14 | { 15 | \Mockery::close(); 16 | } 17 | 18 | public function testParseCsvFileSuccess() 19 | { 20 | $csv_line_file = array("test"=>"test"); 21 | $mock = \Mockery::mock('Jacopo\LaravelImportExport\Models\ParseCsv\File'); 22 | $mock->shouldReceive(array( 23 | 'openFile'=>true, 24 | 'readCsv'=>$csv_line_file)); 25 | 26 | $parse_csv = new ParseCsv(array(),$mock); 27 | 28 | $csv_line_array = $parse_csv->parseCsvFile(); 29 | $this->assertEquals($csv_line_file, $csv_line_array); 30 | 31 | $mock = \Mockery::mock('Jacopo\LaravelImportExport\Models\ParseCsv\File'); 32 | $mock->shouldReceive(array( 33 | 'openFile'=>true, 34 | 'readCsv'=>false, 35 | 'closeFile'=>true)); 36 | 37 | $parse_csv = new ParseCsv(array(),$mock); 38 | 39 | $csv_line_array = $parse_csv->parseCsvFile(); 40 | $this->assertEquals(false, $csv_line_array); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /tests/unit/TestRuntimeModel.php: -------------------------------------------------------------------------------- 1 | model = new RuntimeModel(); 12 | } 13 | 14 | public function testValidConfig() 15 | { 16 | $config = array("timestamps" => true); 17 | 18 | $this->model->setConfig($config); 19 | 20 | $this->assertObjectHasAttribute("timestamps", $this->model); 21 | 22 | } 23 | 24 | public function testForceSetAttributesSuccess() 25 | { 26 | $atts = array( 27 | "first" => 1, 28 | "second" => 2, 29 | ); 30 | $this->model->forceSetAttributes($atts); 31 | 32 | $this->assertEquals($atts["first"],$this->model->first); 33 | $this->assertEquals($atts["second"],$this->model->second); 34 | } 35 | 36 | /** 37 | * @expectedException InvalidArgumentException 38 | */ 39 | public function testExceptionInvalidConfig() 40 | { 41 | 42 | $config = array("invalid" => "invalid"); 43 | 44 | $this->model->setConfig($config); 45 | } 46 | 47 | public function testCanSaveToDbSuccess() 48 | { 49 | $config = array("table"=>"table"); 50 | 51 | $this->model->setConfig($config); 52 | // set a string attribute 53 | $this->model->key = 0; 54 | $can_save = $this->model->canSaveToDb(); 55 | 56 | $this->assertTrue($can_save); 57 | } 58 | 59 | public function testCanSaveToDbFailsTable() 60 | { 61 | $config = array(); 62 | 63 | $this->model->setConfig($config); 64 | // set a string attribute 65 | $this->model->key = 0; 66 | $can_save = $this->model->canSaveToDb(); 67 | 68 | $this->assertFalse($can_save); 69 | } 70 | 71 | public function testCanSaveToDbFailsAttributes() 72 | { 73 | $config = array("table"=>"table"); 74 | 75 | $this->model->setConfig($config); 76 | $can_save = $this->model->canSaveToDb(); 77 | 78 | $this->assertFalse($can_save); 79 | } 80 | } -------------------------------------------------------------------------------- /tests/unit/TestStateHandler.php: -------------------------------------------------------------------------------- 1 | handler = new StateHandler(); 22 | $this->mockSessionExist(); 23 | 24 | $this->handler->initializeState(); 25 | $current_state = Session::get($this->session_key); 26 | $this->assertInstanceOf('Jacopo\LaravelImportExport\Models\StateHandling\StateArray', $current_state); 27 | } 28 | 29 | public function testInizializeStateSuccessReset() 30 | { 31 | $mock = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\StateHandler')->makePartial(); 32 | $mock->shouldReceive('resetState') 33 | ->once() 34 | ->andReturn(true); 35 | 36 | $this->mockSessionReset(); 37 | $mock->initializeState(); 38 | } 39 | 40 | public function testResetStateSuccess() 41 | { 42 | $handler_stub = new StateHandlerStubReset; 43 | 44 | $this->mockSessionReset(); 45 | $this->mockConfigTableDb(); 46 | 47 | $handler_stub->resetState(); 48 | 49 | $returned_array_state = $handler_stub->getStateArray(); 50 | $this->assertInstanceOf('Jacopo\LaravelImportExport\Models\StateHandling\StateArray', $returned_array_state); 51 | $current_state = $handler_stub->getCurrent(); 52 | $this->assertInstanceOf('StdClass', $current_state); 53 | 54 | } 55 | 56 | public function testReplaceCurrentSuccess() 57 | { 58 | $mock_state_array = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\StateArray'); 59 | $mock_state_array->shouldReceive('offsetSet') 60 | ->once() 61 | ->andReturn(true); 62 | 63 | $mock_handler = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\StateHandler')->makePartial(); 64 | $mock_handler->shouldReceive(array( 65 | "getLastKey" => 0, 66 | "getStateArray" => $mock_state_array, 67 | )); 68 | 69 | $mock_handler->replaceCurrent( array() ); 70 | } 71 | 72 | /** 73 | *@expectedException Jacopo\LaravelImportExport\Models\Exceptions\NoDataException 74 | */ 75 | public function testReplaceCurrentThrowsNoDataException() 76 | { 77 | $mock_handler = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\StateHandler')->makePartial(); 78 | $mock_handler->shouldReceive('getLastKey') 79 | ->once() 80 | ->andReturn(-1); 81 | $mock_handler->replaceCurrent( array() ); 82 | } 83 | 84 | public function testProcessFormSuccess() 85 | { 86 | $handler = new StateHandler(); 87 | $mock_get_csv_s = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\GeneralState')->makePartial(); 88 | $mock_get_csv_s->shouldReceive('processForm') 89 | ->once() 90 | ->andReturn(true); 91 | $this->mockSessionPut(); 92 | 93 | $handler->setStateArray( new StateArray( array( $mock_get_csv_s ) ) ); 94 | 95 | $handler->processForm(); 96 | } 97 | 98 | public function textGetLastStateThrowsNoDataException() 99 | { 100 | $mock_handler = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\Import\StateHandler')->makePartial(); 101 | $mock_handler->shouldReceive('getLastKey') 102 | ->once() 103 | ->andReturn(-1); 104 | 105 | $mock_handler->getLastState(); 106 | } 107 | 108 | public function textGetLastStateSuccess() 109 | { 110 | $state_array = array("test array"); 111 | 112 | $mock_handler = m::mock('Jacopo\LaravelImportExport\Models\StateHandling\Import\StateHandler')->makePartial(); 113 | $mock_handler->shouldReceive(array( 114 | "getLastKey" => 0, 115 | "getStateArray" => $state_array, 116 | )); 117 | 118 | $res = $mock_handler->getLastState(); 119 | $this->assertEquals($state_array, $mock_handler->getStateArray()); 120 | } 121 | 122 | protected function mockSessionExist() 123 | { 124 | Illuminate\Support\Facades\Session::swap($session = m::mock('SessionMock')); 125 | $session->shouldReceive(array( 126 | 'has'=>true, 127 | 'get' => new StateArray() 128 | )); 129 | } 130 | 131 | protected function mockSessionReset() 132 | { 133 | Illuminate\Support\Facades\Session::swap($session = m::mock('SessionMock')); 134 | $session->shouldReceive(array( 135 | 'has'=>false, 136 | 'put'=>true, 137 | )); 138 | } 139 | 140 | protected function mockSessionPut() 141 | { 142 | Illuminate\Support\Facades\Session::swap($session = m::mock('SessionMock')); 143 | $session->shouldReceive(array( 144 | 'put'=> true 145 | )); 146 | } 147 | 148 | protected function mockDbTruncate() 149 | { 150 | $mock_truncate = m::mock("StdClass") 151 | ->shouldReceive("truncate") 152 | ->once() 153 | ->andReturn(true) 154 | ->getMock(); 155 | 156 | $mock_table = m::mock('StdClass') 157 | ->shouldReceive('table') 158 | ->andReturn($mock_truncate) 159 | ->getMock(); 160 | 161 | $app = m::mock('AppMock'); 162 | $app->shouldReceive('instance')->andReturn($app); 163 | 164 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 165 | Illuminate\Support\Facades\DB::swap($db = m::mock('DBMock')); 166 | $db->shouldReceive(array( 167 | 'connection'=> $mock_table 168 | )); 169 | } 170 | 171 | protected function mockConfigTable() 172 | { 173 | $app = m::mock('AppMock'); 174 | $app->shouldReceive('instance')->andReturn($app); 175 | 176 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 177 | Illuminate\Support\Facades\Config::swap($config = m::mock('ConfigMock')); 178 | 179 | $config->shouldReceive('get')->once()->with('laravel-import-export::baseconf.table_prefix')->andReturn(true); 180 | } 181 | 182 | protected function mockConfigTableDb() 183 | { 184 | $app = m::mock('AppMock'); 185 | $app->shouldReceive('instance')->andReturn($app); 186 | 187 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 188 | Illuminate\Support\Facades\Config::swap($config = m::mock('ConfigMock')); 189 | 190 | $config->shouldReceive('get','get') 191 | ->andReturn(true,'import'); 192 | } 193 | 194 | protected function mockConfig() 195 | { 196 | $app = m::mock('AppMock'); 197 | $app->shouldReceive('instance')->andReturn($app); 198 | 199 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 200 | Illuminate\Support\Facades\Config::swap($config = m::mock('ConfigMock')); 201 | 202 | $config->shouldReceive('get')->once()->with('laravel-import-export::baseconf.session_import_key','import_state')->andReturn($this->session_key); 203 | } 204 | 205 | } 206 | 207 | class StateHandlerStubReset extends StateHandler 208 | { 209 | protected $initial_state = 'StdClass'; 210 | } -------------------------------------------------------------------------------- /tests/unit/TestTemporaryModel.php: -------------------------------------------------------------------------------- 1 | mockConfig(); 11 | } 12 | 13 | public function tearDown() 14 | { 15 | m::close(); 16 | } 17 | 18 | public function testCanIstantiateModel() 19 | { 20 | $model = new TemporaryModel(); 21 | } 22 | 23 | protected function mockConfig() 24 | { 25 | $app = m::mock('AppMock'); 26 | $app->shouldReceive('instance')->once()->andReturn($app); 27 | 28 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 29 | Illuminate\Support\Facades\Config::swap($config = m::mock('ConfigMock')); 30 | 31 | $config->shouldReceive('get','get') 32 | ->andReturn('_import_export_temporary_table','import'); 33 | } 34 | } -------------------------------------------------------------------------------- /tests/unit/TestValidatorFormInputModel.php: -------------------------------------------------------------------------------- 1 | shouldReceive(array( 17 | 'getFormInput' => $uploaded_file_mock, 18 | 'getRules' => $rules, 19 | 'setErrors' => true, 20 | )); 21 | $this->import_state_mock = $import_state_mock; 22 | } 23 | 24 | public function tearDown() 25 | { 26 | m::close(); 27 | } 28 | 29 | public function testValidateInputSuccess() 30 | { 31 | $this->mockValidatorSuccess(); 32 | $validator = new ValidatorFormInputModel($this->import_state_mock); 33 | $success = $validator->validateInput(); 34 | 35 | $this->assertTrue($success); 36 | } 37 | 38 | public function testValidateInputFail() 39 | { 40 | $this->mockValidatorFail(); 41 | $validator = new ValidatorFormInputModel($this->import_state_mock); 42 | $success = $validator->validateInput(); 43 | 44 | $this->assertFalse($success); 45 | } 46 | 47 | protected function mockValidatorSuccess() 48 | { 49 | $app = m::mock('AppMock'); 50 | $app->shouldReceive('instance')->once()->andReturn($app); 51 | 52 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 53 | Illuminate\Support\Facades\Validator::swap($validator = m::mock('validatorMock')); 54 | 55 | $mock_success = m::mock('StdClass'); 56 | $mock_success->shouldReceive(array( 57 | 'fails' => false, 58 | )); 59 | 60 | $validator->shouldReceive('make') 61 | ->with( m::type('Symfony\Component\HttpFoundation\File\UploadedFile') , m::type('array') ) 62 | ->once() 63 | ->andReturn($mock_success); 64 | } 65 | 66 | protected function mockValidatorFail() 67 | { 68 | $app = m::mock('AppMock'); 69 | $app->shouldReceive('instance')->once()->andReturn($app); 70 | 71 | Illuminate\Support\Facades\Facade::setFacadeApplication($app); 72 | Illuminate\Support\Facades\Validator::swap($validator = m::mock('validatorMock')); 73 | 74 | $mock_success = m::mock('StdClass'); 75 | $mock_success->shouldReceive(array( 76 | 'fails' => true, 77 | 'messages' => 'ok', 78 | )); 79 | 80 | $validator->shouldReceive('make') 81 | ->with( m::type('Symfony\Component\HttpFoundation\File\UploadedFile') , m::type('array') ) 82 | ->once() 83 | ->andReturn($mock_success); 84 | } 85 | } --------------------------------------------------------------------------------