├── tests ├── _data │ └── .gitkeep ├── _output │ └── .gitignore ├── _support │ ├── _generated │ │ └── .gitignore │ ├── Helper │ │ ├── Unit.php │ │ ├── Acceptance.php │ │ └── Functional.php │ ├── UnitTester.php │ ├── AcceptanceTester.php │ └── FunctionalTester.php ├── unit.suite.yml ├── unit │ └── FieldTest.php └── _bootstrap.php ├── resources └── banner.png ├── codeception.yml ├── .travis.yml ├── .gitignore ├── src ├── records │ ├── SeederUserRecord.php │ ├── SeederAssetRecord.php │ ├── SeederEntryRecord.php │ └── SeederCategoryRecord.php ├── config.php ├── translations │ └── en │ │ └── seeder.php ├── migrations │ ├── m190205_191102_removeSectionColumn.php │ └── Install.php ├── services │ ├── fields │ │ ├── CkEditor.php │ │ ├── Redactor.php │ │ ├── Positionfieldtype.php │ │ ├── configvaluesfield.php │ │ ├── Supertable.php │ │ ├── CTA.php │ │ └── Fields.php │ ├── Categories.php │ ├── Users.php │ ├── Weeder.php │ ├── Entries.php │ └── SeederService.php ├── models │ └── Settings.php ├── console │ └── controllers │ │ ├── CleanUpController.php │ │ └── GenerateController.php ├── templates │ └── _index.twig ├── controllers │ └── SeederController.php ├── Seeder.php ├── icon-mask.svg └── icon.svg ├── .editorconfig.json ├── LICENSE.md ├── composer.json ├── CHANGELOG.md └── README.md /tests/_data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/_output/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /tests/_support/_generated/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /resources/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/studioespresso/craft3-seeder/HEAD/resources/banner.png -------------------------------------------------------------------------------- /tests/unit.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | # 3 | # Suite for unit or integration tests. 4 | 5 | actor: UnitTester 6 | modules: 7 | enabled: 8 | - Asserts 9 | - \Helper\Unit -------------------------------------------------------------------------------- /tests/_support/Helper/Unit.php: -------------------------------------------------------------------------------- 1 | false, 13 | "useLocalAssets" => false, 14 | "sets" => [ 15 | 'default' => [ 16 | 'Users' => [ 17 | // groupId => count 18 | 1 => 10 19 | ], 20 | "Entries" => [ 21 | // sectionId => count 22 | 1 => 20, 23 | ] 24 | ], 25 | ], 26 | ]; 27 | -------------------------------------------------------------------------------- /src/translations/en/seeder.php: -------------------------------------------------------------------------------- 1 | 'Seeder plugin loaded', 25 | ]; 26 | -------------------------------------------------------------------------------- /tests/_support/UnitTester.php: -------------------------------------------------------------------------------- 1 | dropColumn(SeederCategoryRecord::tableName(), 'section'); 20 | } 21 | 22 | /** 23 | * @inheritdoc 24 | */ 25 | public function safeDown() 26 | { 27 | echo "m190205_191102_removeSectionColumn cannot be reverted.\n"; 28 | return false; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/unit/FieldTest.php: -------------------------------------------------------------------------------- 1 | field = new Fields(); 20 | $this->entry = $this->getMockBuilder(Entry::class)->getMock(); 21 | } 22 | 23 | public function testLightswitchField() { 24 | $field = $this->getMockBuilder(Lightswitch::class)->getMock(); 25 | $this->assertInternalType('boolean', $this->field->Lightswitch($field, $this->entry)); 26 | } 27 | 28 | protected function _after() { 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /src/services/fields/CkEditor.php: -------------------------------------------------------------------------------- 1 | factory = Factory::create(); 34 | } 35 | 36 | public function Field($field, $entry) { 37 | return Lorem::sentences(rand(5, 20), true); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /tests/_bootstrap.php: -------------------------------------------------------------------------------- 1 | factory = Factory::create(); 36 | } 37 | 38 | public function Field($field, $entry) 39 | { 40 | return Lorem::sentences(rand(5, 20), true); 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/services/fields/Positionfieldtype.php: -------------------------------------------------------------------------------- 1 | factory = Factory::create(); 37 | } 38 | 39 | public function Position(Position $field, $entry) 40 | { 41 | return array_rand(array_filter($field->options)); 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Studio Espresso 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /src/models/Settings.php: -------------------------------------------------------------------------------- 1 | factory = Factory::create(); 38 | } 39 | 40 | public function ConfigValuesFieldField(ConfigValuesFieldField $field, $entry) 41 | { 42 | if ($field->dataSet) { 43 | $options = \statikbe\configvaluesfield\ConfigValuesField::getInstance()->getSettings()->data[$field->dataSet]; 44 | return array_rand($options); 45 | } 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "studioespresso/craft-seeder", 3 | "description": "Easy entries seeder for Craft CMS", 4 | "type": "craft-plugin", 5 | "version": "3.3.1", 6 | "keywords": [ 7 | "craft", 8 | "cms", 9 | "craftcms", 10 | "craft-plugin", 11 | "seeder" 12 | ], 13 | "support": { 14 | "docs": "https://github.com/studioespresso/craft3-seeder/blob/master/README.md", 15 | "issues": "https://github.com/studioespresso/craft3-seeder/issues" 16 | }, 17 | "license": "MIT", 18 | "authors": [ 19 | { 20 | "name": "Studio Espresso", 21 | "homepage": "https://www.studioepsresso.co" 22 | } 23 | ], 24 | "require": { 25 | "craftcms/cms": "^3.1.0", 26 | "fzaninotto/faker": "^1.7.0" 27 | }, 28 | "require-dev": { 29 | "codeception/codeception": "2.4.2" 30 | }, 31 | "autoload": { 32 | "psr-4": { 33 | "studioespresso\\seeder\\": "src/" 34 | } 35 | }, 36 | "extra": { 37 | "name": "Seeder", 38 | "handle": "seeder", 39 | "hasCpSettings": false, 40 | "hasCpSection": true, 41 | "changelogUrl": "https://raw.githubusercontent.com/studioespresso/craft3-seeder/master/CHANGELOG.md", 42 | "class": "studioespresso\\seeder\\Seeder" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/console/controllers/CleanUpController.php: -------------------------------------------------------------------------------- 1 | getSections(); 44 | foreach ($sections->getAllSections() as $section) { 45 | $seededEntries = SeederEntryRecord::findAll([ 46 | 'section' => $section->id 47 | ]); 48 | if (count($seededEntries)) { 49 | Seeder::$plugin->weeder->entries($section->id); 50 | } 51 | } 52 | 53 | Seeder::$plugin->weeder->assets(); 54 | Seeder::$plugin->weeder->users(); 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/services/fields/Supertable.php: -------------------------------------------------------------------------------- 1 | factory = Factory::create(); 38 | } 39 | 40 | public function SuperTableField(SuperTableField $field, $entry) 41 | { 42 | $types = $field->getBlockTypes(); 43 | $fields = $field->getBlockTypeFields(); 44 | 45 | if ($field->staticField) { 46 | $blockCount = 1; 47 | } else { 48 | $blockCount = rand(!empty($field->minRows) ? $field->minRows : 1, !empty($field->maxRows) ? $field->maxRows : 6); 49 | } 50 | 51 | $blockIds = []; 52 | 53 | $types = array_map(function ($type) { 54 | return $type->id; 55 | }, $types); 56 | 57 | for ($x = 1; $x <= $blockCount; $x++) { 58 | $blockIds[] = $types[array_rand($types, 1)]; 59 | } 60 | 61 | foreach ($blockIds as $blockId) { 62 | $superTableBlock = new SuperTableBlockElement(); 63 | $superTableBlock->typeId = $types[0]; 64 | $superTableBlock->fieldId = $field->id; 65 | $superTableBlock->ownerId = $entry->id; 66 | $superTableBlock = Seeder::$plugin->seeder->populateFields($fields, $superTableBlock); 67 | Craft::$app->elements->saveElement($superTableBlock); 68 | 69 | } 70 | return; 71 | 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /src/services/fields/CTA.php: -------------------------------------------------------------------------------- 1 | factory = Factory::create(); 37 | } 38 | 39 | public function CTAField(\statikbe\cta\fields\CTAField $field, $entry) 40 | { 41 | 42 | $customLabel = $field->allowCustomText; 43 | $blank = $field->allowTarget; 44 | 45 | $attr = [ 46 | 'allowCustomText' => $field->allowCustomText, 47 | 'allowTarget' => $field->allowTarget, 48 | 'defaultText' => $field->defaultText, 49 | 'owner' => $entry, 50 | ]; 51 | 52 | if (CTAPlugin::$plugin->getSettings()->classes) { 53 | $classes = CTAPlugin::$plugin->getSettings()->classes; 54 | } else { 55 | $classes = [ 56 | 'btn' => 'Primary', 57 | 'btn btn--secondary' => 'Secondary', 58 | 'btn btn--ghost' => 'Ghost', 59 | 'link link--ext' => 'Link >', 60 | 'link' => 'Link' 61 | ]; 62 | } 63 | 64 | $attr += [ 65 | 'customText' => $field->allowCustomText ? $this->factory->realText(20) : null, 66 | 'target' => $field->allowTarget ? $this->factory->boolean : null, 67 | 'class' => array_rand($classes), 68 | ]; 69 | 70 | if ((is_array($field->allowedLinkNames) && in_array('url', $field->allowedLinkNames)) || $field->allowedLinkNames === '*' ) { 71 | $attr['type'] = 'url'; 72 | $attr['value'] = $this->factory->url; 73 | } elseif (in_array('email', $field->allowedLinkNames)) { 74 | $attr['type'] = 'email'; 75 | $attr['value'] = $this->factory->email; 76 | } 77 | return new \statikbe\cta\models\CTA($attr); 78 | } 79 | } -------------------------------------------------------------------------------- /src/services/Categories.php: -------------------------------------------------------------------------------- 1 | categories->getGroupById((int)$group); 48 | } else { 49 | $categoryGroup = Craft::$app->categories->getGroupByHandle($group); 50 | } 51 | 52 | if (!$categoryGroup) { 53 | echo "Group not found\n"; 54 | return false; 55 | } 56 | $faker = Factory::create(); 57 | 58 | $fields = Craft::$app->fields->getFieldsByElementType('craft\elements\Category'); 59 | 60 | $current = 0; 61 | $total = $count; 62 | Console::startProgress($current, $count); 63 | for ($x = 1; $x <= $count; $x++) { 64 | $category = new Category([ 65 | 'groupId' => (int)$categoryGroup->id, 66 | 'title' => Seeder::$plugin->fields->Title(20), 67 | ]); 68 | Craft::$app->getElements()->saveElement($category); 69 | Seeder::$plugin->seeder->saveSeededCategory($category); 70 | Seeder::$plugin->seeder->populateFields($fields, $category); 71 | Craft::$app->getElements()->saveElement($category); 72 | $current++; 73 | Console::updateProgress($current, $count); 74 | } 75 | Console::endProgress(); 76 | 77 | } 78 | 79 | } -------------------------------------------------------------------------------- /src/migrations/Install.php: -------------------------------------------------------------------------------- 1 | createTable( 25 | SeederEntryRecord::$tableName, [ 26 | 'id' => $this->primaryKey(), 27 | 'entryUid' => $this->uid()->notNull(), 28 | 'section' => $this->integer()->notNull(), 29 | 'dateCreated' => $this->dateTime()->notNull(), 30 | 'dateUpdated' => $this->dateTime()->notNull(), 31 | 'uid' => $this->uid()->notNull(), 32 | ]); 33 | 34 | $this->createTable( 35 | SeederCategoryRecord::$tableName, [ 36 | 'id' => $this->primaryKey(), 37 | 'categoryUid' => $this->uid()->notNull(), 38 | 'section' => $this->integer()->notNull(), 39 | 'dateCreated' => $this->dateTime()->notNull(), 40 | 'dateUpdated' => $this->dateTime()->notNull(), 41 | 'uid' => $this->uid()->notNull(), 42 | ]); 43 | 44 | $this->createTable( 45 | SeederAssetRecord::$tableName, [ 46 | 'id' => $this->primaryKey(), 47 | 'assetUid' => $this->uid()->notNull(), 48 | 'dateCreated' => $this->dateTime()->notNull(), 49 | 'dateUpdated' => $this->dateTime()->notNull(), 50 | 'uid' => $this->uid()->notNull(), 51 | ]); 52 | 53 | $this->createTable( 54 | SeederUserRecord::$tableName, [ 55 | 'id' => $this->primaryKey(), 56 | 'userUid' => $this->uid()->notNull(), 57 | 'dateCreated' => $this->dateTime()->notNull(), 58 | 'dateUpdated' => $this->dateTime()->notNull(), 59 | 'uid' => $this->uid()->notNull(), 60 | ]); 61 | 62 | } 63 | 64 | /** 65 | * @inheritdoc 66 | */ 67 | public function safeDown() 68 | { 69 | $this->dropTable(SeederEntryRecord::$tableName); 70 | $this->dropTable(SeederCategoryRecord::$tableName); 71 | $this->dropTable(SeederAssetRecord::$tableName); 72 | $this->dropTable(SeederUserRecord::$tableName); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/services/Users.php: -------------------------------------------------------------------------------- 1 | userGroups->getGroupById((int)$group); 48 | } else { 49 | $userGroup = Craft::$app->userGroups->getGroupByHandle($group); 50 | } 51 | 52 | if (!$userGroup) { 53 | echo "Group not found\n"; 54 | return false; 55 | } 56 | 57 | $faker = Factory::create(); 58 | 59 | $fields = Craft::$app->fields->getFieldsByElementType('craft\elements\User'); 60 | $current = 0; 61 | Console::startProgress($current, $count); 62 | for ($x = 1; $x <= $count; $x++) { 63 | $user = new User(); 64 | $user->passwordResetRequired = true; 65 | $user->email = $faker->email; 66 | $user->username = $user->email; 67 | $user->firstName = $faker->firstName; 68 | $user->lastName = $faker->lastName; 69 | Craft::$app->elements->saveElement($user); 70 | Seeder::$plugin->seeder->saveSeededUser($user); 71 | Seeder::$plugin->seeder->populateFields($fields, $user); 72 | Craft::$app->elements->saveElement($user); 73 | Craft::$app->users->assignUserToGroups($user->id, [$userGroup->id]); 74 | $current++; 75 | Console::updateProgress($current, $count); 76 | } 77 | Console::endProgress(); 78 | 79 | } 80 | 81 | } -------------------------------------------------------------------------------- /src/templates/_index.twig: -------------------------------------------------------------------------------- 1 | {# @var craft \craft\web\twig\variables\CraftVariable #} 2 | {# 3 | /** 4 | * Seeder plugin for Craft CMS 3.x 5 | * 6 | * Seeder index.twig 7 | * 8 | * @author studioespresso 9 | * @copyright Copyright (c) 2018 studioespresso 10 | * @link https://studioespresso.co 11 | * @package Seeder 12 | * @since 1.0.0 13 | */ 14 | #} 15 | 16 | {% extends "_layouts/cp" %} 17 | {% import "_includes/forms" as forms %} 18 | 19 | {% set title = "Seeder" %} 20 | 21 | {% set pluginCpUrl = url('seeder') %} 22 | 23 | {% set content %} 24 |
25 | {% if data|length %} 26 | {{ csrfInput() }} 27 | {{ redirectInput('seeder') }} 28 | Select the seeded entries you want to remove 29 | 30 | 31 | {% if data.sections is defined %} 32 |

{{ 'Entries' }}

33 | 34 | {% for section in data.sections %} 35 |
36 | 38 | 39 |
40 | {% endfor %} 41 | 42 | {% endif %} 43 | {% if data.assets is defined or data.users is defined or data.categoryGroups is defined %} 44 |

{{ 'Other'|t }}

45 |
46 | {% if data.categoryGroups is defined %} 47 |
48 | 50 | 51 |
52 | {% endif %} 53 | {% if data.assets is defined %} 54 | 55 | 56 | {% endif %} 57 | {% if data.users is defined %} 58 | 59 | 60 | {% endif %} 61 |
62 | {% endif %} 63 |
64 | 65 | {% else %} 66 | You don't have any seeded entries at the moment. 67 | {% endif %} 68 |
69 | {% endset %} -------------------------------------------------------------------------------- /src/controllers/SeederController.php: -------------------------------------------------------------------------------- 1 | getSections(); 39 | foreach ($sections->getAllSections() as $section) { 40 | $seededEntries = SeederEntryRecord::findAll([ 41 | 'section' => $section->id 42 | ]); 43 | if (count($seededEntries)) { 44 | $data['sections'][$section->id]['id'] = $section->id; 45 | $data['sections'][$section->id]['name'] = $section->name; 46 | $data['sections'][$section->id]['count'] = count($seededEntries); 47 | } 48 | } 49 | 50 | $seededCategories = SeederCategoryRecord::find(); 51 | if ($seededCategories->count()) { 52 | $data['categoryGroups']['count'] = $seededCategories->count(); 53 | } 54 | 55 | $seededAssets = SeederAssetRecord::find(); 56 | if ($seededAssets->count()) { 57 | $data['assets']['count'] = $seededAssets->count(); 58 | } 59 | 60 | $seededUsers = SeederUserRecord::find(); 61 | if ($seededUsers->count()) { 62 | $data['users']['count'] = $seededUsers->count(); 63 | } 64 | 65 | 66 | return $this->renderTemplate('seeder/_index', ['data' => $data]); 67 | } 68 | 69 | public function actionClean() 70 | { 71 | $data = Craft::$app->request->post('data'); 72 | if ($data) { 73 | if (!empty($data['sections'])) { 74 | foreach ($data['sections'] as $sectionId) { 75 | Seeder::$plugin->weeder->entries($sectionId); 76 | } 77 | } 78 | if (!empty($data['categories'])) { 79 | Seeder::$plugin->weeder->categories(); 80 | } 81 | if (!empty($data['assets'])) { 82 | Seeder::$plugin->weeder->assets(); 83 | } 84 | if (!empty($data['users'])) { 85 | Seeder::$plugin->weeder->users(); 86 | } 87 | } 88 | return $this->redirectToPostedUrl(); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Craft Seeder Changelog 2 | 3 | ## 3.3.1 - 2029-10-12 4 | ### Added 5 | - Added support for Craft's number field 6 | - Plain text fields now work with the fields config 7 | - Titles based in custom fields nowget set correctly 8 | 9 | 10 | ## 3.2.0 - 2019-12-23 11 | ### Added 12 | - support for Entries fields 13 | - support for [statikbe/craft-config-values](https://github.com/statikbe/craft-config-values) 14 | - better support for [statikbe/craft-cta-field](https://github.com/statikbe/craft3-ctafield) 15 | ### Fixed 16 | - Fixed the seeding of category fields ([#11](https://github.com/studioespresso/craft3-seeder/issues/11)) 17 | 18 | ## 3.1.1 - 2019-10-11 19 | ### Fixed 20 | - `useLocalAssets` now also works with images in the root of the volume 21 | - Unsupported fields are now logged instead of show in console 22 | 23 | ## 3.1.0 - 2019-10-08 24 | ### Added 25 | - Added `eachMatrixBlock` option, to seed a matrix with one of each blocktype in a random order ([#13](https://github.com/studioespresso/craft3-seeder/issues/13)) 26 | - Added`useLocalAssets` option, to seed asset fields with assets from a specified volume & folder, to be used in case you have your own set of test images. 27 | - Added support for [rias/craft-position-fieldtype](https://github.com/Rias500/craft-position-fieldtype) 28 | - Added support for seeding entries for specific sites by using a `siteId` parameter 29 | 30 | ## 3.0.1 - 2019-04-09 31 | 32 | ### Added 33 | - Progress bars when generating elements ([#4](https://github.com/studioespresso/craft3-seeder/issues/4)) 34 | 35 | ### Fixed 36 | - Fixed an issue with seeding categories ([#8](https://github.com/studioespresso/craft3-seeder/issues/8)) 37 | - Fixed an issue with seeding entries for sections without fields 38 | 39 | ## 3.0.0 - 2019-02-05 40 | 41 | ### Added 42 | - Seeder now works with Craft 3.1 🎉 43 | - Added support for [statikbe/craft-cta-field](https://github.com/statikbe/craft3-ctafield) 44 | ### Fixed 45 | - Fixed asset fields in Craft 3.1 46 | - Fixed an issue where seeding a Supertable field in a Matrix field would crash 47 | - Fixed an issue with minimum & maximum number of blocks on a Supertable field 48 | 49 | ## 2.1.0 - 2018-09-19 50 | 51 | ### Added 52 | - Added support for fields on Users 53 | - Added support for fields on Categories 54 | 55 | ## 2.0.0 - 2018-08-24 56 | ### Changed 57 | - The commands now take named parameters in stead of just IDs 58 | - The commands now also work with section/group handle or with section/group id 59 | ### Added 60 | - Supertable support, Super table static field support and all core fields in a Supertable field 61 | 62 | ## 1.0.3 - 2018-05-29 63 | ### Fixed 64 | - Fixes an issues with min/max rows in table fields (issue #3) 65 | 66 | ## 1.0.2 - 2018-05-24 67 | ### Fixed 68 | - Fixed an issue with asset fields that did not have a limit set. Now we'll seed a random number of images between 1 and 5 for those. 69 | 70 | ## 1.0.1 - 2018-05-23 71 | ### Changed 72 | - Seeded images are now smaller (1600x1200), which are served more reliable from lorempixel.com 73 | 74 | ## 1.0.0 - 2018-05-16 75 | ### Added 76 | - Initial release 77 | -------------------------------------------------------------------------------- /src/services/Weeder.php: -------------------------------------------------------------------------------- 1 | $sectionId 41 | ]); 42 | $section = Craft::$app->sections->getSectionById($sectionId); 43 | foreach ($seededEntries as $seededEntry) { 44 | $entry = Entry::find() 45 | ->uid($seededEntry->entryUid) 46 | ->section($section->handle) 47 | ->one(); 48 | if ($entry) { 49 | Craft::$app->elements->deleteElement($entry); 50 | } 51 | SeederEntryRecord::deleteAll(['entryUid' => $seededEntry->entryUid]); 52 | } 53 | } 54 | 55 | public function categories() 56 | { 57 | $seededCategories = SeederCategoryRecord::find(); 58 | foreach ($seededCategories->all() as $seededCategory) { 59 | $category = Category::find() 60 | ->uid($seededCategory->categoryUid) 61 | ->one(); 62 | if ($category) { 63 | Craft::$app->elements->deleteElement($category); 64 | } 65 | SeederCategoryRecord::deleteAll(['categoryUid' => $seededCategory->categoryUid]); 66 | } 67 | } 68 | 69 | public function assets() 70 | { 71 | $seededAssets = SeederAssetRecord::find(); 72 | foreach ($seededAssets->all() as $seededAsset) { 73 | $asset = Asset::find() 74 | ->uid($seededAsset->assetUid) 75 | ->one(); 76 | if ($asset) { 77 | Craft::$app->elements->deleteElement($asset); 78 | SeederAssetRecord::deleteAll(['assetUid' => $seededAsset->assetUid]); 79 | } 80 | } 81 | } 82 | 83 | public function users() 84 | { 85 | $seededUsers = SeederUserRecord::find(); 86 | foreach ($seededUsers->all() as $seededUser) { 87 | $user = User::find() 88 | ->uid($seededUser->userUid) 89 | ->one(); 90 | if ($user) { 91 | Craft::$app->elements->deleteElement($user); 92 | } 93 | SeederUserRecord::deleteAll(['userUid' => $seededUser->userUid]); 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /src/services/Entries.php: -------------------------------------------------------------------------------- 1 | sections->getSectionById((int)$section); 49 | } else { 50 | $section = Craft::$app->sections->getSectionByHandle($section); 51 | } 52 | 53 | if (!$section) { 54 | echo "Section not found\n"; 55 | return false; 56 | } 57 | $faker = Factory::create(); 58 | 59 | $entryTypes = $section->getEntryTypes(); 60 | $current = 0; 61 | $total = count($entryTypes) * $count; 62 | Console::startProgress($current, $count); 63 | foreach ($section->getEntryTypes() as $entryType) { 64 | for ($x = 1; $x <= $count; $x++) { 65 | $current++; 66 | Console::updateProgress($current, $count); 67 | if ($entryType->fieldLayoutId) { 68 | $typeFields = Craft::$app->fields->getFieldsByLayoutId($entryType->getFieldLayoutId()); 69 | } 70 | $entry = new Entry([ 71 | 'sectionId' => (int)$section->id, 72 | 'siteId' => $siteId ? $siteId : Craft::$app->getSites()->getPrimarySite()->id, 73 | 'typeId' => $entryType->id, 74 | 'title' => Seeder::$plugin->fields->Title(), 75 | ]); 76 | Craft::$app->getElements()->saveElement($entry); 77 | Seeder::$plugin->seeder->saveSeededEntry($entry); 78 | if ($entryType->fieldLayoutId) { 79 | $entry = Seeder::$plugin->seeder->populateFields($typeFields, $entry); 80 | $entry->updateTitle(); 81 | $entry->slug = ''; 82 | Craft::$app->getElements()->saveElement($entry); 83 | } 84 | } 85 | } 86 | Console::endProgress(); 87 | return $section->name; 88 | 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /src/services/SeederService.php: -------------------------------------------------------------------------------- 1 | getSettings()->fields[$field->handle]) && 46 | Seeder::$plugin->getSettings()->fields[$field->handle] == 'ignore') { 47 | continue; 48 | } 49 | try { 50 | $fieldData = $this->isFieldSupported($field); 51 | if ($fieldData) { 52 | $fieldProvider = $fieldData[0]; 53 | $fieldType = $fieldData[1]; 54 | $entryFields[$field['handle']] = Seeder::$plugin->$fieldProvider->$fieldType($field, $entry); 55 | } 56 | } catch (FieldNotFoundException $e) { 57 | if (Seeder::$plugin->getSettings()->debug) { 58 | dd($e); 59 | } else { 60 | Craft::warning("Fieldtype not supported: $fieldType", __CLASS__); 61 | } 62 | } 63 | } 64 | $entry->setFieldValues($entryFields); 65 | 66 | return $entry; 67 | 68 | } 69 | 70 | /** 71 | * @param Entry $entry 72 | */ 73 | public function saveSeededEntry($entry) 74 | { 75 | $record = new SeederEntryRecord(); 76 | $record->entryUid = $entry->uid; 77 | $record->section = $entry->sectionId; 78 | $record->save(); 79 | } 80 | 81 | /** 82 | * @param Asset $asset 83 | */ 84 | public function saveSeededAsset($asset) 85 | { 86 | $record = new SeederAssetRecord(); 87 | $record->assetUid = $asset->uid; 88 | $record->save(); 89 | } 90 | 91 | /** 92 | * @param User $user 93 | */ 94 | public function saveSeededUser($user) 95 | { 96 | $record = new SeederUserRecord(); 97 | $record->userUid = $user->uid; 98 | $record->save(); 99 | } 100 | 101 | /** 102 | * @param Asset $asset 103 | */ 104 | public function saveSeededCategory($category) 105 | { 106 | $record = new SeederCategoryRecord(); 107 | $record->section = $category->groupId; 108 | $record->categoryUid = $category->uid; 109 | $record->save(); 110 | } 111 | 112 | private function isFieldSupported($field) 113 | { 114 | $fieldType = explode('\\', get_class($field)); 115 | $fieldProvider = $fieldType[1]; 116 | $fieldType = end($fieldType); 117 | 118 | if (class_exists('studioespresso\\seeder\\services\\fields\\' . $fieldProvider)) { 119 | if (in_array($fieldType, get_class_methods(Seeder::getInstance()->$fieldProvider))) { 120 | return [$fieldProvider, $fieldType]; 121 | } else { 122 | if (Seeder::$plugin->getSettings()->debug) { 123 | throw new FieldNotFoundException('Fieldtype not supported: ' . $fieldType); 124 | } else { 125 | Craft::warning("Fieldtype not supported: $fieldType", __CLASS__); 126 | } 127 | } 128 | } else { 129 | if (Seeder::$plugin->getSettings()->debug) { 130 | throw new FieldNotFoundException('Fieldtype not supported: ' . $fieldType); 131 | } else { 132 | Craft::warning("Fieldtype not supported: $fieldType", __CLASS__); 133 | } 134 | } 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Seeder plugin for Craft CMS 3.x 2 | 3 | ![Seeder](/resources/banner.png?raw=true) 4 | 5 | ## Usage 6 | 7 | Seeder allows you to quickly create dummy entries through the command line. And you can just as easily remove the dummy data when you're done building the site. 8 | With the plugin installed, running `./craft help seeder/generate` will show you which commands are available 9 | 10 | Since the plugin is only usefull during the development and not on a live site, charging money for it would be stupid (you could just free trial it every time). Instead you can download it for free and if you want to support future development, you can support it on [beerpay.io](https://beerpay.io/studioespresso/craft3-seeder). Thanks! 11 | 12 | [![Beerpay](https://beerpay.io/studioespresso/craft3-seeder/badge.svg)](https://beerpay.io/studioespresso/craft3-seeder) 13 | 14 | ## Installation 15 | 16 | To install the plugin, follow these instructions. 17 | 18 | 1. Open your terminal and go to your Craft project: 19 | 20 | cd /path/to/project 21 | 22 | 2. Then tell Composer to load the plugin: 23 | 24 | composer require studioespresso/craft-seeder 25 | 26 | 3. In the Control Panel, go to Settings → Plugins and click the “Install” button for "Seeder". 27 | 28 | ### Usage 29 | 30 | #### Entries (Section ID/handle, siteId, count) 31 | 32 | Use the command below, followed by the ``--section`` option and the ``--number`` of entries you want to create (defaults to 20 if ommited). This command works with both section ID and handle. 33 | 34 | You can also add a `siteId` parameter to seed entries for a specific site. This will use the default site as a fallback. 35 | ```Shell 36 | ./craft seeder/generate/entries --section=news --count=15 37 | ``` 38 | 39 | #### Categories (Category group ID/handle, count) 40 | ```Shell 41 | ./craft seeder/generate/categories --group=labels --count=10 42 | ``` 43 | 44 | #### Users (Usergroup ID/handle, count) 45 | ```Shell 46 | ./craft seeder/generate/users --group=editors --count=5 47 | ``` 48 | 49 | ## Clean up 50 | Once you're done building out the site, the plugin gives you an easy way to remove the dummy data (entries, assets, categories and users). This can be done through the CP (click the Seeder section the sidebar) or through the command line with the following command: 51 | 52 | ```Shell 53 | ./craft seeder/clean-up/all 54 | ``` 55 | 56 | ## Configuration options 57 | ### ``eachMatrixBlock`` - Seed all blocktypes in a matrix field 58 | For a matrix, the plugin will get a random set of block types within the minimum & maximum amounts of blocks the field allows. 59 | 60 | With this setting set to `true`, we'll generate a block of each blocktype once in a random order. This is a good way to test pagebuilder/contentbuilder-like fields. 61 | 62 | ### `useLocalAssets` - Use assets already in your site to seed asset fields 63 | ````php 64 | 'useLocalAssets' => [ 65 | 'volumeId' => 1, 66 | 'path' => 'test/' 67 | ] 68 | ```` 69 | 70 | Add the array above to ``config/seeder.php`` to seed using assets from volume `1` and folder `test/`. 71 | 72 | ### `fields` - Basic field configuration 73 | 74 | 75 | ````php 76 | 'fields' => [ 77 | "sessions" => "ignore", 78 | "radioField" => [ 79 | 'value' => 'value2', 80 | ], 81 | "category" => [ 82 | 'mode' => 'random', 83 | 'value' => [152, 153] 84 | ] 85 | ] 86 | ```` 87 | 88 | These are some basic examples of how you can defined seeding settings per field. 89 | The field handle should be the key in the array and the options are available right now: 90 | - "ignore" => skip the field when seeding 91 | - `["value" => "some string" ]` => Works to set a fixed value for plain text fields, checkboxes, radio buttons. 92 | - `["mode" => "random", "value" => [1, 2] ]` => Works with entries and category fields, values should be ids of those entries. 93 | 94 | 95 | ## Troubleshooting 96 | The most common problem with the plugins is getting the following error: 97 | ````Shell 98 | Unknown command: seeder/generate/entries 99 | ```` 100 | If you have the plugin installed in the CP and are seeing this message, craft can not connect to your database through the command line. Your site probably works correctly but CLI commands won't. 101 | 102 | If you're running MAMP/XAMP, you should use `127.0.0.1` as hostname instead of `localhost`. 103 | 104 | 105 | ## Roadmap 106 | 107 | #### Core elements 108 | - [x] Entries 109 | - [x] Categories 110 | - [x] Users 111 | - [x] Entry fields 112 | 113 | #### Core fields 114 | - [x] Title 115 | - [x] Plain text 116 | - [x] Email 117 | - [x] Url 118 | - [x] Color 119 | - [x] Date 120 | - [x] Entries 121 | - [x] Categories 122 | - [x] Dropdown 123 | - [x] Checkboxes 124 | - [x] Radio buttons 125 | - [x] Multi select 126 | - [x] Assets 127 | - [x] Matrix 128 | - [x] Lightswitch 129 | - [x] Table 130 | - [x] Tags 131 | - [x] Users 132 | 133 | #### Plugin elements 134 | - [ ] Commerce products & variants 135 | 136 | #### Plugin fields 137 | - [x] [Redactor](https://github.com/craftcms/redactor) 138 | - [x] [CKEditor](https://github.com/craftcms/ckeditor) 139 | - [x] [Super Table](https://github.com/verbb/super-table) 140 | - [x] [Position field](https://github.com/Rias500/craft-position-fieldtype) -------------------------------------------------------------------------------- /src/Seeder.php: -------------------------------------------------------------------------------- 1 | components = [ 107 | "seeder" => SeederService::class, 108 | "weeder" => WeederService::class, 109 | "entries" => Entries::class, 110 | "categories" => Categories::class, 111 | "users" => Users::class, 112 | "fields" => Fields::class, 113 | "redactor" => Redactor::class, 114 | "ckeditor" => CkEditor::class, 115 | "supertable" => Supertable::class, 116 | "cta" => CTA::class, 117 | "configvaluesfield" => configvaluesfield::class, 118 | "positionfieldtype" => PositionService::class, 119 | ]; 120 | 121 | Event::on( 122 | UrlManager::class, 123 | UrlManager::EVENT_REGISTER_CP_URL_RULES, 124 | function (RegisterUrlRulesEvent $event) { 125 | $event->rules['seeder'] = 'seeder/seeder/index'; 126 | } 127 | ); 128 | 129 | // Add in our console commands 130 | if (Craft::$app instanceof ConsoleApplication) { 131 | $this->controllerNamespace = 'studioespresso\seeder\console\controllers'; 132 | } 133 | } 134 | 135 | // Protected Methods 136 | // ========================================================================= 137 | 138 | /** 139 | * Creates and returns the model used to store the plugin’s settings. 140 | * 141 | * @return \craft\base\Model|null 142 | */ 143 | protected function createSettingsModel() 144 | { 145 | return new Settings(); 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /src/console/controllers/GenerateController.php: -------------------------------------------------------------------------------- 1 | section) { 82 | echo "Section handle or id missing, please specify\n"; 83 | return; 84 | } 85 | 86 | $result = Seeder::$plugin->entries->generate($this->section, $this->siteId, $this->count); 87 | return $result; 88 | } 89 | 90 | /** 91 | * Generates categories for the specified group 92 | * 93 | * The first line of this method docblock is displayed as the description 94 | * of the Console Command in ./craft help 95 | * 96 | * @return mixed 97 | */ 98 | public function actionCategories() 99 | { 100 | 101 | if (!$this->group) { 102 | echo "Group handle or id missing, please specify\n"; 103 | return; 104 | } 105 | $result = Seeder::$plugin->categories->generate($this->group, $this->count); 106 | 107 | return $result; 108 | } 109 | 110 | /** 111 | * Generates users for the specified usergroup 112 | * 113 | * The first line of this method docblock is displayed as the description 114 | * of the Console Command in ./craft help 115 | * 116 | * @return mixed 117 | */ 118 | public function actionUsers() 119 | { 120 | if (Craft::$app->getEdition() != Craft::Pro) { 121 | echo "Users requires your Craft install to be upgrade to Pro. You can trial Craft Pro in the control panel\n"; 122 | return; 123 | } 124 | 125 | if (!$this->group) { 126 | echo "Group handle or id missing, please specify\n"; 127 | return; 128 | } 129 | $result = Seeder::$plugin->users->generate($this->group, $this->count); 130 | return $result; 131 | } 132 | 133 | /** 134 | * Generates a set of elements predefined in your config/seeder.php 135 | * 136 | * The first line of this method docblock is displayed as the description 137 | * of the Console Command in ./craft help 138 | * 139 | * @return mixed 140 | */ 141 | public function actionSet($name = 'default') 142 | { 143 | if (!array_key_exists($name, Seeder::$plugin->getSettings()->sets)) { 144 | echo "Set not found\n"; 145 | return; 146 | } 147 | $settings = Seeder::$plugin->getSettings()->sets[$name]; 148 | foreach ($settings as $type => $option) { 149 | d($type, $option); 150 | switch ($type) { 151 | case 'Users': 152 | if (is_array($option)) { 153 | foreach ($option as $group => $count) { 154 | $result = Seeder::$plugin->users->generate($group, $count); 155 | if ($result) { 156 | echo "Seeded " . $count . " entries in " . $result . "\n"; 157 | } 158 | } 159 | } 160 | break; 161 | case 'Entries': 162 | if (is_array($option)) { 163 | foreach ($option as $section => $count) { 164 | $result = Seeder::$plugin->entries->generate($section, $count); 165 | if ($result) { 166 | echo "Seeded " . $count . " entries in " . $result . "\n"; 167 | } 168 | } 169 | } 170 | break; 171 | } 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/icon-mask.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Untitled 2 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Untitled 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/services/fields/Fields.php: -------------------------------------------------------------------------------- 1 | factory = Factory::create(); 60 | $this->settings = Seeder::$plugin->getSettings(); 61 | } 62 | 63 | public function Title($maxLength = 40) 64 | { 65 | $title = $this->factory->text(rand(8, $maxLength)); 66 | $title = substr($title, 0, strlen($title) - 1); 67 | return $title; 68 | } 69 | 70 | /** 71 | * @param PlainText $field 72 | * @param Entry $entry 73 | */ 74 | public function PlainText($field, $entry) 75 | { 76 | $configValue = $this->getFieldConfig($field, $entry); 77 | if ($configValue) { 78 | return $configValue; 79 | } 80 | 81 | return $this->factory->realText($field->charLimit ? $field->charLimit : 200); 82 | } 83 | 84 | /** 85 | * @param Email $field 86 | */ 87 | public function Email($field, $entry) 88 | { 89 | return $this->factory->email(); 90 | } 91 | 92 | /** 93 | * @param Url $field 94 | **/ 95 | public function Url($field, $entry) 96 | { 97 | return $this->factory->url(); 98 | } 99 | 100 | public function Color($field, $entry) 101 | { 102 | return $this->factory->safeHexColor; 103 | 104 | } 105 | 106 | public function Date($field, $entry) 107 | { 108 | return $this->factory->dateTime(); 109 | 110 | } 111 | 112 | /** 113 | * @param Categories $field 114 | * @param Entry $entry 115 | */ 116 | public function Categories($field, $entry) 117 | { 118 | $configValue = $this->getFieldConfig($field, $entry); 119 | if ($configValue) { 120 | return $configValue; 121 | } 122 | 123 | $source = explode(":", $field->source); 124 | $catGroup = Craft::$app->getCategories()->getGroupByUid($source[1]); 125 | $cats = Category::find() 126 | ->groupId($catGroup->id) 127 | ->ids(); 128 | 129 | $categories = []; 130 | if ($cats) { 131 | for ($x = 1; $x <= $field->branchLimit; $x++) { 132 | $categories[] = $cats[array_rand($cats)]; 133 | } 134 | } 135 | return $categories; 136 | } 137 | 138 | /** 139 | * @param Dropdown $field 140 | * @param Entry $entry 141 | * 142 | */ 143 | public function Dropdown($field, $entry) 144 | { 145 | $configValue = $this->getFieldConfig($field, $entry); 146 | if ($configValue) { 147 | return $configValue; 148 | } 149 | 150 | return $field->options[array_rand($field->options)]['value']; 151 | } 152 | 153 | /** 154 | * @param Checkboxes $field 155 | * @param Entry $entry 156 | */ 157 | public function Checkboxes($field, $entry) 158 | { 159 | $configValue = $this->getFieldConfig($field, $entry); 160 | if ($configValue) { 161 | return $configValue; 162 | } 163 | 164 | $checkedBoxes = []; 165 | for ($x = 1; $x <= rand(1, count($field->options)); $x++) { 166 | $checkedBoxes[] = $field->options[array_rand($field->options)]['value']; 167 | } 168 | return $checkedBoxes; 169 | } 170 | 171 | /** 172 | * @param Number $field 173 | * @param Entry $entry 174 | */ 175 | public function Number($field, $entry) 176 | { 177 | $configValue = $this->getFieldConfig($field, $entry); 178 | if ($configValue) { 179 | return $configValue; 180 | } 181 | 182 | return rand($field->min, $field->max ? $field->max : 100); 183 | } 184 | 185 | /** 186 | * @param RadioButtons $field 187 | * @param Entry $entry 188 | */ 189 | public function RadioButtons($field, $entry) 190 | { 191 | $configValue = $this->getFieldConfig($field, $entry); 192 | if ($configValue) { 193 | return $configValue; 194 | } 195 | 196 | return $field->options[array_rand($field->options)]['value']; 197 | } 198 | 199 | /** 200 | * @param MultiSelect $field 201 | * @param Entry $entry 202 | */ 203 | public function MultiSelect($field, $entry) 204 | { 205 | $options = []; 206 | for ($x = 1; $x <= rand(1, count($field->options)); $x++) { 207 | $options[] = $field->options[array_rand($field->options)]['value']; 208 | } 209 | return $options; 210 | } 211 | 212 | /** 213 | * @param Lightswitch $field 214 | * @param Entry $entry 215 | */ 216 | public function Lightswitch($field, $entry) 217 | { 218 | return $this->factory->boolean; 219 | } 220 | 221 | /** 222 | * @param Table $field 223 | * @param Entry $entry 224 | */ 225 | public function Table($field, $entry) 226 | { 227 | 228 | if ($field->minRows) { 229 | $min = $field->minRows; 230 | } else { 231 | $min = 1; 232 | } 233 | if ($field->maxRows) { 234 | $max = $field->maxRows; 235 | } else { 236 | $max = $min + 10; 237 | } 238 | 239 | $table = []; 240 | for ($x = 0; $x <= rand($min, $max); $x++) { 241 | foreach ($field->columns as $handle => $col) { 242 | switch ($col['type']) { 243 | case "singleline": 244 | $table[$x][$handle] = $this->factory->text(30); 245 | break; 246 | case "multiline": 247 | $table[$x][$handle] = $this->factory->realText(150, rand(2, 5)); 248 | break; 249 | case "lightswitch": 250 | $table[$x][$handle] = $this->factory->boolean; 251 | break; 252 | case "number": 253 | $table[$x][$handle] = $this->factory->numberBetween(2, 30); 254 | break; 255 | case "checkbox": 256 | $table[$x][$handle] = $this->factory->boolean; 257 | break; 258 | case "date": 259 | $table[$x][$handle] = $this->factory->dateTime; 260 | break; 261 | case "time": 262 | $table[$x][$handle] = $this->factory->dateTime; 263 | break; 264 | case "color": 265 | $table[$x][$handle] = $this->factory->hexColor; 266 | break; 267 | } 268 | } 269 | } 270 | return $table; 271 | } 272 | 273 | /** 274 | * @param Tags $field 275 | * @param Entry $entry 276 | */ 277 | public function Tags($field, $entry) 278 | { 279 | $tags = []; 280 | for ($x = 1; $x <= rand(1, 5); $x++) { 281 | $tag = new Tag(); 282 | $tag->groupId = $field->groupId; 283 | $tag->title = $this->title(); 284 | Craft::$app->elements->saveElement($tag); 285 | $tags[] = $tag->id; 286 | } 287 | return $tags; 288 | } 289 | 290 | /** 291 | * @param Users $field 292 | * @param Entry $entry 293 | */ 294 | public function Users($field, $entry) 295 | { 296 | throw new FieldNotFoundException('Users field not supported'); 297 | } 298 | 299 | /** 300 | * @param Entries $field 301 | * @param Entry $entry 302 | */ 303 | public function Entries($field, $entry) 304 | { 305 | $configValue = $this->getFieldConfig($field, $entry); 306 | if ($configValue) { 307 | return $configValue; 308 | } 309 | 310 | $criteria = Entry::find($field->getSettings()); 311 | $criteria->limit = $field->limit; 312 | return $criteria->ids(); 313 | } 314 | 315 | /** 316 | * @param AssetsField $field 317 | */ 318 | public function Assets($field, $entry) 319 | { 320 | $assets = []; 321 | 322 | if ($field->limit) { 323 | $limit = $field->limit; 324 | } else { 325 | $limit = 5; 326 | } 327 | 328 | if (Seeder::getInstance()->getSettings()->useLocalAssets) { 329 | $assetSettings = Seeder::getInstance()->getSettings()->useLocalAssets; 330 | $folder = VolumeFolder::findOne([ 331 | 'volumeId' => $assetSettings['volumeId'], 332 | 'path' => $assetSettings['path'] ?? '' 333 | ]); 334 | 335 | $localAssets = Asset::find(); 336 | $localAssets->orderBy('RAND()'); 337 | $localAssets->folderId($folder->id); 338 | $localAssets->limit($limit); 339 | $assets = array_values($localAssets->ids()); 340 | 341 | } else { 342 | $path = new Path(); 343 | $dir = $path->getTempAssetUploadsPath() . '/seeder/'; 344 | if (!is_dir($dir)) { 345 | mkdir($dir); 346 | } 347 | 348 | $folder = explode(':', $field->defaultUploadLocationSource); 349 | $folderUid = $folder[1]; 350 | $assetFolder = Craft::$app->volumes->getVolumeByUid($folderUid); 351 | 352 | for ($x = 1; $x <= rand(1, $limit); $x++) { 353 | 354 | $image = $this->factory->imageUrl(1600, 1200, null, true); 355 | $ch = curl_init(); 356 | curl_setopt($ch, CURLOPT_URL, $image); 357 | curl_setopt($ch, CURLOPT_HEADER, 0); 358 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 359 | curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); 360 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 361 | $picture = curl_exec($ch); 362 | curl_close($ch); 363 | 364 | $tmpImage = 'photo-' . rand() . '.jpg'; 365 | $tempPath = $dir . $tmpImage; 366 | $saved = file_put_contents($tempPath, $picture); 367 | 368 | $result = $this->uploadNewAsset($assetFolder->id, $tempPath); 369 | Seeder::$plugin->seeder->saveSeededAsset($result); 370 | $assets[] = $result->id; 371 | } 372 | } 373 | 374 | return $assets; 375 | 376 | } 377 | 378 | /** 379 | * @param Matrix $field 380 | */ 381 | public function Matrix($field, $entry) 382 | { 383 | $types = $field->getBlockTypes(); 384 | 385 | $blockIds = []; 386 | $types = array_map(function ($type) { 387 | return $type->id; 388 | }, $types); 389 | 390 | if (Seeder::getInstance()->getSettings()->eachMatrixBlock) { 391 | $blockCount = count($types); 392 | for ($x = 0; $x < $blockCount; $x++) { 393 | $blockIds[] = $types[$x]; 394 | } 395 | shuffle($blockIds); 396 | } else { 397 | $blockCount = rand(!empty($field->minBlocks) ? $field->minBlocks : 1, !empty($field->maxBlocks) ? $field->maxBlocks : 6); 398 | for ($x = 1; $x <= $blockCount; $x++) { 399 | $blockIds[] = $types[array_rand($types, 1)]; 400 | } 401 | } 402 | 403 | foreach ($blockIds as $blockId) { 404 | $type = Craft::$app->matrix->getBlockTypeById($blockId); 405 | $blockTypeFields = Craft::$app->fields->getFieldsByLayoutId($type->fieldLayoutId); 406 | $matrixBlock = new MatrixBlock(); 407 | $matrixBlock->typeId = $type->id; 408 | $matrixBlock->fieldId = $field->id; 409 | $matrixBlock->ownerId = $entry->id; 410 | Craft::$app->elements->saveElement($matrixBlock); 411 | $matrixBlock = Seeder::$plugin->seeder->populateFields($blockTypeFields, $matrixBlock); 412 | Craft::$app->elements->saveElement($matrixBlock); 413 | 414 | } 415 | return; 416 | } 417 | 418 | private function uploadNewAsset($folderId, $path) 419 | { 420 | $assets = Craft::$app->getAssets(); 421 | $folder = $assets->findFolder(['id' => $folderId]); 422 | 423 | if (!$folder) { 424 | throw new BadRequestHttpException('The target folder provided for uploading is not valid'); 425 | } 426 | 427 | // Check the permissions to upload in the resolved folder. 428 | $filename = Assets::prepareAssetName($path); 429 | 430 | $asset = new Asset(); 431 | $asset->tempFilePath = $path; 432 | $asset->filename = $filename; 433 | $asset->newFolderId = $folder->id; 434 | $asset->volumeId = $folder->volumeId; 435 | $asset->avoidFilenameConflicts = true; 436 | $asset->setScenario(Asset::SCENARIO_CREATE); 437 | 438 | $result = Craft::$app->getElements()->saveElement($asset); 439 | 440 | return $asset; 441 | } 442 | 443 | private function getFieldConfig($field, $entry) 444 | { 445 | if (isset($this->settings->fields[$field->handle])) { 446 | if (isset($this->settings->fields[$field->handle]['mode'])) { 447 | $mode = $this->settings->fields[$field->handle]['mode']; 448 | if ($mode === "random") { 449 | $key = array_rand($this->settings->fields[$field->handle]['value']); 450 | return [$this->settings->fields[$field->handle]['value'][$key]]; 451 | } 452 | } elseif (isset($this->settings->fields[$field->handle]['value'])) { 453 | return $this->settings->fields[$field->handle]['value']; 454 | } 455 | } 456 | return false; 457 | } 458 | } --------------------------------------------------------------------------------