├── .codacy.yml
├── .editorconfig
├── .github
├── FUNDING.yml
└── workflows
│ └── build-ci.yml
├── .gitignore
├── .scrutinizer.yml
├── .styleci.yml
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE.md
├── README.md
├── composer.json
├── composer.lock
├── config
└── laravel-mongo-auto-sync.php
├── docker-compose.yml
├── phpcs.xml
├── phpstan.neon
├── phpunit.xml
├── src
├── Console
│ ├── DropCollection.php
│ └── GenerateModelDocumentation.php
├── Extensions
│ └── MongoCollection.php
├── Http
│ └── Models
│ │ ├── DefaultGeo.php
│ │ ├── DefaultMini.php
│ │ ├── MDModel.php
│ │ └── MSModel.php
├── MongoAutoSyncServiceProvider.php
├── Traits
│ ├── Helper.php
│ ├── MainMongoTrait.php
│ ├── ModelAdditionalMethod.php
│ ├── PlainMongoTrait.php
│ └── RelationshipMongoTrait.php
└── syncUtils.php
└── tests
├── BrowserKitTestCase.php
├── CreatesApplication.php
├── DropCollectionTest.php
├── GenerateModelDocumentationTest.php
├── HelperTest.php
├── MDModelTest.php
├── MainMongoTraitTest.php
├── ModelAdditionalMethodTest.php
├── Models
├── Article.php
├── Category.php
├── Item.php
├── MiniArticle.php
├── MiniCategory.php
├── MiniItem.php
├── MiniNavigation.php
├── MiniPermission.php
├── MiniRole.php
├── MiniSubItem.php
├── MiniUser.php
├── Navigation.php
├── Permission.php
├── Role.php
├── SubItem.php
└── User.php
├── MongoCollectionTest.php
├── MongoSyncTraitTest.php
├── SimpleTestCase.php
├── StoreWIthSyncTest.php
├── SyncTestCase.php
├── SyncUtilsTest.php
├── TestCase.php
├── UpdateWithSyncTest.php
└── config
├── database.php
└── queue.php
/.codacy.yml:
--------------------------------------------------------------------------------
1 | exclude_paths:
2 | - '.github/**'
3 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | ; This file is for unifying the coding style for different editors and IDEs.
2 | ; More information at http://editorconfig.org
3 |
4 | root = true
5 |
6 | [*]
7 | charset = utf-8
8 | indent_size = 4
9 | indent_style = space
10 | end_of_line = lf
11 | insert_final_newline = true
12 | trim_trailing_whitespace = true
13 |
14 | [*.md]
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: offline-agency
2 |
--------------------------------------------------------------------------------
/.github/workflows/build-ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | tags:
7 | pull_request:
8 |
9 | jobs:
10 | build:
11 | runs-on: ${{ matrix.os }}
12 | strategy:
13 | matrix:
14 | php: ['7.4', '8.0', '8.1']
15 | os: ['ubuntu-latest']
16 | mongodb: ['3.6', '4.0', '4.2', '5.0', '6.0', '7.0']
17 | services:
18 | mongo:
19 | image: mongo:${{ matrix.mongodb }}
20 | ports:
21 | - 27017:27017
22 |
23 | name: PHP v${{ matrix.php }} with Mongo v${{ matrix.mongodb }}
24 | steps:
25 | - uses: actions/checkout@v2
26 | - name: "Installing php"
27 | uses: shivammathur/setup-php@v2
28 | with:
29 | php-version: ${{ matrix.php }}
30 | extensions: curl,mbstring,xdebug
31 | coverage: xdebug
32 | tools: composer
33 | - name: Show PHP version
34 | run: php -v && composer -V
35 | - name: Show Dockerfile version
36 | run: if [[ "$DEBUG" == "true" ]]; then docker version && env; fi
37 | env:
38 | DEBUG: ${{secrets.DEBUG}}
39 | - name: Download Composer cache dependencies from cache
40 | id: composer-cache
41 | run: echo "::set-output name=dir::$(composer config cache-files-dir)"
42 | - name: Cache Composer dependencies
43 | uses: actions/cache@v1
44 | with:
45 | path: ${{ steps.composer-cache.outputs.dir }}
46 | key: ${{ matrix.os }}-composer-${{ hashFiles('**/composer.json') }}
47 | restore-keys: ${{ matrix.os }}-composer-
48 | - name: Install dependencies
49 | run: |
50 | composer install --no-interaction
51 | - name: Run tests
52 | run: |
53 | ./vendor/bin/phpunit --coverage-clover coverage.xml
54 | env:
55 | MONGO_HOST: 0.0.0.0
56 | - uses: codecov/codecov-action@v1
57 | with:
58 | token: ${{ secrets.CODECOV_TOKEN }}
59 | fail_ci_if_error: false
60 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .DS_Store
3 | vendor/
4 | storage/
5 | bootstrap/
6 | .idea
7 | .phpunit.result.cache
8 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | build:
2 | environment:
3 | php:
4 | version: 7.4
5 | memcached: true
6 | mongodb: true
7 |
8 | nodes:
9 | my-node:
10 | services:
11 | # For available tags, see https://hub.docker.com/_/mongo/
12 | mongo: 4
13 | analysis:
14 | project_setup:
15 | override: true
16 | tests:
17 | override:
18 | - php-scrutinizer-run
19 | - command: 'vendor/bin/phpunit --dump-xdebug-filter xdebug-filter.php'
20 | checks:
21 |
22 | php:
23 | remove_extra_empty_lines: true
24 | remove_php_closing_tag: true
25 | remove_trailing_whitespace: true
26 |
27 | fix_use_statements:
28 | remove_unused: true
29 | preserve_multiple: false
30 | preserve_blanklines: true
31 | order_alphabetically: true
32 |
33 | fix_php_opening_tag: true
34 | fix_linefeed: true
35 | fix_line_ending: true
36 | fix_identation_4spaces: true
37 | fix_doc_comments: true
38 |
39 | coding_style:
40 | php:
41 | spaces:
42 | before_parentheses:
43 | closure_definition: true
44 | other:
45 | after_type_cast: false
46 |
--------------------------------------------------------------------------------
/.styleci.yml:
--------------------------------------------------------------------------------
1 | preset: laravel
2 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Awesome! How do I contribute?
2 | Contributions are welcome, and are accepted via pull requests. Please review these guidelines before submitting any pull requests.
3 |
4 | ## Guidelines
5 | - Please follow the [PSR-2 Coding Standard](https://www.php-fig.org/psr/psr-2/) and [PHP-FIG Naming Conventions](https://www.php-fig.org/bylaws/psr-naming-conventions/).
6 |
7 | - Ensure that the current tests pass, and if you've added something new, add the tests where relevant.
8 |
9 | - Remember that we follow [SemVer](https://semver.org/). If you are changing the behaviour, or the public api, you may need to update the docs.
10 |
11 | - Send a coherent commit history, making sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History) them before submitting.
12 |
13 | - You may also need to [rebase](https://git-scm.com/book/en/v2/Git-Branching-Rebasing) to avoid merge conflicts.
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG PHP_VERSION=7.2
2 | ARG COMPOSER_VERSION=1.8
3 |
4 | FROM composer:${COMPOSER_VERSION}
5 | FROM php:${PHP_VERSION}-cli
6 |
7 | RUN apt-get update && \
8 | apt-get install -y autoconf pkg-config libssl-dev git libzip-dev zlib1g-dev && \
9 | pecl install mongodb && docker-php-ext-enable mongodb && \
10 | pecl install xdebug && docker-php-ext-enable xdebug && \
11 | docker-php-ext-install -j$(nproc) pdo_mysql zip
12 |
13 | COPY --from=composer /usr/bin/composer /usr/local/bin/composer
14 |
15 | WORKDIR /code
16 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Offline Agency
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Laravel MongoDB Relationships
2 | [](https://packagist.org/packages/offline-agency/laravel-mongo-auto-sync)
3 | [](https://packagist.org/packages/offline-agency/laravel-mongo-auto-sync)
4 | [](https://github.com/offline-agency/laravel-mongo-auto-sync/actions/workflows/build-ci.yml)
5 | [](LICENSE.md)
6 | [](https://scrutinizer-ci.com/g/offline-agency/laravel-mongo-auto-sync)
7 | [](https://styleci.io/repos/167277388)
8 | [](https://codecov.io/gh/offline-agency/laravel-mongo-auto-sync)
9 |
10 | This package provides a better support for [MongoDB](https://www.mongodb.com) relationships in [Laravel](https://laravel.com/) Projects.
11 | At low level all CRUD operations has been handled by [jenssegers/laravel-mongodb](https://github.com/jenssegers/laravel-mongodb)
12 |
13 | ## Installation
14 |
15 | ```bash
16 | composer require offline-agency/laravel-mongo-auto-sync
17 | ```
18 |
19 | ### Prerequisites
20 | Make sure you have the MongoDB PHP driver installed. You can find installation instructions at [http://php.net/manual/en/mongodb.installation.php](http://php.net/manual/en/mongodb.installation.php)
21 |
22 | ### Package version Compatibility
23 |
24 | | This package | Laravel | Laravel MongoDB |
25 | |--------------|---------|-----------------|
26 | | 1.x | 5.8.x | 3.5.x |
27 | | 1.x | 6.x | 3.6.x |
28 | | 2.x | 5.8.x | 3.5.x |
29 | | 2.x | 6.x | 3.6.x |
30 | | 2.x | 7.x | 3.7.x |
31 | | 2.x | 8.x | 3.8.x |
32 | | 2.x | 9.x | 3.9.x |
33 | | 3.x | 5.8.x | 3.5.x |
34 | | 3.x | 6.x | 3.6.x |
35 | | 3.x | 7.x | 3.7.x |
36 | | 3.x | 8.x | 3.8.x |
37 | | 3.x | 9.x | 3.9.x |
38 |
39 | ### PHP Version Compatibility
40 | - Version 1: PHP 7.1, 7.2, 7.3
41 | - Version 2: PHP 7.4
42 | - Version 3: PHP 7.4-8.1
43 |
44 | ## Features
45 | - Sync changes between collection with relationships after CRUD operations
46 | - EmbedsOne & EmbedsMany
47 |
48 | #### Example without our package
49 |
50 | ``` php
51 | //create a new Article with title "Game of Thrones" with Category "TV Series"
52 | //assign data to $article
53 | $article->save();
54 | /*
55 | Article::class {
56 | 'title' => 'Game of Thrones',
57 | 'category' => Category::class {
58 | 'name' => 'TV Series'
59 | }
60 | }
61 | */
62 |
63 | //Retrieve 'TV Series' category
64 | $category = Category::where('name', 'TV Series')->first();
65 | /*
66 | Category::class {
67 | 'name' => 'Game of Thrones',
68 | 'articles' => null
69 | }
70 | */
71 | ```
72 |
73 | The sub document article has not been updated with the new article. So you will need some extra code to write in order to see the new article it in the category page. The number of sync depends on the number of the relationships and on the number of the entry in every single EmbedsMany relationships.
74 |
75 | Total updates = ∑ (entry in all EmbedsMany relationships) + ∑ (EmbedsOne relationships)
76 |
77 | As you can see the lines of extra code can rapidly increase, and you will write many redundant code.
78 |
79 | #### Example with our package
80 |
81 | ``` php
82 | //create a new Article with title "Game of Thrones" with Category "TV Series"
83 | $article->storeWithSync($request);
84 | /*
85 | Article::class {
86 | 'title' => 'Game of Thrones',
87 | 'category' => Category::class {
88 | 'name' => 'TV Series'
89 | }
90 | }
91 | */
92 | //Retrieve 'TV Series' category
93 | $category = Category::where('name', 'TV Series')->first();
94 | /*
95 | Category::class {
96 | 'name' => 'Game of Thrones',
97 | 'articles' => Article::class {
98 | 'title' => 'Game of Thrones'
99 | }
100 | }
101 | */
102 | ```
103 | The sub document article has been updated with the new article, with no need of extra code :tada:
104 |
105 | You can see the new article on the category page because the package synchronizes the information for you by reading the Model Setup.
106 |
107 | **These example can be applied for all write operations on the database.**
108 | - Referenced sub documents [TO DO]
109 | - Handle sub document as Model in order to exploit Laravel ORM support during write operation (without sync feature) [TO BE TEST]
110 | - Handle referenced sub document as Model in order to exploit Laravel ORM support during write operation (without sync feature) [TO DO]
111 | - Advance cast field support
112 |
113 | ## Use cases
114 | - Blog: see demo [here](https://github.com/offline-agency/laravel-mongodb-blog)
115 | - Ecommerce
116 | - API System for mobile application o for generated static site
117 | - Any projects that require fast read operations and (slow) write operations that can be run on background
118 |
119 | ## Documentation
120 | You can find the documentation [here](https://docs.offlineagency.com/laravel-mongo-auto-sync/)
121 |
122 | ## Testing
123 |
124 | Run this command inside your project's route
125 | ``` bash
126 | docker-compose up
127 | ```
128 |
129 | Now run the tests with:
130 | ``` bash
131 | composer test
132 | ```
133 |
134 | ## Roadmap :rocket:
135 | - Refactor target synchronization to Observer pattern, so all this operation can be run on background using [Laravel Queue System](https://laravel.com/docs/5.8/queues). This will also speed up all the operations in the collection that is primary involved in write operations.
136 | - Command Analyse Database: This command will analyse the database in order to find some relationship error.
137 | Ex: An article with a category associated that is not present on the Category's sub document.
138 | - Refactor **save()** method in order to handle CRUD operation on relationship also without sync.
139 | - Support for [referenced relationships](https://docs.mongodb.com/manual/tutorial/model-referenced-one-to-many-relationships-between-documents/).
140 | - Better support for all field types.
141 | - DestroyWithSync() without delete sub documents on other collections.
142 | - Add more tests.
143 | - Nested relationships.
144 | - Benchmark MongoDB vs Mysql (write and read operation).
145 | - Fix typo errors.
146 |
147 | ## Contributing
148 | Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
149 |
150 | ## Security
151 | If you discover any security-related issues, please email support@offlineagency.com instead of using the issue tracker.
152 |
153 |
154 |
155 | ## Credits
156 | - [Giacomo Fabbian](https://github.com/Giacomo92)
157 |
158 | - [All Contributors](https://github.com/offline-agency/laravel-mongo-auto-sync/graphs/contributors)
159 |
160 | ## About us
161 | Offline Agency is a web design agency based in Padua, Italy. You'll find an overview of our projects [on our website](https://offlineagency.it/#home).
162 |
163 | ## License
164 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
165 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "offline-agency/laravel-mongo-auto-sync",
3 | "description": "This package provides a better support for MongoDB relationships in Laravel Projects.",
4 | "type": "library",
5 | "keywords": ["laravel","database","mongodb","eloquent", "relationships"],
6 | "require": {
7 | "php": ">=7.4",
8 | "ext-json": "*",
9 | "ext-mongodb": "*",
10 | "illuminate/support": "^5.0|^6.0|^7.0|^8.0",
11 | "illuminate/container": "^5.0|^6.0|^7.0|^8.0",
12 | "illuminate/database": "^5.0|^6.0|^7.0|^8.0",
13 | "illuminate/events": "^5.0|^6.0|^7.0|^8.0",
14 | "jenssegers/mongodb": "^3.6|^3.7|^3.8"
15 | },
16 | "require-dev": {
17 | "orchestra/testbench": "^3.0|^4.0|^5.0|^6.0",
18 | "phpunit/phpcov": "^7.0|^8.0",
19 | "phpunit/phpunit": "^5.0|^6.0|^7.0|^8.0|^9.0"
20 | },
21 | "license": "MIT",
22 | "authors": [
23 | {
24 | "name": "Offline Agency",
25 | "email": "info@offlineagency.it"
26 | }
27 | ],
28 | "autoload": {
29 | "psr-4": {
30 | "OfflineAgency\\MongoAutoSync\\": "src/"
31 | },
32 | "files": [
33 | "src/syncUtils.php"
34 | ]
35 | },
36 | "autoload-dev": {
37 | "psr-4": {
38 | "Tests\\": "tests/"
39 | },
40 | "files": [
41 | "src/syncUtils.php"
42 | ]
43 | },
44 | "scripts": {
45 | "test": "vendor/bin/phpunit"
46 | },
47 | "config": {
48 | "preferred-install": "dist",
49 | "sort-packages": true,
50 | "optimize-autoloader": true
51 | },
52 | "extra": {
53 | "laravel": {
54 | "providers": [
55 | "OfflineAgency\\MongoAutoSync\\MongoAutoSyncServiceProvider"
56 | ]
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/config/laravel-mongo-auto-sync.php:
--------------------------------------------------------------------------------
1 | app_path().'/Models',
5 | 'model_namespace' => 'App\Models',
6 | 'other_models' => [
7 | 'user' => [
8 | 'model_path' => app_path(),
9 | 'model_namespace' => 'App',
10 | ],
11 | ],
12 | ];
13 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 |
3 | services:
4 | tests:
5 | container_name: tests
6 | build:
7 | context: .
8 | dockerfile: Dockerfile
9 | volumes:
10 | - .:/code
11 | working_dir: /code
12 | depends_on:
13 | - mongodb
14 | mongodb:
15 | container_name: mongodb_
16 | image: mongo
17 | ports:
18 | - 27017:27017
19 | logging:
20 | driver: none
21 |
--------------------------------------------------------------------------------
/phpcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Coding standard for Laravel package boilerplate.
4 | src
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/phpstan.neon:
--------------------------------------------------------------------------------
1 | parameters:
2 | level: 7
3 | paths: ['src/']
4 | autoload_files:
5 | - vendor/autoload.php
6 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 | ./tests
14 |
15 |
16 |
17 |
18 | ./src
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/Console/DropCollection.php:
--------------------------------------------------------------------------------
1 | argument('collection_name');
44 |
45 | $modelPath = $this->getModelPathByName($collection_name);
46 |
47 | $model = $this->getModel($modelPath);
48 |
49 | if (! is_null($model)) {
50 | $model = $model->all();
51 |
52 | $count = $model->count();
53 | $bar = $this->output->createProgressBar($count);
54 |
55 | if ($count > 0) {
56 | for ($i = 0; $i <= $count - 1; $i++) {
57 | $bar->advance();
58 | $model[$i]->destroyWithSync();
59 | $this->line($i + 1 .') Destroy item document with id #'.$model[$i]->getId());
60 | }
61 | } else {
62 | $this->warn('No record found on collection '.strtolower($collection_name));
63 | }
64 | } else {
65 | $this->error('Error Model not found \n');
66 | }
67 | }
68 |
69 | /**
70 | * @param $collection_name
71 | * @return string
72 | *
73 | * @throws Exception
74 | */
75 | public function getModelPathByName($collection_name)
76 | {
77 | $path = config('laravel-mongo-auto-sync.model_path');
78 |
79 | return $this->checkOaModels($path, $collection_name);
80 | }
81 |
82 | /**
83 | * @param $path
84 | * @param $collection_name
85 | * @return string
86 | *
87 | * @throws Exception
88 | */
89 | public function checkOaModels($path, $collection_name)
90 | {
91 | $out = '';
92 |
93 | try {
94 | $results = scandir($path);
95 | } catch (Exception $e) {
96 | throw new Exception('Error directory '.config('laravel-mongo-auto-sync.model_path').' not found');
97 | }
98 |
99 | foreach ($results as $result) {
100 | if ($result === '.' or $result === '..') {
101 | continue;
102 | }
103 | $filename = $path.'/'.$result;
104 | if (is_dir($filename)) {
105 | $out = $this->checkOaModels($filename, $collection_name);
106 | } elseif (strtolower(substr($result, 0, -4)) == strtolower($collection_name)) {
107 | return config('laravel-mongo-auto-sync.model_namespace').'\\'.substr($result, 0, -4);
108 | }
109 | }
110 |
111 | foreach (config('laravel-mongo-auto-sync.other_models') as $key => $values) {
112 | if (strtolower($collection_name) == $key) {
113 | return $values['model_namespace'].'\\'.Str::ucfirst($key);
114 | }
115 | }
116 |
117 | return $out;
118 | }
119 |
120 | /**
121 | * @param string $modelPath
122 | * @return MDModel
123 | *
124 | * @throws Exception
125 | */
126 | private function getModel(string $modelPath)
127 | {
128 | if (class_exists($modelPath)) {
129 | return new $modelPath;
130 | } else {
131 | throw new Exception('Error '.$this->argument('collection_name').' Model not found');
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/src/Console/GenerateModelDocumentation.php:
--------------------------------------------------------------------------------
1 | argument('collection_name');
44 |
45 | $modelPath = $this->getModelPathByName($collection_name);
46 |
47 | $model = $this->getModel($modelPath);
48 |
49 | $items = $model->getItems();
50 | $relations = $model->getMongoRelation();
51 |
52 | $output = "\n\n\n\n/**\n*\n* Plain Fields\n* \n";
53 | $output .= "* @property string \$id\n";
54 |
55 | foreach ($items as $key => $item) {
56 | if (isML($item)) {
57 | $output .= '* @property array $'.$key."\n";
58 | } else {
59 | $output .= '* @property string $'.$key."\n";
60 | }
61 | }
62 |
63 | $output .= "*\n*\n*";
64 |
65 | if (count($relations) > 0) {
66 | $output .= " Relationships\n*\n";
67 | foreach ($relations as $key => $relation) {
68 | $modelTarget = str_replace("App\Models\\", '', $relation['model']);
69 |
70 | $output .= '* @property '.$modelTarget.' $'.$key."\n";
71 | }
72 | $output .= "*\n**/ \n\n\n\n\n";
73 | }
74 |
75 | $this->info($output);
76 | }
77 |
78 | /**
79 | * @param $collection_name
80 | * @return string
81 | *
82 | * @throws Exception
83 | */
84 | public function getModelPathByName($collection_name)
85 | {
86 | $path = config('laravel-mongo-auto-sync.model_path');
87 |
88 | return $this->checkOaModels($path, $collection_name);
89 | }
90 |
91 | /**
92 | * @param $path
93 | * @param $collection_name
94 | * @return string
95 | *
96 | * @throws Exception
97 | */
98 | public function checkOaModels($path, $collection_name)
99 | {
100 | $out = '';
101 |
102 | try {
103 | $results = scandir($path);
104 | } catch (Exception $e) {
105 | throw new Exception('Error directory '.config('laravel-mongo-auto-sync.model_path').' not found');
106 | }
107 |
108 | foreach ($results as $result) {
109 | if ($result === '.' or $result === '..') {
110 | continue;
111 | }
112 | $filename = $path.'/'.$result;
113 | if (is_dir($filename)) {
114 | $out = $this->checkOaModels($filename, $collection_name);
115 | } elseif (strtolower(substr($result, 0, -4)) == strtolower($collection_name)) {
116 | return config('laravel-mongo-auto-sync.model_namespace').'\\'.substr($result, 0, -4);
117 | }
118 | }
119 | foreach (config('laravel-mongo-auto-sync.other_models') as $key => $values) {
120 | if (strtolower($collection_name) == $key) {
121 | return $values['model_namespace'].'\\'.Str::ucfirst($key);
122 | }
123 | }
124 |
125 | return $out;
126 | }
127 |
128 | /**
129 | * @param string $modelPath
130 | * @return MDModel
131 | *
132 | * @throws Exception
133 | */
134 | private function getModel(string $modelPath)
135 | {
136 | if (class_exists($modelPath)) {
137 | return new $modelPath;
138 | } else {
139 | throw new Exception('Error '.$this->argument('collection_name').' Model not found');
140 | }
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/src/Extensions/MongoCollection.php:
--------------------------------------------------------------------------------
1 | filter(function ($col) use ($category, $myslug, $cl) {
15 | if ($col->slug[$cl] === $myslug && $col->status === 'published' && $col->primarycategory->slug[$cl] === $category) {
16 | return true;
17 | } else {
18 | return false;
19 | }
20 | })->first();
21 | if (! $out) {//Handler 404 Object Not Found
22 | $obj_name = get_class($this->first());
23 | $message = __('error.'.$obj_name);
24 | abort(404, $message);
25 | } else {
26 | return $out;
27 | }
28 | }
29 |
30 | /**
31 | * @param null $myslug
32 | * @return mixed
33 | */
34 | public function getBySlug($myslug = null)
35 | {
36 | $cl = cl();
37 | $out = $this->filter(function ($col) use ($myslug, $cl) {
38 | if ($col->slug[$cl] === $myslug) {
39 | return true;
40 | }
41 | })->first();
42 | if (! $out) {//Handler 404 Object Not Found
43 | $obj_name = get_class($this->first());
44 | $message = __('error.'.$obj_name);
45 | abort(404, $message);
46 | } else {
47 | return $out;
48 | }
49 | }
50 |
51 | //Method to retrieve only not deleted item of a collection - Check on is_deleted custom property added on MDMODEL ovverriding init, delete
52 |
53 | /**
54 | * @return MongoCollection
55 | */
56 | public function getNotDeleted()
57 | {
58 | return $this->filter(function ($col) {
59 | if ($col->is_deleted) {
60 | return false;
61 | } else {
62 | return true;
63 | }
64 | });
65 | }
66 |
67 | //Method to retrieve only published item of a collection - Check on status entry
68 |
69 | /**
70 | * @return MongoCollection
71 | */
72 | public function getPublished()
73 | {
74 | return $this->filter(function ($col) {
75 | if ($col->status === 'published') {
76 | return true;
77 | } else {
78 | return false;
79 | }
80 | });
81 | }
82 |
83 | //Method to retrieve only public item of a collection - Check on status entry
84 |
85 | /**
86 | * @return MongoCollection
87 | */
88 | public function getPublic()
89 | {
90 | return $this->filter(function ($col) {
91 | if ($col->visibility === 'public') {
92 | return true;
93 | } else {
94 | return false;
95 | }
96 | });
97 | }
98 |
99 | //Check if the collection has an item with ref_id equal to id of the obj pass in to the parameter, useful to mark a category already selected in edit
100 |
101 | /**
102 | * @param $obj
103 | * @return bool
104 | */
105 | public function hasItem($obj)
106 | {
107 | if (is_null($obj)) {
108 | return false;
109 | } elseif (is_null($obj->id)) {
110 | return false;
111 | }
112 |
113 | $id = $obj->id;
114 |
115 | $out = $this->filter(function ($col) use ($id) {
116 | if ($col->ref_id === $id) {
117 | return true;
118 | } else {
119 | return false;
120 | }
121 | });
122 |
123 | if ($out->count() > 0) {
124 | return true;
125 | } else {
126 | return false;
127 | }
128 | }
129 |
130 | //Move the item with ref_id equal to the parameter, useful for edit primary category
131 |
132 | /**
133 | * @param $id
134 | * @return $this
135 | */
136 | public function moveFirst($id)
137 | {
138 | for ($i = 0; $i <= ($this->count() - 1); $i++) {
139 | $this[$i]->ref_id == $id ? $this->prepend($this->splice($i, 1)[0]) : 0;
140 | }
141 |
142 | return $this;
143 | }
144 |
145 | /**
146 | * @return MongoCollection
147 | */
148 | public function getActive()
149 | {
150 | return $this->filter(function ($col) {
151 | return $col->is_active;
152 | });
153 | }
154 |
155 | /**
156 | * @return bool
157 | */
158 | public function exist()
159 | {
160 | if ($this->count() > 0) {
161 | return true;
162 | } else {
163 | return false;
164 | }
165 | }
166 |
167 | /**
168 | * @param string $aid
169 | * @return mixed
170 | */
171 | public function findByAID(string $aid)
172 | {
173 | return $this->filter(function ($col) use ($aid) {
174 | return $col->autoincrement_id == $aid;
175 | })->first();
176 | }
177 |
178 | /**
179 | * @param $id
180 | * @return bool
181 | */
182 | public function hasPermission($id)
183 | {
184 | if (is_null($id)) {
185 | return false;
186 | }
187 |
188 | $out = $this->filter(function ($col) use ($id) {
189 | if ($col->ref_id == $id) {
190 | return true;
191 | }
192 | });
193 |
194 | if ($out->count() > 0) {
195 | return true;
196 | } else {
197 | return false;
198 | }
199 | }
200 |
201 | /**
202 | * @param $name
203 | * @return bool
204 | */
205 | public function hasRole($name)
206 | {
207 | if (is_null($name)) {
208 | return false;
209 | }
210 |
211 | $out = $this->filter(function ($col) use ($name) {
212 | if ($col->name == $name) {
213 | return true;
214 | }
215 | });
216 |
217 | if ($out->count() > 0) {
218 | return true;
219 | } else {
220 | return false;
221 | }
222 | }
223 |
224 | /**
225 | * @param $name
226 | * @return bool
227 | */
228 | public function checkPermission($name)
229 | {
230 | if (is_null($name)) {
231 | return false;
232 | }
233 |
234 | $out = $this->filter(function ($col) use ($name) {
235 | if ($col->name == $name) {
236 | return true;
237 | }
238 | });
239 |
240 | if ($out->count() > 0) {
241 | return true;
242 | } else {
243 | return false;
244 | }
245 | }
246 | }
247 |
--------------------------------------------------------------------------------
/src/Http/Models/DefaultGeo.php:
--------------------------------------------------------------------------------
1 | id;
29 | }
30 |
31 | /**
32 | * @return string
33 | */
34 | public function getCollection()
35 | {
36 | return $this->collection;
37 | }
38 |
39 | /**
40 | * @param int $size
41 | * @return mixed
42 | */
43 | public function getRandom($size = 3)
44 | {
45 | return $this->all()->random($size);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Http/Models/MSModel.php:
--------------------------------------------------------------------------------
1 | app->bind('command.model-doc:generate', GenerateModelDocumentation::class);
22 | $this->app->bind('command.drop:collection', DropCollection::class);
23 |
24 | $this->commands([
25 | 'command.model-doc:generate',
26 | ]);
27 |
28 | $this->commands([
29 | 'command.drop:collection',
30 | ]);
31 | }
32 |
33 | /**
34 | * Register the application services.
35 | *
36 | * @return void
37 | */
38 | public function register()
39 | {
40 | $this->mergeConfigFrom(
41 | $this->packagePath('config/laravel-mongo-auto-sync.php'),
42 | 'laravel-mongo-auto-sync'
43 | );
44 | }
45 |
46 | /**
47 | * @param $path
48 | * @return string
49 | */
50 | private function packagePath($path)
51 | {
52 | return __DIR__.'/../'.$path;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Traits/Helper.php:
--------------------------------------------------------------------------------
1 | validateOptions($options);
19 |
20 | return $this->getFieldTypeOptionsValue($options, 'is-array', 'boolean');
21 | }
22 |
23 | /**
24 | * @param $options
25 | * @return bool|mixed
26 | *
27 | * @throws Exception
28 | */
29 | public function isCarbonDate($options)
30 | {
31 | $this->validateOptions($options);
32 |
33 | return $this->getFieldTypeOptionsValue($options, 'is-carbon-date', 'boolean');
34 | }
35 |
36 | /**
37 | * @param $options
38 | *
39 | * @throws Exception
40 | */
41 | private function validateOptions($options)
42 | {
43 | if (gettype($options) !== 'array') {
44 | throw new Exception($options.' is not a valid array!');
45 | }
46 | }
47 |
48 | /**
49 | * @param $value
50 | * @param string $expected
51 | *
52 | * @throws Exception
53 | */
54 | private function validateOptionValue($value, string $expected)
55 | {
56 | if (gettype($value) !== $expected) {
57 | throw new Exception($value.' is not a valid '.$expected.' found '.gettype($value).'! Check on your model configurations.');
58 | }
59 | }
60 |
61 | /**
62 | * @param array $options
63 | * @param string $key
64 | * @param string $expected
65 | * @return bool|mixed
66 | *
67 | * @throws Exception
68 | */
69 | private function getFieldTypeOptionsValue(array $options, string $key, string $expected)
70 | {
71 | if (Arr::has($options, $key)) {
72 | $value = Arr::get($options, $key);
73 | $this->validateOptionValue($value, $expected);
74 |
75 | return $value;
76 | } else {
77 | return false;
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/Traits/MainMongoTrait.php:
--------------------------------------------------------------------------------
1 | initDataForSync($request, $additionalData, $options, $target_additional_data);
31 | $this->storeEditAllItems($request, 'add', $options);
32 | $this->processAllRelationships($request, 'add', '', '', $options);
33 |
34 | //Dispatch the creation event
35 | $this->fireModelEvent('storeWithSync');
36 |
37 | return $this->fresh();
38 | }
39 |
40 | /**
41 | * @param Request $request
42 | * @param array $additionalData
43 | * @param array $options
44 | * @param array $target_additional_data
45 | * @return $this
46 | *
47 | * @throws Exception
48 | */
49 | public function updateWithSync(Request $request, array $additionalData = [], array $options = [], array $target_additional_data = [])
50 | {
51 | $this->initDataForSync($request, $additionalData, $options, $target_additional_data);
52 | $this->storeEditAllItems($request, 'update', $options);
53 | $this->processAllRelationships($request, 'update', '', '', $options);
54 |
55 | //Dispatch the update event
56 | $this->fireModelEvent('updateWithSync');
57 |
58 | return $this->fresh();
59 | }
60 |
61 | /**
62 | * @return $this
63 | */
64 | public function destroyWithSync()
65 | {
66 | //Get the relation info
67 | $relations = $this->getMongoRelation();
68 | //Process all relationships
69 | foreach ($relations as $method => $relation) {
70 | //Get Relation Save Mode
71 | $type = $relation['type'];
72 | $hasTarget = hasTarget($relation);
73 | if ($hasTarget) {
74 | $modelTarget = $relation['modelTarget'];
75 | $methodOnTarget = $relation['methodOnTarget'];
76 | $modelOnTarget = $relation['modelOnTarget'];
77 | $is_EO = is_EO($type);
78 | $is_EM = is_EM($type);
79 | $is_HO = is_HO($type);
80 | $is_HM = is_HM($type);
81 | $typeOnTarget = getTypeOnTarget($relation);
82 | $is_EM_target = is_EM($typeOnTarget);
83 | $is_EO_target = is_EO($typeOnTarget);
84 | if ($is_EO || $is_EM) {//EmbedsOne Create - EmbedsMany Create
85 | //Delete EmbedsMany or EmbedsOne on Target
86 | $this->deleteTargetObj($method, $modelTarget, $methodOnTarget, $is_EO, $is_EM, $is_EO_target, $is_EM_target);
87 | }
88 | //TODO: Need to be implemented
89 | /* elseif ($is_HM) {//HasMany
90 | } elseif ($is_HO) {//HasOne Create
91 | }*/
92 | }
93 | }
94 | //Delete current object
95 | $this->delete();
96 | //Dispatch the destroy event
97 | $this->fireModelEvent('destroyWithSync');
98 |
99 | return $this;
100 | }
101 |
102 | /**
103 | * @param array $options
104 | * @param string $key
105 | * @return bool|mixed
106 | */
107 | private function getOptionValue(array $options, string $key)
108 | {
109 | return Arr::has($options, $key) ? $options[$key] : '';
110 | }
111 |
112 | /**
113 | * @param $obj
114 | * @param string $EOkey
115 | * @param string $method
116 | * @param string $model
117 | *
118 | * @throws Exception
119 | */
120 | public function checkPropertyExistence($obj, string $EOkey, $method = '', $model = '')
121 | {
122 | if (! property_exists($obj, $EOkey)) {
123 | $msg = 'Error - '.$EOkey.' attribute not found on obj '.json_encode($obj).' during save of model: '.$model.' and attribute: '.$method;
124 | throw new Exception($msg);
125 | }
126 | }
127 |
128 | /**
129 | * @param $arr
130 | * @param string $key
131 | *
132 | * @throws Exception
133 | */
134 | public function checkArrayExistence($arr, string $key)
135 | {
136 | if (! Arr::has($arr, $key)) {
137 | $msg = ('Error - '.$key.' attribute not found on obj '.json_encode($arr));
138 | throw new Exception($msg);
139 | }
140 | }
141 |
142 | /**
143 | * @param Request $request
144 | * @param string $key
145 | *
146 | * @throws Exception
147 | */
148 | private function checkRequestExistence(Request $request, string $key)
149 | {
150 | if (! $request->has($key)) {
151 | $msg = ('Error - '.$key.' attribute not found in Request '.json_encode($request->all()));
152 | throw new Exception($msg);
153 | }
154 | }
155 |
156 | /**
157 | * @param bool $request_has_key
158 | * @param bool $hasTarget
159 | * @return bool
160 | */
161 | public function getIsSkippable($request_has_key, $hasTarget = false)
162 | {
163 | return ! $request_has_key && $this->getHasPartialRequest() && ! $hasTarget;
164 | }
165 |
166 | /**
167 | * @return bool
168 | */
169 | public function getHasPartialRequest()
170 | {
171 | return $this->has_partial_request;
172 | }
173 |
174 | public function setHasPartialRequest(): void
175 | {
176 | $this->has_partial_request = $this->getOptionValue(
177 | $this->getOptions(),
178 | 'request_type'
179 | ) == 'partial';
180 | }
181 |
182 | /**
183 | * @param string $modelTarget
184 | * @param stdClass $obj
185 | * @return MDModel|null
186 | *
187 | * @throws Exception
188 | */
189 | private function getModelTobeSync(string $modelTarget, stdClass $obj)
190 | {
191 | $this->checkPropertyExistence($obj, 'ref_id');
192 | $target_id = $obj->ref_id;
193 |
194 | //Init the Target Model
195 | $modelToBeSync = new $modelTarget;
196 |
197 | return $modelToBeSync->find($target_id);
198 | }
199 |
200 | /**
201 | * @param string $key
202 | * @param Request $request
203 | * @return mixed
204 | *
205 | * @throws Exception
206 | */
207 | private function getRelationshipRequest(string $key, Request $request)
208 | {
209 | $this->checkRequestExistence(
210 | $request,
211 | $key
212 | );
213 |
214 | return $request->input($key);
215 | }
216 |
217 | /**
218 | * @return Request
219 | */
220 | public function getRequest()
221 | {
222 | return $this->request;
223 | }
224 |
225 | /**
226 | * @param Request $request
227 | * @param array $additionalData
228 | */
229 | public function setRequest(Request $request, array $additionalData): void
230 | {
231 | $request = $request->merge($additionalData);
232 | $this->request = $request;
233 | }
234 |
235 | /**
236 | * @return Request
237 | */
238 | public function getPartialGeneratedRequest()
239 | {
240 | return $this->partial_generated_request;
241 | }
242 |
243 | /**
244 | * @param array $arr
245 | */
246 | public function setPartialGeneratedRequest(array $arr): void
247 | {
248 | $partial_generated_request = new Request;
249 | $partial_generated_request->merge($arr);
250 |
251 | $this->partial_generated_request = $partial_generated_request;
252 | }
253 |
254 | /**
255 | * @return array
256 | */
257 | public function getOptions()
258 | {
259 | return $this->options;
260 | }
261 |
262 | /**
263 | * @param array $options
264 | */
265 | public function setOptions(array $options): void
266 | {
267 | $this->options = $options;
268 | }
269 |
270 | /**
271 | * @return array
272 | */
273 | public function getTargetAdditionalData()
274 | {
275 | return $this->target_additional_data;
276 | }
277 |
278 | /**
279 | * @param array $target_additional_data
280 | */
281 | public function setTargetAdditionalData($target_additional_data): void
282 | {
283 | $this->target_additional_data = $target_additional_data;
284 | }
285 |
286 | /**
287 | * @param Request $request
288 | * @param array $additionalData
289 | * @param array $options
290 | * @param array $target_additional_data
291 | */
292 | public function initDataForSync(Request $request, array $additionalData, array $options, array $target_additional_data)
293 | {
294 | $this->setRequest($request, $additionalData);
295 | $this->setTargetAdditionalData($target_additional_data);
296 | $this->setOptions($options);
297 | $this->setHasPartialRequest();
298 | }
299 | }
300 |
--------------------------------------------------------------------------------
/src/Traits/ModelAdditionalMethod.php:
--------------------------------------------------------------------------------
1 | items;
28 | }
29 |
30 | /**
31 | * @return array
32 | */
33 | public function getMongoRelation(): array
34 | {
35 | if (! empty($this->mongoRelation)) {
36 | return $this->mongoRelation;
37 | } else {
38 | return [];
39 | }
40 | }
41 |
42 | /**
43 | * @return void
44 | *
45 | * @throws Exception
46 | */
47 | public function setMiniModels()
48 | {
49 | $miniModelList = $this->getUniqueMiniModelList();
50 | $this->mini_models = $this->populateMiniModels($miniModelList);
51 | }
52 |
53 | /**
54 | * @return array
55 | */
56 | public function getMiniModels()
57 | {
58 | return $this->mini_models;
59 | }
60 |
61 | /**
62 | * @return array
63 | *
64 | * @throws Exception
65 | */
66 | public function getUniqueMiniModelList()
67 | {
68 | $relationships = $this->getMongoRelation();
69 |
70 | $models = [];
71 | $embedded_object = [];
72 |
73 | foreach ($relationships as $method => $relationship) {
74 | $hasTarget = hasTarget($relationship);
75 | if ($hasTarget) {
76 | $relationshipsContainsTarget = Arr::has($relationship, 'modelOnTarget');
77 | if ($relationshipsContainsTarget) {
78 | $models[] = Arr::get($relationship, 'modelOnTarget');
79 | $embedded_object[$method] = $this->getObjWithRefId($method, $relationship);
80 | } else {
81 | throw new Exception('modelOnTarget not found on relationship '.$method.' array. Check your Model configuration '.get_class($this));
82 | }
83 | }
84 | }
85 | $this->setPartialGeneratedRequest($embedded_object);
86 |
87 | return collect($models)->unique()->toArray();
88 | }
89 |
90 | /**
91 | * @param array $miniModelList
92 | * @return mixed
93 | *
94 | * @throws Exception
95 | */
96 | public function populateMiniModels(array $miniModelList)
97 | {
98 | $miniModels = [];
99 | foreach ($miniModelList as $miniModel) {
100 | $miniModels[$miniModel] = $this->getFreshMiniModel($miniModel);
101 | }
102 |
103 | return $miniModels;
104 | }
105 |
106 | /**
107 | * @param string $mini_model_path
108 | * @return MDModel
109 | *
110 | * @throws Exception
111 | */
112 | public function getFreshMiniModel(string $mini_model_path)
113 | {
114 | $embededModel = $this->getModelInstanceFromPath($mini_model_path);
115 | $items = $embededModel->getItems();
116 | foreach ($items as $key => $item) {
117 | $embededModel->$key = $this->castValueToBeSaved($key, $item, $mini_model_path);
118 | }
119 |
120 | return $embededModel;
121 | }
122 |
123 | /**
124 | * @param string $key
125 | * @param $item
126 | * @param string $mini_model_path
127 | * @return array|mixed|UTCDateTime|null
128 | *
129 | * @throws Exception
130 | */
131 | public function castValueToBeSaved(string $key, $item, string $mini_model_path)
132 | {
133 | $is_ML = isML($item);
134 | $is_MD = isMD($item);
135 | $is_array = $this->isArray($item);
136 | $is_carbon_date = $this->isCarbonDate($item);
137 |
138 | $value = $this->getObjValueToBeSaved($key, $mini_model_path);
139 | if ($is_ML) {
140 | return is_array($value) ? $value : ml([], $value);
141 | } elseif ($is_MD) {
142 | if ($value instanceof UTCDateTime) {
143 | return $value;
144 | }
145 |
146 | if ($value == '') {
147 | return null;
148 | }
149 |
150 | return new UTCDateTime(new DateTime($value));
151 | } elseif ($is_carbon_date) {
152 | if ($value == '') {
153 | return new UTCDateTime();
154 | }
155 |
156 | return new UTCDateTime($value);
157 | } elseif ($is_array) {
158 | return is_null($value) ? [] : (is_array($value) ? $value : $value->getAttributes());
159 | } else {
160 | return $value;
161 | }
162 | }
163 |
164 | /**
165 | * @param string $mini_model_path
166 | * @return MDModel
167 | */
168 | public function getModelInstanceFromPath(string $mini_model_path)
169 | {
170 | return new $mini_model_path;
171 | }
172 |
173 | /**
174 | * @param string $key
175 | * @param string $mini_model_path
176 | * @param bool $rewrite_ref_id_key
177 | * @return mixed
178 | */
179 | public function getObjValueToBeSaved(string $key, string $mini_model_path, $rewrite_ref_id_key = true)
180 | {
181 | $key = $key === 'ref_id' && $rewrite_ref_id_key ? '_id' : $key;
182 | $target_additional_data = $this->getTargetAdditionalData();
183 | $request = $this->getRequest();
184 |
185 | $db_value = $this->getDbValue($key);
186 |
187 | return Arr::has($target_additional_data, $mini_model_path.'.'.$key) ? Arr::get($target_additional_data, $mini_model_path.'.'.$key) : // Search on target_additional_data [] 4th parameter of updateWithSync() / storeWithSync()
188 | ($request->has($key) ? $request->input($key) : $db_value); // Search on Main Request 1st parameter of updateWithSync() / storeWithSync() or directly on database
189 | //TODO: Add default value from Item Model
190 | }
191 |
192 | /**
193 | * @param string $key
194 | * @return mixed
195 | */
196 | private function getDbValue(string $key)
197 | {
198 | return $this->$key;
199 | }
200 |
201 | /**
202 | * @param string $key
203 | * @return array
204 | *
205 | * @throws Exception
206 | */
207 | public function getEmbedModel(string $key)
208 | {
209 | $embedModels = $this->getMiniModels();
210 |
211 | if (Arr::has($embedModels, $key)) {
212 | return Arr::get($embedModels, $key);
213 | } else {
214 | throw new Exception('I cannot find an embedded model with key: '.$key.'. Check on your model configuration');
215 | }
216 | }
217 |
218 | /**
219 | * @param string $method
220 | * @param array $relationship
221 | * @return false|string
222 | *
223 | * @throws Exception
224 | */
225 | public function getObjWithRefId(string $method, array $relationship)
226 | {
227 | $objs = [];
228 | $type = $relationship['type'];
229 |
230 | $is_EO = is_EO($type);
231 | $is_EM = is_EM($type);
232 |
233 | if ($is_EO) {
234 | $objs[] = $this->getObjValueToBeSaved($method, '', false);
235 | } elseif ($is_EM) {
236 | if (! is_null($this->$method) > 0) {
237 | foreach ($this->$method as $value) {
238 | $obj = new stdClass;
239 | $obj->ref_id = $value->ref_id;
240 | $objs[] = $obj;
241 | }
242 | }
243 | } else {
244 | throw new Exception('Relationship '.$method.' type '.$type.' is not valid! Possible values are: EmbedsMany and EmbedsOne');
245 | }
246 |
247 | return json_encode($objs);
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/src/Traits/PlainMongoTrait.php:
--------------------------------------------------------------------------------
1 | getItems();
23 |
24 | //Current Obj Create
25 | foreach ($items as $key => $item) {
26 | $is_ML = isML($item);
27 | $is_MD = isMD($item);
28 |
29 | $is_fillable = isFillable($item, $event);
30 | $is_skippable = $this->getIsSkippable($request->has($key));
31 |
32 | if ($is_skippable) {
33 | continue;
34 | } else {
35 | $this->checkRequestExistence(
36 | $request,
37 | $key
38 | );
39 | }
40 |
41 | if ($is_fillable) {
42 | if ($is_ML) {
43 | if (is_null($this->$key)) {
44 | $old_value = [];
45 | } else {
46 | $old_value = $this->$key;
47 | }
48 | $this->$key = ml($old_value, $request->input($key));
49 | } elseif ($is_MD) {
50 | if ($request->input($key) == '' || $request->input($key) == null) {
51 | $this->$key = null;
52 | } else {
53 | $this->$key = new UTCDateTime(new DateTime($request->input($key)));
54 | }
55 | } else {
56 | $this->$key = $request->input($key);
57 | }
58 | }
59 | }
60 |
61 | $this->save();
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Traits/RelationshipMongoTrait.php:
--------------------------------------------------------------------------------
1 | setIsPartialRequest($options);
27 | $this->setMiniModels(); // For target Sync
28 |
29 | //Get the relation info
30 | $relations = $this->getMongoRelation();
31 |
32 | //Process all relationships
33 | foreach ($relations as $method => $relation) {
34 | //Get Relation Save Mode
35 | $type = $relation['type'];
36 | $model = $relation['model'];
37 | $hasTarget = hasTarget($relation);
38 | if ($hasTarget) {
39 | $modelTarget = $relation['modelTarget'];
40 | $methodOnTarget = $relation['methodOnTarget'];
41 | $modelOnTarget = $relation['modelOnTarget'];
42 | $typeOnTarget = getTypeOnTarget($relation);
43 | } else {
44 | $modelTarget = '';
45 | $methodOnTarget = '';
46 | $modelOnTarget = '';
47 | $typeOnTarget = '';
48 | }
49 |
50 | $is_EO = is_EO($type);
51 | $is_EM = is_EM($type);
52 |
53 | $is_EM_target = is_EM($typeOnTarget);
54 | $is_EO_target = is_EO($typeOnTarget);
55 |
56 | $key = $parent.$method.$counter;
57 | $is_skippable = $this->getIsSkippable($request->has($key), $hasTarget);
58 |
59 | if ($is_skippable) {
60 | continue;
61 | }
62 | $current_request = $request->has($key) ? $request : $this->getPartialGeneratedRequest();
63 |
64 | $value = $this->getRelationshipRequest($key, $current_request);
65 |
66 | $is_embeds_has_to_be_updated = $request->has($key);
67 |
68 | if (! is_null($value) && ! ($value == '') && ! ($value == '[]')) {
69 | $objs = json_decode($value);
70 | } else {
71 | $objs = getArrayWithEmptyObj($model, $is_EO, $is_EM);
72 | }
73 |
74 | if ($is_EO || $is_EM) {//EmbedsOne Create - EmbedsMany Create
75 | if ($event == 'update' && $is_embeds_has_to_be_updated) {
76 | //Delete EmbedsMany or EmbedsOne on Target - TODO: check if it is necessary to run deleteTargetObj method
77 | if ($hasTarget) {
78 | $this->deleteTargetObj($method, $modelTarget, $methodOnTarget, $is_EO, $is_EM, $is_EO_target, $is_EM_target);
79 | }
80 | //Delete EmbedsMany or EmbedsOne on current object
81 | if ($is_EM) {
82 | $this->$method = [];
83 | $this->save();
84 | }
85 | }
86 |
87 | if (! empty($objs)) {
88 | if ($is_EM) {
89 | $this->tempEM = [];
90 | }
91 |
92 | $i = 0;
93 | foreach ($objs as $obj) {
94 | $this->processOneEmbeddedRelationship(
95 | $request,
96 | $obj,
97 | $type,
98 | $model,
99 | $method,
100 | $modelTarget,
101 | $methodOnTarget,
102 | $modelOnTarget, $event,
103 | $hasTarget,
104 | $is_EO,
105 | $is_EM,
106 | $is_EO_target,
107 | $is_EM_target,
108 | $i,
109 | $is_embeds_has_to_be_updated,
110 | $options);
111 | $i++;
112 | }
113 |
114 | if ($is_EM) {
115 | $this->$method = $this->tempEM;
116 | }
117 | } else {
118 | $this->$method = [];
119 | }
120 | $this->save();
121 | }
122 | }
123 | }
124 |
125 | /**
126 | * @param $mini_model
127 | * @param string $method_on_target
128 | * @param bool $is_EO_target
129 | * @param bool $is_EM_target
130 | *
131 | * @throws \Throwable
132 | */
133 | public function updateRelationWithSync($mini_model, string $method_on_target, $is_EO_target, $is_EM_target)
134 | {
135 | if ($is_EM_target) {
136 | $new_values = [];
137 | throw_if(
138 | ! isset($this->$method_on_target),
139 | new Exception(
140 | 'Error during target update. Remember to init the attribute '.$method_on_target.
141 | ' on collection '.$this->getCollection()
142 | )
143 | );
144 |
145 | $is_update_operation = false;
146 |
147 | foreach ($this->$method_on_target as $temp) {
148 | throw_if(
149 | is_array($temp),
150 | new Exception(
151 | 'Error during target update. Remember to declare '.$method_on_target.' as '.
152 | 'EmbedsMany relationship on model '.get_class($this)
153 | )
154 | );
155 |
156 | if (! is_null($temp)) {
157 | if ($this->getIsPartialRequest()) {
158 | if (Arr::get($temp->attributes, 'ref_id') !== Arr::get($mini_model->attributes, 'ref_id')) {
159 | $new_values[] = $temp->attributes;
160 | } else {
161 | $new_values[] = $mini_model->attributes;
162 | $is_update_operation = true;
163 | }
164 | } else {
165 | $new_values[] = $temp->attributes;
166 | }
167 | }
168 | }
169 |
170 | if (! $is_update_operation) {
171 | $new_values[] = $mini_model->attributes;
172 | }
173 | } elseif ($is_EO_target) {
174 | throw_if(
175 | is_array($mini_model),
176 | new Exception(
177 | 'Error during target update. Remember to declare '.$method_on_target.' as '.
178 | 'EmbedOne relationship on model '.get_class($this)
179 | )
180 | );
181 | $new_values = $mini_model->attributes;
182 | }
183 |
184 | $this->$method_on_target = $new_values;
185 | $this->save();
186 | }
187 |
188 | /**
189 | * @param Request $request
190 | * @param $obj
191 | * @param $type
192 | * @param $model
193 | * @param $method
194 | * @param $modelTarget
195 | * @param $methodOnTarget
196 | * @param $modelOnTarget
197 | * @param $event
198 | * @param $hasTarget
199 | * @param bool $is_EO
200 | * @param bool $is_EM
201 | * @param bool $is_EO_target
202 | * @param bool $is_EM_target
203 | * @param $i
204 | * @param bool $is_embeds_has_to_be_updated
205 | * @param $options
206 | *
207 | * @throws Exception
208 | */
209 | public function processOneEmbeddedRelationship(Request $request, $obj, $type, $model, $method, $modelTarget, $methodOnTarget, $modelOnTarget, $event, $hasTarget, $is_EO, $is_EM, $is_EO_target, $is_EM_target, $i, $is_embeds_has_to_be_updated, $options)
210 | {
211 | if ($is_embeds_has_to_be_updated) {
212 | $this->processEmbedOnCurrentCollection($request, $obj, $type, $model, $method, $event, $is_EO, $is_EM, $i, $options);
213 | }
214 |
215 | if ($hasTarget) {
216 | $this->processEmbedOnTargetCollection($modelTarget, $obj, $methodOnTarget, $modelOnTarget, $is_EO_target, $is_EM_target);
217 | }
218 | }
219 |
220 | /**
221 | * @param string $method
222 | * @param string $modelTarget
223 | * @param string $methodOnTarget
224 | * @param bool $is_EO
225 | * @param bool $is_EM
226 | * @param bool $is_EO_target
227 | * @param bool $is_EM_target
228 | */
229 | public function deleteTargetObj($method, $modelTarget, $methodOnTarget, bool $is_EO, bool $is_EM, bool $is_EO_target, bool $is_EM_target)
230 | {
231 | if ($is_EO) {
232 | $embedObj = $this->$method;
233 | if (! is_null($embedObj)) {
234 | $target_id = $embedObj->ref_id;
235 | $this->handleSubTarget($target_id, $modelTarget, $methodOnTarget, $is_EO_target, $is_EM_target);
236 | }
237 | } elseif ($is_EM) {
238 | foreach ($this->$method as $target) {
239 | $this->handleSubTarget($target->ref_id, $modelTarget, $methodOnTarget, $is_EO_target, $is_EM_target);
240 | }
241 | }
242 | }
243 |
244 | /**
245 | * @param string|null $target_id
246 | * @param string $modelTarget
247 | * @param string $methodOnTarget
248 | * @param bool $is_EO_target
249 | * @param bool $is_EM_target
250 | */
251 | public function handleSubTarget(?string $target_id, string $modelTarget, string $methodOnTarget, bool $is_EO_target, bool $is_EM_target)
252 | {
253 | if ($is_EM_target) {
254 | $target = new $modelTarget;
255 | $target = $target->all()->where('id', $target_id)->first();
256 | if (! is_null($target)) {
257 | $new_values = [];
258 | foreach ($target->$methodOnTarget as $temp) {
259 | if ($temp->ref_id !== $this->getId()) {
260 | $new_values[] = $temp->attributes;
261 | }
262 | }
263 | $target->$methodOnTarget = $new_values;
264 | $target->save();
265 | }
266 | } elseif ($is_EO_target) {
267 | //Do nothing because when we are updating we already init the informations
268 | }
269 | }
270 |
271 | /**
272 | * @param Request $request
273 | * @param $obj
274 | * @param $type
275 | * @param $model
276 | * @param $method
277 | * @param $event
278 | * @param $is_EO
279 | * @param $is_EM
280 | * @param $i
281 | * @param $options
282 | *
283 | * @throws Exception
284 | */
285 | private function processEmbedOnCurrentCollection(Request $request, $obj, $type, $model, $method, $event, $is_EO, $is_EM, $i, $options)
286 | {
287 | //Init the embed one model
288 | $embedObj = new $model;
289 |
290 | $EOitems = $embedObj->getItems();
291 | //Current Obj Create
292 | foreach ($EOitems as $EOkey => $item) {
293 | if (! is_null($obj)) {
294 | $is_ML = isML($item);
295 | $is_MD = isMD($item);
296 | $this->checkPropertyExistence($obj, $EOkey, $method, $model);
297 |
298 | if ($is_ML) {
299 | $embedObj->$EOkey = ml([], $obj->$EOkey);
300 | } elseif ($EOkey == 'updated_at' || $EOkey == 'created_at') {
301 | $embedObj->$EOkey = now();
302 | } elseif ($is_MD) {
303 | if ($obj->$EOkey == '' || $obj->$EOkey == null) {
304 | $embedObj->$EOkey = null;
305 | } else {
306 | $embedObj->$EOkey = new UTCDateTime(new DateTime($obj->$EOkey));
307 | }
308 | } else {
309 | $embedObj->$EOkey = $obj->$EOkey;
310 | }
311 | }
312 | }
313 |
314 | //else if($is_EM){//To be implemented}
315 | //else if($is_HM){//To be implemented}
316 | //else if($is_HO){//To be implemented}
317 |
318 | //Get counter for embeds many with level > 1
319 | $counter = getCounterForRelationships($method, $is_EO, $is_EM, $i);
320 | //Check for another Level of Relationship
321 | $embedObj->processAllRelationships($request, $event, $method.'-', $counter, $options);
322 |
323 | if ($is_EO) {
324 | $this->$method = $embedObj->attributes;
325 | } else {
326 | $this->tempEM[] = $embedObj->attributes;
327 | }
328 | }
329 |
330 | /**
331 | * @param $modelTarget
332 | * @param $obj
333 | * @param $methodOnTarget
334 | * @param $modelOnTarget
335 | * @param bool $is_EO_target
336 | * @param bool $is_EM_target
337 | *
338 | * @throws Exception
339 | */
340 | private function processEmbedOnTargetCollection($modelTarget, $obj, $methodOnTarget, $modelOnTarget, bool $is_EO_target, bool $is_EM_target)
341 | {
342 | $modelToBeSync = $this->getModelTobeSync($modelTarget, $obj);
343 | if (! is_null($modelToBeSync)) {
344 | $miniModel = $this->getEmbedModel($modelOnTarget);
345 | $modelToBeSync->setIsPartialRequest([], $this->getIsPartialRequest());
346 | $modelToBeSync->updateRelationWithSync($miniModel, $methodOnTarget, $is_EO_target, $is_EM_target);
347 | //TODO:Sync target on level > 1
348 | //$modelToBeSync->processAllRelationships($request, $event, $methodOnTarget, $methodOnTarget . "-");
349 | }
350 | }
351 |
352 | public function getIsPartialRequest()
353 | {
354 | return $this->is_partial_request;
355 | }
356 |
357 | public function setIsPartialRequest(array $options, $is_partial_request = null): void
358 | {
359 | if (! is_null($is_partial_request)) {
360 | $this->is_partial_request = $is_partial_request;
361 |
362 | return;
363 | }
364 |
365 | if (Arr::has($options, 'request_type')) {
366 | $this->is_partial_request = Arr::get($options, 'request_type') == 'partial';
367 |
368 | return;
369 | }
370 |
371 | $this->is_partial_request = false;
372 | }
373 | }
374 |
--------------------------------------------------------------------------------
/src/syncUtils.php:
--------------------------------------------------------------------------------
1 | $input]);
50 | }
51 | }
52 |
53 | if (! function_exists('isML')) {
54 | function isML($value)
55 | {
56 | if (array_key_exists('is-ml', $value)) {
57 | return $value['is-ml'];
58 | } else {
59 | return false;
60 | }
61 | }
62 | }
63 |
64 | if (! function_exists('isMD')) {
65 | function isMD($value)
66 | {
67 | if (array_key_exists('is-md', $value)) {
68 | return $value['is-md'];
69 | } else {
70 | return false;
71 | }
72 | }
73 | }
74 |
75 | if (! function_exists('is_EM')) {
76 | function is_EM($value)
77 | {
78 | if ($value === 'EmbedsMany') {
79 | return true;
80 | } else {
81 | return false;
82 | }
83 | }
84 | }
85 |
86 | if (! function_exists('is_EO')) {
87 | function is_EO($value)
88 | {
89 | if ($value === 'EmbedsOne') {
90 | return true;
91 | } else {
92 | return false;
93 | }
94 | }
95 | }
96 |
97 | if (! function_exists('is_HM')) {
98 | function is_HM($value)
99 | {
100 | if ($value === 'HasMany') {
101 | return true;
102 | } else {
103 | return false;
104 | }
105 | }
106 | }
107 |
108 | if (! function_exists('is_HO')) {
109 | function is_HO($value)
110 | {
111 | if ($value === 'HasOne') {
112 | return true;
113 | } else {
114 | return false;
115 | }
116 | }
117 | }
118 |
119 | if (! function_exists('isEditable')) {
120 | function isEditable($value)
121 | {
122 | if (array_key_exists('is-editable', $value)) {
123 | return $value['is-editable'];
124 | } else {
125 | return true;
126 | }
127 | }
128 | }
129 |
130 | if (! function_exists('hasTarget')) {
131 | function hasTarget($value)
132 | {
133 | if (array_key_exists('has-target', $value)) {
134 | return $value['has-target'];
135 | } else {
136 | return true;
137 | }
138 | }
139 | }
140 |
141 | if (! function_exists('isFillable')) {
142 | function isFillable($value, $event)
143 | {
144 | if ($event === 'add') {
145 | return true;
146 | } else {
147 | return isEditable($value);
148 | }
149 | }
150 | }
151 |
152 | if (! function_exists('getAID')) {
153 | /**
154 | * @param Model $model
155 | * @return string
156 | */
157 | function getAID(Model $model)
158 | {
159 | //Get Last Obj
160 | $obj = $model->orderBy('created_at', 'desc')->first();
161 |
162 | return is_null($obj) ? 1 : $obj->autoincrement_id + 1;
163 | }
164 | }
165 |
166 | if (! function_exists('getArrayWithEmptyObj')) {
167 | /**
168 | * @param $model
169 | * @return array
170 | */
171 | function getArrayWithEmptyObj($model, $is_EO, $is_EM)
172 | {
173 | $arr = [];
174 | if ($is_EO) {
175 | $obj = new stdClass();
176 | $embedObj = new $model;
177 | $EOitems = $embedObj->getItems();
178 |
179 | //Current Obj Create
180 | foreach ($EOitems as $EOkey => $item) {
181 | $obj->$EOkey = null;
182 | }
183 |
184 | $arr[] = $obj;
185 | }// $is_EM == empty array
186 |
187 | return $arr;
188 | }
189 | }
190 |
191 | if (! function_exists('getCounterForRelationships')) {
192 | /**
193 | * @param $method
194 | * @param $is_EO
195 | * @param $is_EM
196 | * @param $i
197 | * @return string
198 | */
199 | function getCounterForRelationships($method, $is_EO, $is_EM, $i)
200 | {
201 | if ($method === '' || ($method !== '' && $is_EO) || ($method === '' && $is_EM)) {
202 | return '';
203 | } else {
204 | return '-'.$i;
205 | }
206 | }
207 |
208 | if (! function_exists('getTypeOnTarget')) {
209 | function getTypeOnTarget($relation)
210 | {
211 | return Arr::has($relation, 'typeOnTarget') ? Arr::get($relation, 'typeOnTarget') : 'EmbedsMany';
212 | }
213 | }
214 | }
215 |
--------------------------------------------------------------------------------
/tests/BrowserKitTestCase.php:
--------------------------------------------------------------------------------
1 | 'Package\Facade',
18 | ];
19 | }
20 |
21 | public function setUp()
22 | {
23 | parent::setUp();
24 | $this->artisan('migrate', ['--database' => 'sqlite']);
25 | $this->loadLaravelMigrations(['--database' => 'sqlite']);
26 | $this->withFactories(__DIR__.'/factories');
27 | }
28 |
29 | /**
30 | * Creates the application.
31 | *
32 | * Needs to be implemented by subclasses.
33 | *
34 | * @return \Illuminate\Foundation\Application
35 | */
36 | public function createApplication()
37 | {
38 | $app = parent::createApplication();
39 |
40 | Hash::setRounds(4);
41 |
42 | return $app;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tests/DropCollectionTest.php:
--------------------------------------------------------------------------------
1 | prepareArticleData([], 10);
16 |
17 | $this->artisan('drop:collection', ['collection_name' => 'Article'])
18 | ->assertExitCode(0);
19 |
20 | $articles = Article::all();
21 | $this->assertEmpty($articles);
22 | $category = Category::where('name.'.cl(), 'sport')->first();
23 |
24 | $this->assertEmpty($category->articles);
25 |
26 | Article::truncate();
27 | Category::truncate();
28 | }
29 |
30 | public function test_exception_model_not_found()
31 | {
32 | $this->expectExceptionMessage('Error ModelThatDoesNotExist Model not found');
33 | $this->artisan('drop:collection', ['collection_name' => 'ModelThatDoesNotExist'])
34 | ->assertExitCode(0);
35 | }
36 |
37 | public function test_exception_path_not_found()
38 | {
39 | config()->set('laravel-mongo-auto-sync.model_path', 'path_that_does_not_exist');
40 | $this->expectExceptionMessage('Error directory path_that_does_not_exist not found');
41 | $this->artisan('model-doc:generate', ['collection_name' => 'ModelThatDoesNotExist'])
42 | ->assertExitCode(0);
43 | }
44 |
45 | public function isDeleted($articles)
46 | {
47 | if ($articles != null) {
48 | foreach ($articles as $article) {
49 | $this->assertNull(Article::find($article->id));
50 | }
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/tests/GenerateModelDocumentationTest.php:
--------------------------------------------------------------------------------
1 | getOutput();
10 |
11 | /*$this->artisan('model-doc:generate', ['collection_name' => 'Article'])
12 | ->expectsOutput($output)
13 | ->assertExitCode(0);*/
14 | $this->assertTrue(true);
15 | }
16 |
17 | public function test_generate_model_documentation_for_article()
18 | {
19 | /*$this->artisan('model-doc:generate', ['collection_name' => 'article'])
20 | ->expectsOutput('')
21 | ->assertExitCode(0);*/
22 |
23 | $this->assertTrue(true);
24 | }
25 |
26 | public function test_exception_model_not_found()
27 | {
28 | $this->expectExceptionMessage('Error ModelThatDoesNotExist Model not found');
29 | $this->artisan('model-doc:generate', ['collection_name' => 'ModelThatDoesNotExist'])
30 | ->assertExitCode(0);
31 | }
32 |
33 | public function test_exception_path_not_found()
34 | {
35 | config()->set('laravel-mongo-auto-sync.model_path', 'path_that_does_not_exist');
36 | $this->expectExceptionMessage('Error directory path_that_does_not_exist not found');
37 | $this->artisan('model-doc:generate', ['collection_name' => 'ModelThatDoesNotExist'])
38 | ->assertExitCode(0);
39 | }
40 |
41 | private function getOutput()
42 | {
43 | return '
44 |
45 |
46 |
47 |
48 | /**
49 | *
50 | * Plain Fields
51 | *
52 | * @property string $id
53 | * @property string $title
54 | *
55 | *
56 | *';
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/tests/HelperTest.php:
--------------------------------------------------------------------------------
1 | true,
14 | ];
15 | $emptyArray = [];
16 | $article = new Article;
17 |
18 | //Check return true
19 | $outBoolValue = $article->isArray($boolValue);
20 | $this->assertTrue($outBoolValue);
21 |
22 | //Check return false
23 | $outNotBoolValue = $article->isArray($emptyArray);
24 | $this->assertFalse($outNotBoolValue);
25 |
26 | //
27 | $this->expectExceptionMessage($stringValue.' is not a valid array!');
28 | $article->isArray($stringValue);
29 | }
30 |
31 | public function test_validateOptionValueException()
32 | {
33 | $notBoolValue = [
34 | 'is-array' => 'value',
35 | ];
36 | $article = new Article;
37 | $expected = 'boolean';
38 | $this->expectExceptionMessage($notBoolValue['is-array'].' is not a valid '.$expected.' found '.gettype($notBoolValue['is-array']).'! Check on your model configurations.');
39 | $article->isArray($notBoolValue);
40 | }
41 |
42 | public function test_isCarbonDate()
43 | {
44 | $stringValue = '';
45 | $boolValue = [
46 | 'is-carbon-date' => true,
47 | ];
48 | $emptyArray = [];
49 | $article = new Article;
50 |
51 | //Check return true
52 | $outBoolValue = $article->isCarbonDate($boolValue);
53 | $this->assertTrue($outBoolValue);
54 |
55 | //Check return false
56 | $outNotBoolValue = $article->isCarbonDate($emptyArray);
57 | $this->assertFalse($outNotBoolValue);
58 |
59 | //
60 | $this->expectExceptionMessage($stringValue.' is not a valid array!');
61 | $article->isCarbonDate($stringValue);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/tests/MDModelTest.php:
--------------------------------------------------------------------------------
1 | createNavigation();
13 |
14 | $out = $modelTest->getId();
15 |
16 | $this->assertNotNull($out);
17 | }
18 |
19 | public function test_getCollection()
20 | {
21 | $navigation = new Navigation();
22 |
23 | $out = $navigation->getCollection();
24 |
25 | $this->assertEquals('navigation', $out);
26 | }
27 |
28 | public function test_getRandom()
29 | {
30 | Navigation::truncate();
31 |
32 | for ($i = 0; $i < 10; $i++) {
33 | $this->createNavigation();
34 | }
35 |
36 | $navigation = new Navigation();
37 | $out = $navigation->getRandom();
38 | $this->assertInstanceOf(MongoCollection::class, $out);
39 | $this->assertCount(3, $out);
40 |
41 | //
42 |
43 | $out = $navigation->getRandom(1);
44 | $this->assertInstanceOf(MongoCollection::class, $out);
45 | $this->assertCount(1, $out);
46 |
47 | Navigation::truncate();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tests/MainMongoTraitTest.php:
--------------------------------------------------------------------------------
1 | expectException(Exception::class);
16 |
17 | $this->checkPropertyExistence(
18 | (object) ['key' => 'value'],
19 | 'fake_key'
20 | );
21 | }
22 |
23 | public function test_checkArrayExistence()
24 | {
25 | $this->expectException(Exception::class);
26 |
27 | $this->checkArrayExistence(
28 | ['key' => 'value'],
29 | 'fake_key'
30 | );
31 | }
32 |
33 | public function test_checkRequestExistence()
34 | {
35 | $request = new Request();
36 |
37 | $this->expectException(Exception::class);
38 |
39 | $request = $request->replace([
40 | ['key' => 'value'],
41 | ]);
42 |
43 | $this->checkRequestExistence(
44 | $request,
45 | 'fake_key'
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/ModelAdditionalMethodTest.php:
--------------------------------------------------------------------------------
1 | setRequest();
34 |
35 | // []
36 |
37 | $this->setMl([]);
38 |
39 | $parsed_value = $this->castValueToBeSaved('ml', [
40 | 'is-ml' => true,
41 | ], 'Tests\Models\MiniSubItem');
42 |
43 | $this->assertIsArray($parsed_value);
44 | $this->assertEquals([], $parsed_value);
45 |
46 | // null
47 |
48 | $this->setMl(null);
49 |
50 | $parsed_value = $this->castValueToBeSaved('ml', [
51 | 'is-ml' => true,
52 | ], 'Tests\Models\MiniSubItem');
53 |
54 | $this->assertIsArray($parsed_value);
55 | $this->assertCount(1, $parsed_value);
56 | }
57 |
58 | public function test_cast_md()
59 | {
60 | $this->setRequest();
61 |
62 | // UTCDateTime
63 |
64 | $this->setMd(new UTCDateTime(new DateTime()));
65 |
66 | $parsed_value = $this->castValueToBeSaved('md', [
67 | 'is-md' => true,
68 | ], 'Tests\Models\MiniSubItem');
69 |
70 | $this->assertEquals($this->getMd(), $parsed_value);
71 |
72 | // '' empty string
73 |
74 | $this->setMd('');
75 |
76 | $parsed_value = $this->castValueToBeSaved('md', [
77 | 'is-md' => true,
78 | ], 'Tests\Models\MiniSubItem');
79 |
80 | $this->assertNull($parsed_value);
81 |
82 | // null
83 |
84 | $this->setMd(null);
85 |
86 | $parsed_value = $this->castValueToBeSaved('md', [
87 | 'is-md' => true,
88 | ], 'Tests\Models\MiniSubItem');
89 |
90 | $this->assertNull($parsed_value);
91 |
92 | // carbon
93 |
94 | $this->setMd(Carbon::now());
95 |
96 | $parsed_value = $this->castValueToBeSaved('md', [
97 | 'is-md' => true,
98 | ], 'Tests\Models\MiniSubItem');
99 |
100 | $this->assertInstanceOf(UTCDateTime::class, $parsed_value);
101 | }
102 |
103 | public function test_cast_carbon_date()
104 | {
105 | $this->setRequest();
106 |
107 | // Carbon
108 |
109 | $now = Carbon::now();
110 | $this->setCarbonDate($now);
111 | $now_utc = new UTCDateTime($now);
112 |
113 | $parsed_value = $this->castValueToBeSaved('carbon_date', [
114 | 'is-carbon-date' => true,
115 | ], 'Tests\Models\MiniSubItem');
116 |
117 | $this->assertEquals($now_utc, $parsed_value);
118 |
119 | // '' empty string
120 |
121 | $this->setCarbonDate('');
122 |
123 | $parsed_value = $this->castValueToBeSaved('carbon_date', [
124 | 'is-carbon-date' => true,
125 | ], 'Tests\Models\MiniSubItem');
126 |
127 | $this->assertInstanceOf(UTCDateTime::class, $parsed_value);
128 |
129 | // null
130 |
131 | $this->setCarbonDate(null);
132 |
133 | $parsed_value = $this->castValueToBeSaved('carbon_date', [
134 | 'is-carbon-date' => true,
135 | ], 'Tests\Models\MiniSubItem');
136 |
137 | $this->assertInstanceOf(UTCDateTime::class, $parsed_value);
138 | }
139 |
140 | public function test_cast_array()
141 | {
142 | $this->setRequest();
143 |
144 | // filled array
145 |
146 | $this->setArray(['key' => 'value']);
147 |
148 | $parsed_value = $this->castValueToBeSaved('array', [
149 | 'is-array' => true,
150 | ], 'Tests\Models\MiniSubItem');
151 |
152 | $this->assertArrayHasKey('key', $parsed_value);
153 | $this->assertEquals('value', $parsed_value['key']);
154 |
155 | // null
156 |
157 | $this->setArray(null);
158 |
159 | $parsed_value = $this->castValueToBeSaved('array', [
160 | 'is-array' => true,
161 | ], 'Tests\Models\MiniSubItem');
162 |
163 | $this->assertIsArray($parsed_value);
164 | $this->assertEquals([], $parsed_value);
165 |
166 | // getAttributes
167 |
168 | $this->setArray($this->createSubItems());
169 |
170 | $parsed_value = $this->castValueToBeSaved('array', [
171 | 'is-array' => true,
172 | ], 'Tests\Models\MiniSubItem');
173 |
174 | $this->assertIsArray($parsed_value);
175 | }
176 |
177 | public function test_unique_mini_model()
178 | {
179 | $this->setMongoRelation([
180 | 'relation' => [
181 | 'type' => 'EmbedsMany',
182 | 'mode' => 'classic',
183 | 'model' => 'App\Models\MiniRelation',
184 | 'modelTarget' => 'App\Models\Relation',
185 | 'methodOnTarget' => 'Related',
186 | ],
187 | ]);
188 |
189 | $this->expectException(Exception::class);
190 |
191 | $this->getUniqueMiniModelList();
192 | }
193 |
194 | public function test_obj_with_ref_id()
195 | {
196 | $this->expectException(Exception::class);
197 |
198 | $this->getObjWithRefId('', [
199 | 'type' => 'fake',
200 | ]);
201 | }
202 |
203 | public function test_embed_model()
204 | {
205 | $this->setMiniModels([
206 | 'modelTargets' => 'App\Models\Relation',
207 | ]);
208 |
209 | $this->expectException(Exception::class);
210 |
211 | $this->getEmbedModel('modelTarget');
212 | }
213 |
214 | /* GETTERs & SETTERs */
215 |
216 | public function getMl()
217 | {
218 | return $this->ml;
219 | }
220 |
221 | public function setMl($ml): void
222 | {
223 | $this->ml = $ml;
224 | }
225 |
226 | public function getMd()
227 | {
228 | return $this->md;
229 | }
230 |
231 | public function setMd($md): void
232 | {
233 | $this->md = $md;
234 | }
235 |
236 | public function getCarbonDate()
237 | {
238 | return $this->carbon_date;
239 | }
240 |
241 | public function setCarbonDate($carbon_date): void
242 | {
243 | $this->carbon_date = $carbon_date;
244 | }
245 |
246 | public function getArray()
247 | {
248 | return $this->array;
249 | }
250 |
251 | public function setArray($array): void
252 | {
253 | $this->array = $array;
254 | }
255 |
256 | private function setRequest()
257 | {
258 | $this->request = new Request();
259 | }
260 |
261 | private function setMongoRelation($mongoRelation)
262 | {
263 | $this->mongoRelation = $mongoRelation;
264 | }
265 |
266 | private function setMiniModels($mini_models)
267 | {
268 | $this->mini_models = $mini_models;
269 | }
270 | }
271 |
--------------------------------------------------------------------------------
/tests/Models/Article.php:
--------------------------------------------------------------------------------
1 | [],
11 | 'title' => [
12 | 'is-ml' => true,
13 | 'is-editable' => true,
14 | ],
15 | 'content' => [
16 | 'is-ml' => true,
17 | ],
18 | 'slug' => [
19 | 'is-ml' => true,
20 | ],
21 | 'visibility' => [],
22 | 'status' => [],
23 | 'is_deleted' => [],
24 | 'is_active' => [],
25 | ];
26 |
27 | protected $mongoRelation = [
28 | 'primarycategory' => [
29 | 'type' => 'EmbedsOne',
30 | 'model' => 'Tests\Models\MiniCategory',
31 | 'has-target' => false,
32 | ],
33 | 'categories' => [
34 | 'type' => 'EmbedsMany',
35 | 'mode' => 'classic',
36 | 'model' => 'Tests\Models\MiniCategory',
37 | 'modelTarget' => 'Tests\Models\Category',
38 | 'methodOnTarget' => 'articles',
39 | 'modelOnTarget' => 'Tests\Models\MiniArticle',
40 | ],
41 | ];
42 |
43 | public function categories()
44 | {
45 | return $this->embedsMany('Tests\Models\MiniCategory');
46 | }
47 |
48 | public function primarycategory()
49 | {
50 | return $this->embedsOne('Tests\Models\MiniCategory');
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tests/Models/Category.php:
--------------------------------------------------------------------------------
1 | [],
11 | 'name' => [
12 | 'is-ml' => true,
13 | ],
14 | 'slug' => [
15 | 'is-ml' => true,
16 | ],
17 | 'description' => [
18 | 'is-ml' => true,
19 | ],
20 | ];
21 |
22 | protected $mongoRelation = [
23 | 'articles' => [
24 | 'type' => 'EmbedsMany',
25 | 'model' => 'Tests\Models\MiniArticle',
26 | 'mode' => 'classic',
27 | 'modelTarget' => 'Tests\Models\Article',
28 | 'methodOnTarget' => 'categories',
29 | 'modelOnTarget' => 'Tests\Models\MiniCategory',
30 | ],
31 | ];
32 |
33 | public function articles()
34 | {
35 | return $this->embedsMany('Tests\Models\MiniArticle');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/Models/Item.php:
--------------------------------------------------------------------------------
1 | [],
11 | 'code' => [],
12 | 'price' => [],
13 | 'quantity' => [],
14 | 'discount' => [],
15 | 'taxable_price' => [],
16 | 'partial_vat' => [],
17 | 'total_price' => [],
18 | 'vat_code' => [],
19 | 'vat_value' => [],
20 | 'vat_label' => [],
21 | 'collection_type' => [],
22 | 'navigation_code' => [],
23 | ];
24 |
25 | protected $mongoRelation = [
26 | 'navigation' => [
27 | 'type' => 'EmbedsOne',
28 | 'mode' => 'classic',
29 | 'model' => 'Tests\Models\MiniNavigation',
30 | 'modelTarget' => 'Tests\Models\Navigation',
31 | 'methodOnTarget' => 'sub_items',
32 | 'modelOnTarget' => 'Tests\Models\MiniItem',
33 | ],
34 | ];
35 |
36 | public function navigation()
37 | {
38 | return $this->embedsOne('Tests\Models\MiniNavigation');
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tests/Models/MiniArticle.php:
--------------------------------------------------------------------------------
1 | [],
11 | 'title' => [],
12 | 'slug' => [],
13 | 'visibility' => [],
14 | 'status' => [],
15 | 'last_updated_by' => [],
16 |
17 | ];
18 | }
19 |
--------------------------------------------------------------------------------
/tests/Models/MiniCategory.php:
--------------------------------------------------------------------------------
1 | [],
11 | 'name' => [],
12 | 'slug' => [],
13 | 'description' => [],
14 | ];
15 | }
16 |
--------------------------------------------------------------------------------
/tests/Models/MiniItem.php:
--------------------------------------------------------------------------------
1 | [],
11 | 'name' => [],
12 | 'code' => [],
13 | ];
14 | }
15 |
--------------------------------------------------------------------------------
/tests/Models/MiniNavigation.php:
--------------------------------------------------------------------------------
1 | [],
21 | 'code' => [],
22 | 'text' => [],
23 | 'title' => [
24 | 'is-ml' => true,
25 | ],
26 | ];
27 | }
28 |
--------------------------------------------------------------------------------
/tests/Models/MiniPermission.php:
--------------------------------------------------------------------------------
1 | [],
11 | 'name' => [],
12 | 'label' => [
13 | 'is-ml' => true,
14 | ],
15 | ];
16 | }
17 |
--------------------------------------------------------------------------------
/tests/Models/MiniRole.php:
--------------------------------------------------------------------------------
1 | [],
11 | 'name' => [],
12 | ];
13 | }
14 |
--------------------------------------------------------------------------------
/tests/Models/MiniSubItem.php:
--------------------------------------------------------------------------------
1 | [],
21 | 'text' => [
22 | 'is-ml' => true,
23 | ],
24 | 'code' => [],
25 | 'href' => [],
26 | ];
27 | }
28 |
--------------------------------------------------------------------------------
/tests/Models/MiniUser.php:
--------------------------------------------------------------------------------
1 | [],
11 | 'name' => [],
12 | 'surname' => [],
13 | 'email' => [],
14 | ];
15 | }
16 |
--------------------------------------------------------------------------------
/tests/Models/Navigation.php:
--------------------------------------------------------------------------------
1 | [],
29 | 'code' => [],
30 | 'href' => [],
31 | 'date' => [
32 | 'is-carbon-date' => true,
33 | ],
34 | 'target' => [],
35 | 'title' => [
36 | 'is-ml' => true,
37 | ],
38 | ];
39 |
40 | protected $mongoRelation = [
41 | 'sub_items' => [
42 | 'type' => 'EmbedsMany',
43 | 'mode' => 'classic',
44 | 'model' => 'Tests\Models\MiniSubItem',
45 | 'modelTarget' => 'Tests\Models\SubItem',
46 | 'methodOnTarget' => 'navigation',
47 | 'modelOnTarget' => 'Tests\Models\MiniNavigation',
48 | 'typeOnTarget' => 'EmbedsOne',
49 | ],
50 | ];
51 |
52 | public function sub_items()
53 | {
54 | return $this->embedsMany('Tests\Models\MiniItem');
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/tests/Models/Permission.php:
--------------------------------------------------------------------------------
1 | [],
11 | 'label' => [
12 | 'is-ml' => true,
13 | ],
14 | ];
15 |
16 | protected $mongoRelation = [
17 | 'roles' => [
18 | 'type' => 'EmbedsMany',
19 | 'mode' => 'classic',
20 | 'model' => 'Tests\Models\MiniRole',
21 | 'modelTarget' => 'Tests\Models\Role',
22 | 'methodOnTarget' => 'permissions',
23 | 'modelOnTarget' => 'Tests\Models\MiniPermission',
24 | ],
25 | 'users' => [
26 | 'type' => 'EmbedsMany',
27 | 'mode' => 'classic',
28 | 'model' => 'Tests\Models\MiniUser',
29 | 'modelTarget' => 'Tests\Models\User',
30 | 'methodOnTarget' => 'permissions',
31 | 'modelOnTarget' => 'Tests\Models\MiniPermission',
32 | ],
33 | ];
34 |
35 | public function roles()
36 | {
37 | return $this->embedsMany('Tests\Models\Role');
38 | }
39 |
40 | public function users()
41 | {
42 | return $this->embedsMany('Tests\Models\User');
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tests/Models/Role.php:
--------------------------------------------------------------------------------
1 | [],
11 | 'label' => [
12 | 'is-ml' => true,
13 | ],
14 | ];
15 |
16 | protected $mongoRelation = [
17 | 'permissions' => [
18 | 'type' => 'EmbedsMany',
19 | 'mode' => 'classic',
20 | 'model' => 'Tests\Models\MiniPermission',
21 | 'modelTarget' => 'Tests\Models\Permission',
22 | 'methodOnTarget' => 'roles',
23 | 'modelOnTarget' => 'Tests\Models\MiniRole',
24 | ],
25 | 'users' => [
26 | 'type' => 'EmbedsMany',
27 | 'mode' => 'classic',
28 | 'model' => 'Tests\Models\MiniUser',
29 | 'modelTarget' => 'Tests\Models\User',
30 | 'methodOnTarget' => 'roles',
31 | 'modelOnTarget' => 'Tests\Models\MiniRole',
32 | ],
33 | ];
34 |
35 | public function permissions()
36 | {
37 | return $this->embedsMany('Tests\Models\MiniPermission');
38 | }
39 |
40 | public function users()
41 | {
42 | return $this->embedsMany('Tests\Models\MiniUser');
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tests/Models/SubItem.php:
--------------------------------------------------------------------------------
1 | [
21 | 'is-ml' => true,
22 | ],
23 | 'code' => [],
24 | 'href' => [],
25 | ];
26 |
27 | protected $mongoRelation = [
28 | 'navigation' => [
29 | 'type' => 'EmbedsOne',
30 | 'mode' => 'classic',
31 | 'model' => 'Tests\Models\MiniNavigation',
32 | 'modelTarget' => 'Tests\Models\Navigation',
33 | 'methodOnTarget' => 'sub_items',
34 | 'modelOnTarget' => 'Tests\Models\MiniSubItem',
35 | 'typeOnTarget' => 'EmbedsMany',
36 | ],
37 | ];
38 |
39 | public function navigation()
40 | {
41 | return $this->embedsOne('Tests\Models\MiniNavigation');
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/Models/User.php:
--------------------------------------------------------------------------------
1 | [],
11 | 'name' => [],
12 | 'surname' => [],
13 | ];
14 |
15 | protected $mongoRelation = [
16 | 'permissions' => [
17 | 'type' => 'EmbedsMany',
18 | 'mode' => 'classic',
19 | 'model' => 'Tests\Models\MiniPermission',
20 | 'modelTarget' => 'Tests\Models\Permission',
21 | 'methodOnTarget' => 'users',
22 | 'modelOnTarget' => 'Tests\Models\MiniUser',
23 | ],
24 | 'roles' => [
25 | 'type' => 'EmbedsMany',
26 | 'mode' => 'classic',
27 | 'model' => 'Tests\Models\MiniRole',
28 | 'modelTarget' => 'Tests\Models\Role',
29 | 'methodOnTarget' => 'users',
30 | 'modelOnTarget' => 'Tests\Models\MiniUser',
31 | ],
32 | ];
33 |
34 | public function roles()
35 | {
36 | return $this->embedsMany('Tests\Models\MiniRole');
37 | }
38 |
39 | public function permissions()
40 | {
41 | return $this->embedsMany('Tests\Models\MiniPermission');
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/MongoCollectionTest.php:
--------------------------------------------------------------------------------
1 | cleanDb();
18 |
19 | $this->prepareArticleData(['status' => 'published'], 15);
20 |
21 | $this->prepareArticleData(['status' => 'draft'], 5);
22 |
23 | //Not found by slug 404
24 |
25 | try {
26 | Article::all()->getBySlugAndStatus('sport', 'articolo');
27 | } catch (Throwable $e) {
28 | $this->assertEquals(
29 | new NotFoundHttpException('error.Tests\Models\Article'),
30 | $e
31 | );
32 | }
33 |
34 | //Not found by all parameters null 404
35 | try {
36 | Article::all()->getBySlugAndStatus(null, null);
37 | } catch (Throwable $e) {
38 | $this->assertEquals(
39 | new NotFoundHttpException('error.Tests\Models\Article'),
40 | $e
41 | );
42 | }
43 |
44 | //Not found by category null 404
45 | try {
46 | Article::all()->getBySlugAndStatus(null, 'articolo-1');
47 | } catch (Throwable $e) {
48 | $this->assertEquals(
49 | new NotFoundHttpException('error.Tests\Models\Article'),
50 | $e
51 | );
52 | }
53 |
54 | //Not found by title null 404
55 | try {
56 | Article::all()->getBySlugAndStatus('sport', null);
57 | } catch (Throwable $e) {
58 | $this->assertEquals(
59 | new NotFoundHttpException('error.Tests\Models\Article'),
60 | $e
61 | );
62 | }
63 |
64 | //Not found by category not existing 404
65 | try {
66 | Article::all()->getBySlugAndStatus('category-not-existing', 'articolo-1');
67 | } catch (Throwable $e) {
68 | $this->assertEquals(
69 | new NotFoundHttpException('error.Tests\Models\Article'),
70 | $e
71 | );
72 | }
73 |
74 | //Not found draft article not existing 404
75 | try {
76 | Article::all()->getBySlugAndStatus('sport', 'articolo-16');
77 | } catch (Throwable $e) {
78 | $this->assertEquals(
79 | new NotFoundHttpException('error.Tests\Models\Article'),
80 | $e
81 | );
82 | }
83 |
84 | //Check if instance of Article is passed
85 | $outPublished = Article::all()->getBySlugAndStatus('sport', 'articolo-1');
86 | $this->assertInstanceOf(Article::class, $outPublished);
87 | $this->assertEquals('articolo 1', getTranslatedContent($outPublished->title));
88 | $this->assertEquals('articolo-1', getTranslatedContent($outPublished->slug));
89 | $this->assertEquals('sport', getTranslatedContent($outPublished->primarycategory->name));
90 |
91 | $this->cleanDb();
92 | }
93 |
94 | public function test_getBySlug()
95 | {
96 | $this->cleanDb();
97 |
98 | $article = $this->prepareArticleData([], 5);
99 |
100 | $this->expectException(NotFoundHttpException::class);
101 |
102 | $out = Article::all()->getBySlug('articolo-1');
103 | $this->assertInstanceOf(Article::class, $out);
104 |
105 | $outNotFoundBySlug = Article::all()->getBySlugAndStatus('sport', 'articolo');
106 | $outNotFoundByCategory = Article::all()->getBySlugAndStatus('sports', 'articolo-1');
107 |
108 | $this->cleanDb();
109 | }
110 |
111 | public function test_getNotDeleted()
112 | {
113 | $this->cleanDb();
114 |
115 | $this->prepareArticleData(['is_deleted' => true], 5);
116 | $this->prepareArticleData(['is_deleted' => false], 3);
117 |
118 | $allArticles = Article::all();
119 | $notDeletedArticles = $allArticles->getNotDeleted();
120 |
121 | $this->assertCount(3, $notDeletedArticles);
122 | $this->assertCount(8, $allArticles);
123 |
124 | $this->cleanDb();
125 | }
126 |
127 | public function test_getPublished()
128 | {
129 | $this->cleanDb();
130 |
131 | $this->prepareArticleData(['status' => 'published'], 5);
132 | $this->prepareArticleData(['status' => 'draft'], 3);
133 |
134 | $allArticles = Article::all();
135 | $getPublished = $allArticles->getPublished();
136 |
137 | $this->assertCount(5, $getPublished);
138 | $this->assertCount(8, $allArticles);
139 |
140 | $this->cleanDb();
141 | }
142 |
143 | public function test_getPublic()
144 | {
145 | $this->cleanDb();
146 |
147 | $this->prepareArticleData(['visibility' => 'public'], 5);
148 | $this->prepareArticleData(['visibility' => 'hidden'], 3);
149 |
150 | $allArticles = Article::all();
151 | $public = $allArticles->getPublic();
152 |
153 | $this->assertCount(5, $public);
154 | $this->assertCount(8, $allArticles);
155 |
156 | $this->cleanDb();
157 | }
158 |
159 | public function test_hasItem()
160 | {
161 | $this->cleanDb();
162 |
163 | $this->prepareArticleData([], 1);
164 | $this->createCategory(['name' => 'news']);
165 |
166 | $idNull = $this->getIdNull();
167 | $article = Article::all()->first();
168 | $categoryAssigned = Category::where('name.'.cl(), 'sport')->first();
169 | $categoryNotAssigned = Category::where('name.'.cl(), 'news')->first();
170 | $out = $article->categories->hasItem(null);
171 | $this->assertFalse($out);
172 |
173 | $out = $article->categories->hasItem($categoryAssigned);
174 | $this->assertTrue($out);
175 |
176 | $out = $article->categories->hasItem($categoryNotAssigned);
177 | $this->assertFalse($out);
178 |
179 | $out = $article->categories->hasItem($idNull);
180 | $this->assertFalse($out);
181 |
182 | $this->cleanDb();
183 | }
184 |
185 | public function test_moveFirst()
186 | {
187 | $this->cleanDb();
188 |
189 | $this->prepareArticleDataWithTwoCategories();
190 |
191 | $article = Article::all()->first();
192 | $out = $article->categories->moveFirst($article->primarycategory->ref_id);
193 |
194 | $this->assertEquals('news', getTranslatedContent($out->first()->name));
195 | $this->assertCount(2, $out);
196 |
197 | $this->cleanDb();
198 | }
199 |
200 | public function test_getActive()
201 | {
202 | $this->cleanDb();
203 |
204 | $this->prepareArticleData(['is_active' => true], 2);
205 | $this->prepareArticleData(['is_active' => false]);
206 |
207 | $allArticles = Article::all();
208 | $active = $allArticles->getActive();
209 | $notActiveCount = $allArticles->count() - $active->count();
210 |
211 | $this->assertCount(2, $active);
212 | $this->assertCount(3, $allArticles);
213 | $this->assertEquals(1, $notActiveCount);
214 |
215 | $this->cleanDb();
216 | }
217 |
218 | public function test_exist()
219 | {
220 | $this->cleanDb();
221 |
222 | //Test not Exist - return value false
223 | $allArticles = Article::all();
224 | $out = $allArticles->exist();
225 |
226 | $this->assertFalse($out, $out);
227 | $this->assertCount(0, $allArticles);
228 |
229 | //Test Exist - return value true
230 | $this->prepareArticleData([], 2);
231 |
232 | $allArticles = Article::all();
233 | $out = $allArticles->exist();
234 |
235 | $this->assertEquals($out, $out);
236 | $this->assertCount(2, $allArticles);
237 |
238 | $this->cleanDb();
239 | }
240 |
241 | public function test_findByAID()
242 | {
243 | $this->cleanDb();
244 | $this->prepareArticleData(['title' => 'My autoincrement title']);
245 | $this->prepareArticleData([], 2);
246 |
247 | $allArticles = Article::all();
248 | $out = $allArticles->findByAID(1);
249 |
250 | $this->assertEquals('My autoincrement title', getTranslatedContent($out->title));
251 | $this->assertCount(3, $allArticles);
252 | $this->cleanDb();
253 |
254 | $this->cleanDb();
255 | $this->prepareArticleData([], 2);
256 | $this->prepareArticleData(['title' => 'My autoincrement title']);
257 |
258 | $allArticles = Article::all();
259 | $out = $allArticles->findByAID(3);
260 |
261 | $this->assertEquals('My autoincrement title', getTranslatedContent($out->title));
262 | $this->assertCount(3, $allArticles);
263 | $this->cleanDb();
264 | }
265 |
266 | public function test_hasPermission()
267 | {
268 | $this->cleanDbUPR();
269 |
270 | $this->prepareUserData();
271 |
272 | $permissionNotExisting = '111';
273 |
274 | $out = User::all()->first()->permissions->hasPermission($permissionNotExisting);
275 |
276 | $this->assertFalse($out);
277 |
278 | $permissionExisting = Permission::where('name', 'EditArticle')->first();
279 | $out = User::all()->first()->permissions->hasPermission($permissionExisting->id);
280 |
281 | $this->assertTrue($out);
282 |
283 | $out = User::all()->first()->permissions->hasPermission(null);
284 |
285 | $this->assertFalse($out);
286 |
287 | $this->cleanDbUPR();
288 | }
289 |
290 | public function test_hasRole()
291 | {
292 | $this->cleanDbUPR();
293 |
294 | $this->prepareUserData();
295 |
296 | $out = User::all()->first()->roles->hasRole('RoleNotExisting');
297 |
298 | $this->assertFalse($out);
299 |
300 | $out = User::all()->first()->roles->hasRole('SuperAdmin');
301 |
302 | $this->assertTrue($out);
303 |
304 | $out = User::all()->first()->roles->hasRole(null);
305 |
306 | $this->assertFalse($out);
307 |
308 | $this->cleanDbUPR();
309 | }
310 |
311 | public function test_checkPermission()
312 | {
313 | $this->cleanDbUPR();
314 |
315 | $this->prepareUserData();
316 |
317 | $permissionNotExisting = 'CreateArticle';
318 |
319 | $out = User::all()->first()->permissions->checkPermission($permissionNotExisting);
320 |
321 | $this->assertFalse($out);
322 |
323 | $permissionExisting = 'EditArticle';
324 | $out = User::all()->first()->permissions->checkPermission($permissionExisting);
325 |
326 | $this->assertTrue($out);
327 |
328 | $out = User::all()->first()->permissions->checkPermission(null);
329 |
330 | $this->assertFalse($out);
331 |
332 | $this->cleanDbUPR();
333 | }
334 |
335 | private function cleanDb()
336 | {
337 | Category::truncate();
338 | Article::truncate();
339 | }
340 |
341 | private function cleanDbUPR()
342 | {
343 | User::truncate();
344 | Permission::truncate();
345 | Role::truncate();
346 | }
347 | }
348 |
--------------------------------------------------------------------------------
/tests/MongoSyncTraitTest.php:
--------------------------------------------------------------------------------
1 | createNavigation();
19 |
20 | $arr = [
21 | 'text' => null,
22 | ];
23 | $options = [
24 | 'request_type' => 'partial',
25 | ];
26 |
27 | $navigation->updateWithSync($request, $arr, $options);
28 |
29 | $this->assertNull($navigation->text);
30 | }
31 |
32 | public function test_store_with_sync()
33 | {
34 | $request = new Request;
35 |
36 | $faker = Factory::create();
37 |
38 | $navigation = new Navigation;
39 |
40 | $arr = [
41 | 'text' => $faker->text(50),
42 | 'code' => $faker->creditCardNumber,
43 | 'href' => $faker->url,
44 | 'title' => $faker->text(30),
45 | 'date' => new UTCDateTime(new DateTime()),
46 | 'target' => (object) [
47 | 'name' => $faker->text(20),
48 | 'code' => $faker->slug(2),
49 | ],
50 | ];
51 |
52 | $navigation->storeWithSync($request, $arr);
53 |
54 | $this->assertTrue($this->isNavigationCreated($navigation));
55 | }
56 |
57 | public function test_store_different_input_type()
58 | {
59 | $request = new Request;
60 |
61 | $faker = Factory::create();
62 |
63 | $navigation = new Navigation;
64 |
65 | $arr = [
66 | 'text' => $faker->text(50),
67 | 'code' => $faker->creditCardNumber,
68 | 'href' => null,
69 | 'title' => $faker->text(30),
70 | 'date' => new UTCDateTime(new DateTime()),
71 | 'target' => (object) [],
72 | ];
73 |
74 | $navigation->storeWithSync($request, $arr);
75 |
76 | $this->assertTrue($this->isNavigationCreated($navigation));
77 | $this->assertIsString($navigation->text);
78 | $this->assertNull($navigation->href);
79 | $this->assertIsArray($navigation->title);
80 | $this->assertIsObject($navigation->target);
81 | }
82 |
83 | public function test_update_with_sync_with_embeds_one_on_target()
84 | {
85 | $request = new Request;
86 |
87 | $faker = Factory::create();
88 |
89 | $navigation = Navigation::all()->last();
90 |
91 | $options = [
92 | 'request_type' => 'partial',
93 | ];
94 |
95 | $arr = [
96 | 'text' => 'Aggiornato',
97 | 'code' => $faker->creditCardNumber,
98 | 'href' => $faker->imageUrl(),
99 | 'title' => $faker->text(30),
100 | 'date' => null,
101 | 'target' => (object) [],
102 | ];
103 |
104 | $navigation->updateWithSync($request, $arr, $options);
105 |
106 | $this->assertTrue($this->isUpdated($navigation));
107 | }
108 |
109 | public function test_update_with_sync_with_embeds_many_on_target()
110 | {
111 | $request = new Request;
112 |
113 | $faker = Factory::create();
114 |
115 | $navigation = Navigation::all()->last();
116 |
117 | $options = [
118 | 'request_type' => 'partial',
119 | ];
120 |
121 | $arr = [
122 | 'text' => 'Aggiornato',
123 | 'code' => $faker->creditCardNumber,
124 | 'href' => $faker->imageUrl(),
125 | 'title' => $faker->text(30),
126 | 'date' => null,
127 | 'target' => (object) [],
128 | ];
129 |
130 | $navigation->updateWithSync($request, $arr, $options);
131 |
132 | $this->assertTrue($this->isUpdated($navigation));
133 | }
134 |
135 | public function test_update_different_input_type()
136 | {
137 | $request = new Request;
138 |
139 | $faker = Factory::create();
140 |
141 | $navigation = Navigation::all()->last();
142 |
143 | $options = [
144 | 'request_type' => 'partial',
145 | ];
146 |
147 | $arr = [
148 | 'text' => 'Aggiornato',
149 | 'code' => $faker->creditCardNumber,
150 | 'href' => $faker->text(50),
151 | 'title' => $faker->text(30),
152 | 'date' => new UTCDateTime(new DateTime()),
153 | 'target' => (object) [],
154 | ];
155 |
156 | $navigation->updateWithSync($request, $arr, $options);
157 |
158 | $this->assertTrue($this->isUpdated($navigation));
159 | $this->assertIsObject($navigation->target);
160 | $this->assertIsArray($navigation->title);
161 | $this->assertIsString($navigation->href);
162 | }
163 |
164 | public function test_update_null_value_on_all_field_except_text_and_code()
165 | {
166 | $request = new Request;
167 |
168 | $faker = Factory::create();
169 |
170 | $navigation = Navigation::all()->last();
171 |
172 | $options = [
173 | 'request_type' => 'partial',
174 | ];
175 |
176 | $arr = [
177 | 'text' => 'Aggiornato',
178 | 'code' => $faker->creditCardNumber,
179 | 'href' => null,
180 | 'title' => null,
181 | 'date' => null,
182 | 'target' => null,
183 | ];
184 |
185 | $navigation->updateWithSync($request, $arr, $options);
186 |
187 | $this->assertTrue($this->isUpdated($navigation));
188 | /*$this->assertNull($navigation->href);
189 | $this->assertNull($navigation->title[cl()]);
190 | $this->assertNull($navigation->date);
191 | $this->assertNull($navigation->target);*/
192 | }
193 |
194 | public function test_store_item_with_relation()
195 | {
196 | $request = new Request;
197 | $navigation = $this->createNavigation();
198 | $faker = Factory::create();
199 |
200 | $item = new Item;
201 |
202 | $arr = [
203 | 'name' => $faker->firstName.' '.$faker->lastName,
204 | 'code' => $faker->creditCardNumber,
205 | 'price' => $faker->numberBetween(1, 100),
206 | 'quantity' => $faker->numberBetween(1, 10),
207 | 'discount' => $faker->randomElement([10, 20, 50]),
208 | 'taxable_price' => $faker->numberBetween(10, 500),
209 | 'partial_vat' => $faker->numberBetween(20, 50),
210 | 'total_price' => $faker->numberBetween(20, 600),
211 | 'vat_code' => $faker->randomElement([
212 | '0',
213 | '3',
214 | '4',
215 | ]),
216 | 'vat_value' => $faker->randomElement([
217 | 22,
218 | 10,
219 | 4,
220 | ]),
221 | 'vat_label' => $faker->randomElement([
222 | 'Iva 22%',
223 | 'Iva 10%',
224 | 'Iva 4%',
225 | ]),
226 | 'collection_type' => null,
227 | 'navigation_code' => $navigation->code,
228 |
229 | //Relation
230 | 'navigation' => $this->getNavigation($navigation->code),
231 | ];
232 |
233 | $item = $item->storeWithSync($request, $arr);
234 | $mini_items = Navigation::where('sub_items.ref_id', $item->getId())->first()->sub_items;
235 |
236 | $this->assertTrue($this->isItemCreated($item));
237 | $this->assertNotNull($mini_items);
238 | }
239 |
240 | public function test_update_navigation_with_items()
241 | {
242 | $navigation = $this->createNavigation();
243 |
244 | $request = new Request;
245 |
246 | $options = [
247 | 'request_type' => 'partial',
248 | ];
249 |
250 | $arr = [
251 | 'text' => $navigation->text.' Aggiornato',
252 | 'code' => $navigation->code,
253 | 'href' => $navigation->href,
254 | 'title' => $navigation->title[cl()],
255 | 'date' => $navigation->date,
256 | 'target' => $navigation->target,
257 | ];
258 |
259 | $navigation->updateWithSync($request, $arr, $options);
260 |
261 | $this->assertTrue($this->isNavigationUpdatedCorrectly($navigation));
262 | }
263 | }
264 |
--------------------------------------------------------------------------------
/tests/SimpleTestCase.php:
--------------------------------------------------------------------------------
1 | createSubItems(
19 | [
20 | 'text' => 'example sub item test',
21 | 'code' => 'HFGRT12345',
22 | 'href' => 'https://google.com',
23 | ]
24 | );
25 |
26 | $this->assertEquals('example sub item test', getTranslatedContent($sub_item->text));
27 | $this->assertEquals('HFGRT12345', $sub_item->code);
28 | $this->assertEquals('https://google.com', $sub_item->href);
29 |
30 | //Create a mini Sub Item to associate to the new navigation
31 | $sub_items = json_encode(
32 | [
33 | (object) [
34 | 'ref_id' => $sub_item->id,
35 | 'text' => getTranslatedContent($sub_item->text),
36 | 'code' => $sub_item->code,
37 | 'href' => $sub_item->href,
38 | ],
39 | ]
40 | );
41 |
42 | $date = Date::now();
43 |
44 | //Create a navigation and test if the data is store correctly
45 | $navigation = $this->createNavigation(
46 | [
47 | 'text' => 'example navigation text',
48 | 'code' => '1234ABHFGRT5',
49 | 'href' => 'https://www.netflix.com/browse',
50 | 'date' => $date,
51 | 'target' => '_blank',
52 | 'title' => 'Random title',
53 | 'sub_items' => $sub_items,
54 | ]
55 | );
56 |
57 | $this->assertTrue($this->isNavigationCreated($navigation));
58 | $this->assertIsString($navigation->text);
59 | $this->assertIsArray($navigation->title);
60 |
61 | $this->assertEquals('example navigation text', $navigation->text);
62 | $this->assertEquals('1234ABHFGRT5', $navigation->code);
63 | $this->assertEquals('https://www.netflix.com/browse', $navigation->href);
64 | //$this->assertEquals($date, $navigation->date); TODO: fix precision date
65 | $this->assertEquals('_blank', $navigation->target);
66 | $this->assertEquals('Random title', getTranslatedContent($navigation->title));
67 | $this->assertInstanceOf(MongoCollection::class, $navigation->sub_items);
68 |
69 | //Check if the subitem target is updated correctly
70 | $sub_item = SubItem::find($sub_item->id);
71 | $mini_navigation = $sub_item->navigation;
72 | $this->assertNotNull($mini_navigation);
73 | $this->assertEquals($navigation->id, $mini_navigation->ref_id);
74 | $this->assertEquals('1234ABHFGRT5', $mini_navigation->code);
75 | $this->assertEquals('Random title', getTranslatedContent($mini_navigation->title));
76 | $this->assertEquals('example navigation text', $navigation->text);
77 |
78 | //Clean all data that has been stored
79 | $this->cleanUp($navigation, $sub_item);
80 | }
81 |
82 | public function test_store_with_embeds_many_on_target()
83 | {
84 | //Create a navigation and test if the data is store correctly
85 | $navigation = $this->createNavigation();
86 |
87 | $this->assertTrue($this->isNavigationCreated($navigation));
88 | $this->assertInstanceOf(MongoCollection::class, $navigation->sub_items);
89 | $mini_navigation = $this->getMiniNavigation($navigation->id);
90 |
91 | $sub_item = $this->createSubItems(
92 | [
93 | 'text' => 'example sub item test',
94 | 'code' => 'HFGRT12345',
95 | 'href' => 'https://google.com',
96 | 'navigation' => $mini_navigation,
97 | ]
98 | );
99 |
100 | $this->assertEquals('example sub item test', getTranslatedContent($sub_item->text));
101 | $this->assertEquals('HFGRT12345', $sub_item->code);
102 | $this->assertEquals('https://google.com', $sub_item->href);
103 |
104 | //Check target
105 | $navigation = Navigation::find($navigation->id);
106 |
107 | $sub_item_mini = $navigation->sub_items[0];
108 |
109 | $this->assertNotEmpty($navigation->sub_items);
110 | $this->assertEquals($sub_item->id, $sub_item_mini->ref_id);
111 | $this->assertEquals(getTranslatedContent($sub_item->text), getTranslatedContent($sub_item_mini->text));
112 | $this->assertEquals($sub_item->code, $sub_item_mini->code);
113 | $this->assertEquals($sub_item->href, $sub_item_mini->href);
114 |
115 | $faker = Factory::create();
116 | //Add more sub items and restart test
117 | $navigation->sub_items = [
118 | [
119 | 'ref_id' => $faker->uuid,
120 | 'text' => $faker->text,
121 | 'code' => $faker->name,
122 | 'href' => $faker->url,
123 | ],
124 | [
125 | 'ref_id' => $faker->uuid,
126 | 'text' => $faker->text,
127 | 'code' => $faker->name,
128 | 'href' => $faker->url,
129 | ],
130 | [
131 | 'ref_id' => $faker->uuid,
132 | 'text' => $faker->text,
133 | 'code' => $faker->name,
134 | 'href' => $faker->url,
135 | ],
136 | ];
137 |
138 | $navigation->save();
139 |
140 | $mini_navigation = $this->getMiniNavigation($navigation->id);
141 | $data = [
142 | 'navigation' => $mini_navigation,
143 | ];
144 |
145 | $sub_item = $this->createSubItems($data);
146 | $navigation = Navigation::find($navigation->id);
147 |
148 | $this->assertEquals(4, $navigation->sub_items->count());
149 |
150 | $sub_item_mini = $navigation->sub_items->where('ref_id', $sub_item->id)->first();
151 |
152 | $this->assertEquals($sub_item->id, $sub_item_mini->ref_id);
153 | $this->assertEquals($sub_item->text, $sub_item_mini->text);
154 | $this->assertEquals($sub_item->code, $sub_item_mini->code);
155 | $this->assertEquals($sub_item->title, $sub_item_mini->title);
156 |
157 | //clean data
158 | $navigation->delete();
159 | $sub_item->delete();
160 | }
161 |
162 | public function test_store_with_embeds_one_on_target_just_filled()
163 | {
164 | $faker = Factory::create();
165 |
166 | $navigation = new Navigation;
167 | $navigation = $navigation->storeWithSync(new Request, [
168 | 'text' => $faker->text(50),
169 | 'code' => $faker->creditCardNumber,
170 | 'href' => $faker->url,
171 | 'date' => Date::now(),
172 | 'target' => $faker->text(50),
173 | 'title' => null,
174 | 'sub_items' => json_encode([]),
175 | ]);
176 |
177 | $this->assertTrue($this->isNavigationCreated($navigation));
178 | $this->assertInstanceOf(MongoCollection::class, $navigation->sub_items);
179 |
180 | // 1 navigation
181 |
182 | $first_sub_item = $this->createSubItems([
183 | 'code' => 'HFGRT12345',
184 | 'navigation' => $this->getMiniNavigation($navigation->id),
185 | ]);
186 |
187 | $this->assertEquals('HFGRT12345', $first_sub_item->code);
188 | $this->assertEquals($navigation->id, $first_sub_item->navigation->ref_id);
189 | $this->assertInstanceOf(MiniNavigation::class, $first_sub_item->navigation);
190 |
191 | // 1 navigation with 1 sub item and 1 sub item with navigation
192 |
193 | $second_sub_item = $this->createSubItems([
194 | 'code' => 'HFGRT12346',
195 | 'navigation' => $this->getMiniNavigation($navigation->id),
196 | ]);
197 |
198 | $this->assertEquals('HFGRT12346', $second_sub_item->code);
199 | $this->assertEquals($navigation->id, $second_sub_item->navigation->ref_id);
200 | $this->assertInstanceOf(MiniNavigation::class, $second_sub_item->navigation);
201 |
202 | // 1 navigation with 2 sub items and 1 sub item with navigation
203 |
204 | $navigation = Navigation::find($navigation->id);
205 |
206 | $this->assertCount(2, $navigation->sub_items);
207 | $this->assertEquals('HFGRT12345', $navigation->sub_items[0]->code);
208 | $this->assertEquals('HFGRT12346', $navigation->sub_items[1]->code);
209 |
210 | $navigation->delete();
211 | $first_sub_item->delete();
212 | $second_sub_item->delete();
213 | }
214 | }
215 |
--------------------------------------------------------------------------------
/tests/SyncTestCase.php:
--------------------------------------------------------------------------------
1 | text(50);
36 | $code = Arr::has($data, 'code') ? Arr::get($data, 'code') : $faker->creditCardNumber;
37 | $href = Arr::has($data, 'href') ? Arr::get($data, 'href') : $faker->url;
38 | $navigation = Arr::has($data, 'navigation') ? Arr::get($data, 'navigation') : json_encode([]);
39 |
40 | $arr = [
41 | 'text' => $text,
42 | 'code' => $code,
43 | 'href' => $href,
44 | 'navigation' => $navigation,
45 | ];
46 |
47 | return $sub_item->storeWithSync($request, $arr);
48 | }
49 |
50 | /**
51 | * @param array $data
52 | * @return Item
53 | *
54 | * @throws Exception
55 | */
56 | public function createItems(array $data = [])
57 | {
58 | $sub_item = new Item;
59 | $faker = Factory::create();
60 | $request = new Request;
61 |
62 | $text = Arr::has($data, 'text') ? Arr::get($data, 'text') : $faker->text(50);
63 | $code = Arr::has($data, 'code') ? Arr::get($data, 'code') : $faker->creditCardNumber;
64 | $href = Arr::has($data, 'href') ? Arr::get($data, 'href') : $faker->url;
65 | $navigation = Arr::has($data, 'navigation') ? Arr::get($data, 'navigation') : json_encode([]);
66 |
67 | $arr = [
68 | 'text' => $text,
69 | 'name' => $text,
70 | 'code' => $code,
71 | 'href' => $href,
72 | 'navigation' => $navigation,
73 | ];
74 |
75 | return $sub_item->storeWithSync($request, $arr);
76 | }
77 |
78 | /**
79 | * @param array $data
80 | * @return Navigation
81 | *
82 | * @throws Exception
83 | */
84 | public function createNavigation(
85 | array $data = []
86 | ) {
87 | $faker = Factory::create();
88 | $request = new Request;
89 |
90 | $navigation = new Navigation;
91 |
92 | $text = Arr::has($data, 'text') ? Arr::get($data, 'text') : $faker->text(50);
93 | $code = Arr::has($data, 'code') ? Arr::get($data, 'code') : $faker->creditCardNumber;
94 | $href = Arr::has($data, 'href') ? Arr::get($data, 'href') : $faker->url;
95 | $date = Arr::has($data, 'date') ? Arr::get($data, 'date') : Date::now();
96 | $target = Arr::has($data, 'target') ? Arr::get($data, 'target') : $faker->text(50);
97 | $title = Arr::has($data, 'title') ? Arr::get($data, 'title') : $faker->title;
98 |
99 | $sub_items = Arr::has($data, 'sub_items') ? Arr::get($data, 'sub_items') : json_encode([]);
100 |
101 | $arr = [
102 | 'text' => $text,
103 | 'code' => $code,
104 | 'href' => $href,
105 | 'date' => $date,
106 | 'target' => $target,
107 | 'title' => $title,
108 | 'sub_items' => $sub_items,
109 | ];
110 |
111 | return $navigation->storeWithSync($request, $arr);
112 | }
113 |
114 | /**
115 | * @param array $data
116 | * @return Category
117 | *
118 | * @throws Exception
119 | */
120 | public function createCategory(
121 | array $data = []
122 | ) {
123 | $faker = Factory::create();
124 | $request = new Request;
125 |
126 | $category = new Category;
127 |
128 | $category_id = getAID($category);
129 | $name = Arr::has($data, 'name') ? Arr::get($data, 'name') : $faker->text(50);
130 | $slug = Arr::has($data, 'slug') ? Arr::get($data, 'slug') : Str::slug($name);
131 | $description = Arr::has($data, 'description') ? Arr::get($data, 'description') : $faker->text(50);
132 |
133 | $articles = Arr::has($data, 'articles') ? Arr::get($data, 'articles') : json_encode([]);
134 |
135 | $arr = [
136 | 'category_id' => $category_id,
137 | 'name' => $name,
138 | 'slug' => $slug,
139 | 'description' => $description,
140 | 'articles' => $articles,
141 | ];
142 |
143 | return $category->storeWithSync($request, $arr);
144 | }
145 |
146 | /**
147 | * @param array $data
148 | * @return Permission
149 | *
150 | * @throws Exception
151 | */
152 | public function createPermission(
153 | array $data = []
154 | ) {
155 | $faker = Factory::create();
156 | $request = new Request;
157 |
158 | $permission = new Permission;
159 |
160 | $name = Arr::has($data, 'name') ? Arr::get($data, 'name') : $faker->name;
161 | $label = Arr::has($data, 'label') ? Arr::get($data, 'label') : $faker->name;
162 |
163 | $roles = Arr::has($data, 'roles') ? Arr::get($data, 'roles') : json_encode([]);
164 | $users = Arr::has($data, 'users') ? Arr::get($data, 'users') : json_encode([]);
165 |
166 | $arr = [
167 | 'name' => $name,
168 | 'label' => $label,
169 | 'roles' => $roles,
170 | 'users' => $users,
171 | ];
172 |
173 | return $permission->storeWithSync($request, $arr);
174 | }
175 |
176 | /**
177 | * @param array $data
178 | * @return Role
179 | *
180 | * @throws Exception
181 | */
182 | public function createRole(
183 | array $data = []
184 | ) {
185 | $faker = Factory::create();
186 | $request = new Request;
187 |
188 | $role = new Role;
189 |
190 | $name = Arr::has($data, 'name') ? Arr::get($data, 'name') : $faker->name;
191 | $label = Arr::has($data, 'label') ? Arr::get($data, 'label') : $faker->name;
192 |
193 | $permissions = Arr::has($data, 'permissions') ? Arr::get($data, 'permissions') : json_encode([]);
194 | $users = Arr::has($data, 'users') ? Arr::get($data, 'users') : json_encode([]);
195 |
196 | $arr = [
197 | 'name' => $name,
198 | 'label' => $label,
199 | 'permissions' => $permissions,
200 | 'users' => $users,
201 | ];
202 |
203 | return $role->storeWithSync($request, $arr);
204 | }
205 |
206 | /**
207 | * @param array $data
208 | * @param int $size
209 | *
210 | * @throws Exception
211 | */
212 | public function createArticles(
213 | array $data = [],
214 | int $size = 1
215 | ) {
216 | $faker = Factory::create();
217 |
218 | for ($i = 0; $i < $size; $i++) {
219 | $request = new Request;
220 | $article = new Article;
221 |
222 | $autoincrement_id = getAID($article);
223 | $title = Arr::has($data, 'title') ? Arr::get($data, 'title') : 'articolo '.$autoincrement_id;
224 | $content = Arr::has($data, 'content') ? Arr::get($data, 'name') : $faker->text(100);
225 | $slug = Arr::has($data, 'slug') ? Arr::get($data, 'slug') : Str::slug($title);
226 | $visibility = Arr::has($data, 'visibility') ? Arr::get($data, 'visibility') : $faker->text(50);
227 | $status = Arr::has($data, 'status') ? Arr::get($data, 'status') : $faker->text(50);
228 | $is_deleted = Arr::has($data, 'is_deleted') ? Arr::get($data, 'is_deleted') : $faker->boolean;
229 | $is_active = Arr::has($data, 'is_active') ? Arr::get($data, 'is_active') : $faker->text(50);
230 | $primarycategory = Arr::has($data, 'primarycategory') ? Arr::get($data, 'primarycategory') : $faker->text(50);
231 |
232 | $categories = Arr::has($data, 'categories') ? Arr::get($data, 'categories') : json_encode([]);
233 |
234 | $arr = [
235 | 'autoincrement_id' => $autoincrement_id,
236 | 'title' => $title,
237 | 'content' => $content,
238 | 'slug' => $slug,
239 | 'visibility' => $visibility,
240 | 'status' => $status,
241 | 'is_deleted' => $is_deleted,
242 | 'is_active' => $is_active,
243 | 'primarycategory' => $primarycategory,
244 | 'categories' => $categories,
245 | ];
246 |
247 | $article->storeWithSync($request, $arr);
248 | }
249 | }
250 |
251 | /**
252 | * @param array $data
253 | * @param int $size
254 | *
255 | * @throws Exception
256 | */
257 | public function createUsers(
258 | array $data = [],
259 | int $size = 1
260 | ) {
261 | $faker = Factory::create();
262 |
263 | for ($i = 0; $i < $size; $i++) {
264 | $request = new Request;
265 | $user = new User;
266 |
267 | $name = Arr::has($data, 'name') ? Arr::get($data, 'name') : $faker->firstName;
268 | $surname = Arr::has($data, 'surname') ? Arr::get($data, 'surname') : $faker->lastName;
269 | $email = Arr::has($data, 'email') ? Arr::get($data, 'email') : $faker->email;
270 |
271 | $roles = Arr::has($data, 'roles') ? Arr::get($data, 'roles') : json_encode([]);
272 | $permissions = Arr::has($data, 'permissions') ? Arr::get($data, 'permissions') : json_encode([]);
273 |
274 | $arr = [
275 | 'name' => $name,
276 | 'surname' => $surname,
277 | 'email' => $email,
278 | 'roles' => $roles,
279 | 'permissions' => $permissions,
280 | ];
281 | $user->storeWithSync($request, $arr);
282 | }
283 | }
284 |
285 | /**
286 | * @param array $data
287 | * @param int $size
288 | *
289 | * @throws Exception
290 | */
291 | public function prepareArticleData(
292 | array $data = [],
293 | int $size = 1
294 | ) {
295 | $category = $this->createCategory(['name' => 'sport']);
296 | $miniCategory = $this->getMiniCategory($category->id);
297 |
298 | $relationshipValues = [
299 | 'primarycategory' => $miniCategory,
300 | 'categories' => $miniCategory,
301 | ];
302 |
303 | $mergedData = array_merge($relationshipValues, $data);
304 |
305 | $this->createArticles($mergedData, $size);
306 | }
307 |
308 | public function prepareUserData(
309 | array $data = [],
310 | int $size = 1
311 | ) {
312 | $first_permission = $this->createPermission(['name' => 'EditArticle']);
313 | $second_permission = $this->createPermission(['name' => 'CreateUser']);
314 |
315 | $first_role = $this->createRole(['name' => 'SuperAdmin']);
316 | $second_role = $this->createRole(['name' => 'Editor']);
317 |
318 | $miniPermissions = $this->getMiniPermissions([
319 | $first_permission->id,
320 | $second_permission->id,
321 | ]);
322 |
323 | $miniRoles = $this->getMiniRoles([
324 | $first_role->id,
325 | $second_role->id, ]
326 | );
327 |
328 | $relationshipValues = [
329 | 'permissions' => $miniPermissions,
330 | 'roles' => $miniRoles,
331 | ];
332 |
333 | $mergedData = array_merge($relationshipValues, $data);
334 |
335 | $this->createUsers($mergedData, $size);
336 | }
337 |
338 | public function prepareArticleDataWithTwoCategories(
339 | array $data = [],
340 | int $size = 1
341 | ) {
342 | $first_category = $this->createCategory(['name' => 'sport']);
343 | $second_category = $this->createCategory(['name' => 'news']);
344 | $miniPrimaryCategory = $this->getMiniCategory($second_category->id);
345 |
346 | $miniCategories = $this->getMiniCategory([$second_category->id, $first_category->id]);
347 |
348 | $relationshipValues = [
349 | 'primarycategory' => $miniPrimaryCategory,
350 | 'categories' => $miniCategories,
351 | ];
352 | //dd($relationshipValues);
353 | $mergedData = array_merge($relationshipValues, $data);
354 |
355 | $this->createArticles($mergedData, $size);
356 | }
357 |
358 | /**
359 | * @param string|array $category_id
360 | * @return string|false
361 | *
362 | * @throws Exception
363 | */
364 | public function getMiniCategory($category_id = '')
365 | {
366 | if (is_array($category_id)) {
367 | $out = [];
368 | foreach ($category_id as $category) {
369 | $out[] = $this->prepareSingleMiniCategory($category);
370 | }
371 | } else {
372 | $out[] = $this->prepareSingleMiniCategory($category_id);
373 | }
374 |
375 | return json_encode($out);
376 | }
377 |
378 | /**
379 | * @param string|array $permission_id
380 | * @return string|false
381 | *
382 | * @throws Exception
383 | */
384 | public function getMiniPermissions($permission_id = '')
385 | {
386 | if (is_array($permission_id)) {
387 | $out = [];
388 | foreach ($permission_id as $permission) {
389 | $out[] = $this->prepareSingleMiniPermission($permission);
390 | }
391 | } else {
392 | $out[] = $this->prepareSingleMiniPermission($permission_id);
393 | }
394 |
395 | return json_encode($out);
396 | }
397 |
398 | /**
399 | * @param string|array $role_id
400 | * @return string|false
401 | *
402 | * @throws Exception
403 | */
404 | public function getMiniRoles($role_id = '')
405 | {
406 | if (is_array($role_id)) {
407 | $out = [];
408 | foreach ($role_id as $role) {
409 | $out[] = $this->prepareSingleMiniRole($role);
410 | }
411 | } else {
412 | $out[] = $this->prepareSingleMiniRole($role_id);
413 | }
414 |
415 | return json_encode($out);
416 | }
417 |
418 | /**
419 | * @param $category_id
420 | * @return object
421 | *
422 | * @throws Exception
423 | */
424 | public function prepareSingleMiniCategory($category_id)
425 | {
426 | if ($category_id == '' || is_null($category_id)) {
427 | $category = $this->createCategory();
428 | } else {
429 | $category = Category::find($category_id);
430 | if (is_null($category)) {
431 | return null;
432 | }
433 | }
434 |
435 | return (object) [
436 | 'ref_id' => $category->id,
437 | 'name' => $category->name,
438 | 'slug' => $category->slug,
439 | 'description' => $category->description,
440 | ];
441 | }
442 |
443 | /**
444 | * @param $permission_id
445 | * @return object
446 | *
447 | * @throws Exception
448 | */
449 | public function prepareSingleMiniPermission($permission_id)
450 | {
451 | if ($permission_id == '' || is_null($permission_id)) {
452 | $permission = $this->createPermission();
453 | } else {
454 | $permission = Permission::find($permission_id);
455 | if (is_null($permission)) {
456 | return null;
457 | }
458 | }
459 |
460 | return (object) [
461 | 'ref_id' => $permission->id,
462 | 'name' => $permission->name,
463 | 'label' => getTranslatedContent($permission->label),
464 | ];
465 | }
466 |
467 | /**
468 | * @param $role_id
469 | * @return object
470 | *
471 | * @throws Exception
472 | */
473 | public function prepareSingleMiniRole($role_id)
474 | {
475 | if ($role_id == '' || is_null($role_id)) {
476 | $role = $this->createRole();
477 | } else {
478 | $role = Role::find($role_id);
479 | if (is_null($role)) {
480 | return null;
481 | }
482 | }
483 |
484 | return (object) [
485 | 'ref_id' => $role->id,
486 | 'name' => $role->name,
487 | 'label' => $role->label,
488 | ];
489 | }
490 |
491 | /**
492 | * @param string $autoincrement_id
493 | * @return false|string
494 | */
495 | public function getMiniArticle(string $autoincrement_id = '')
496 | {
497 | if ($autoincrement_id == '' || is_null($autoincrement_id)) {
498 | $article = $this->createArticle();
499 | } else {
500 | $article = Article::find($autoincrement_id);
501 | if (is_null($article)) {
502 | return json_encode(
503 | []
504 | );
505 | }
506 | }
507 |
508 | return json_encode(
509 | [
510 | (object) [
511 | 'ref_id' => $article->id,
512 | 'title' => $article->title,
513 | 'slug' => $article->slug,
514 | 'visibility' => $article->visibility,
515 | 'status' => $article->status,
516 | ],
517 | ]
518 | );
519 | }
520 |
521 | /**
522 | * @return object
523 | */
524 | public function getIdNull()
525 | {
526 | return (object) [
527 | 'id' => null,
528 | ];
529 | }
530 |
531 | /**
532 | * @param string $navigation_id
533 | * @return false|string
534 | *
535 | * @throws Exception
536 | */
537 | public function getMiniNavigation(string $navigation_id = '')
538 | {
539 | if ($navigation_id == '' || is_null($navigation_id)) {
540 | $navigation = $this->createNavigation();
541 | } else {
542 | $navigation = Navigation::find($navigation_id);
543 | if (is_null($navigation)) {
544 | return json_encode(
545 | []
546 | );
547 | }
548 | }
549 |
550 | return json_encode(
551 | [
552 | (object) [
553 | 'ref_id' => $navigation->id,
554 | 'text' => $navigation->text,
555 | 'code' => $navigation->code,
556 | 'title' => getTranslatedContent($navigation->title),
557 | ],
558 | ]
559 | );
560 | }
561 |
562 | /**
563 | * @param $navigation
564 | * @return bool
565 | */
566 | public function isNavigationCreated($navigation)
567 | {
568 | return ! is_null(Navigation::find($navigation->id));
569 | }
570 |
571 | /**
572 | * @param $item
573 | * @return bool
574 | */
575 | public function isItemCreated($item)
576 | {
577 | return ! is_null(Item::find($item->id));
578 | }
579 |
580 | /**
581 | * @param Navigation $navigation
582 | * @param SubItem $sub_item
583 | *
584 | * @throws Exception
585 | */
586 | public function cleanUp(Navigation $navigation, SubItem $sub_item)
587 | {
588 | $sub_item->delete();
589 | $navigation->delete();
590 | }
591 |
592 | /**
593 | * @param $item
594 | * @return bool
595 | */
596 | public function isItemUpdatedCorrectly($item)
597 | {
598 | return Str::contains($item->name, 'Aggiornato');
599 | }
600 |
601 | /**
602 | * @param $navigation
603 | * @return bool
604 | */
605 | public function isNavigationUpdatedCorrectly($navigation)
606 | {
607 | return Str::contains($navigation->text, 'Aggiornato');
608 | }
609 |
610 | /**
611 | * @param $navigation
612 | * @return bool
613 | */
614 | public function isUpdated($navigation)
615 | {
616 | return $navigation->text == 'Aggiornato';
617 | }
618 |
619 | /**
620 | * @param $navigation_id
621 | * @param $item_id
622 | * @return bool
623 | */
624 | public function isItemAddedInNavigationCollection($navigation_id, $item_id)
625 | {
626 | $navigation = Navigation::where('id', '=', $navigation_id)->get()->first();
627 | $return = false;
628 | if (isset($navigation->items)) {
629 | foreach ($navigation->items as $item) {
630 | $return = $item->ref_id == $item_id;
631 | }
632 | }
633 |
634 | return $return;
635 | }
636 |
637 | /**
638 | * @param $navigation_code
639 | * @return false|string
640 | */
641 | public function getNavigation($navigation_code)
642 | {
643 | $arr = [];
644 | $navigation = Navigation::where('code', '=', $navigation_code)->get()->first();
645 |
646 | $newNavigation = new stdClass;
647 | $newNavigation->ref_id = $navigation->id;
648 | $newNavigation->code = $navigation_code;
649 | $newNavigation->title[cl()] = $navigation->title;
650 | $newNavigation->text = $navigation->text;
651 |
652 | $arr[] = $newNavigation;
653 |
654 | return json_encode($arr);
655 | }
656 |
657 | protected function getMiniSubItem(string $sub_item_id)
658 | {
659 | if ($sub_item_id == '' || is_null($sub_item_id)) {
660 | $sub_item = $this->createSubItems();
661 | } else {
662 | $sub_item = SubItem::find($sub_item_id);
663 | if (is_null($sub_item)) {
664 | return json_encode(
665 | []
666 | );
667 | }
668 | }
669 |
670 | return json_encode(
671 | [
672 | (object) [
673 | 'ref_id' => $sub_item->id,
674 | 'code' => $sub_item->code,
675 | 'href' => $sub_item->href,
676 | 'text' => getTranslatedContent($sub_item->text),
677 | ],
678 | ]
679 | );
680 | }
681 | }
682 |
--------------------------------------------------------------------------------
/tests/SyncUtilsTest.php:
--------------------------------------------------------------------------------
1 | assertEquals('', $out);
17 |
18 | // Input not expected Array with key equals to language code Ex. En
19 |
20 | $cl = cl();
21 |
22 | $mlCollection = [
23 | $cl => 'car',
24 | ];
25 |
26 | $out = getTranslatedContent($mlCollection);
27 |
28 | $this->assertEquals('car', $out);
29 | }
30 |
31 | public function test_cl()
32 | {
33 | // Input expected to be 'en' from $cl
34 |
35 | $cl = 'en';
36 |
37 | $out = cl($cl);
38 |
39 | $this->assertEquals('en', $out);
40 | }
41 |
42 | public function test_ml()
43 | {
44 | // Input expected to be [ "en" => "1" ] from $out
45 |
46 | $destination = null;
47 | $input = '1';
48 | $out = ml($destination, $input);
49 | $this->assertEquals([
50 | 'en' => '1',
51 | ], $out);
52 | }
53 |
54 | public function test_isMl()
55 | {
56 | $value = [
57 | 'is-ml' => true,
58 | ];
59 |
60 | $out = isML($value);
61 |
62 | $this->assertEquals(true, $out);
63 |
64 | //
65 |
66 | $value = [
67 | 'is-ml' => false,
68 | ];
69 |
70 | $out = isML($value);
71 |
72 | $this->assertEquals(false, $out);
73 |
74 | //
75 |
76 | $value = [
77 | 'is-ml' => '',
78 | ];
79 |
80 | $out = isML($value);
81 |
82 | $this->assertEquals(false, $out);
83 | }
84 |
85 | public function test_isMD()
86 | {
87 | //Input expected '' from $value
88 |
89 | $value = [
90 | 'is-md' => true,
91 | ];
92 |
93 | $out = isMD($value);
94 | $this->assertEquals(true, $out);
95 |
96 | //
97 | $value = [
98 | 'is-md' => false,
99 | ];
100 |
101 | $out = isMD($value);
102 | $this->assertEquals(false, $out);
103 |
104 | //
105 |
106 | $value = [
107 | 'is-md' => '',
108 | ];
109 |
110 | $out = isMD($value);
111 | $this->assertEquals(false, $out);
112 | }
113 |
114 | public function test_isEM()
115 | {
116 | //Input expected 'EmbedsMany' from $value
117 |
118 | $value = 'EmbedsMany';
119 |
120 | $out = is_EM($value);
121 |
122 | $this->assertEquals(true, $out);
123 |
124 | //Input expected '' from $value
125 |
126 | $value = '';
127 |
128 | $out = is_EM($value);
129 |
130 | $this->assertEquals(false, $out);
131 | }
132 |
133 | public function test_isEO()
134 | {
135 | //Input expected 'EmbedsOne' from $value
136 |
137 | $value = 'EmbedsOne';
138 |
139 | $out = is_EO($value);
140 |
141 | $this->assertEquals(true, $out);
142 |
143 | //Input expected '' from $value
144 | $value = '';
145 |
146 | $out = is_EO($value);
147 |
148 | $this->assertEquals(false, $out);
149 | }
150 |
151 | public function test_isHM()
152 | {
153 | //Input expected 'Has Many' from $value
154 |
155 | $value = 'HasMany';
156 |
157 | $out = is_HM($value);
158 |
159 | $this->assertEquals(true, $out);
160 |
161 | //Input expected '' from $value
162 |
163 | $value = '';
164 |
165 | $out = is_HM($value);
166 |
167 | $this->assertEquals(false, $out);
168 | }
169 |
170 | public function test_isHO()
171 | {
172 | //Input expected 'HasOne' from $value
173 |
174 | $value = 'HasOne';
175 |
176 | $out = is_HO($value);
177 |
178 | $this->assertEquals(true, $out);
179 |
180 | //Input expected '' from $value
181 |
182 | $value = '';
183 |
184 | $out = is_HO($value);
185 |
186 | $this->assertEquals(false, $out);
187 | }
188 |
189 | public function test_isEditable()
190 | {
191 | $value = [
192 | 'is-editable' => false,
193 | ];
194 |
195 | $out = isEditable($value);
196 |
197 | $this->assertEquals(false, $out);
198 |
199 | //
200 |
201 | $value = [
202 | 'is-editable' => true,
203 | ];
204 |
205 | $out = isEditable($value);
206 |
207 | $this->assertEquals(true, $out);
208 |
209 | //
210 |
211 | $value = [
212 | 'is-editable' => '',
213 | ];
214 |
215 | $out = isEditable($value);
216 |
217 | $this->assertEquals('', $out);
218 | }
219 |
220 | public function test_hasTarget()
221 | {
222 | $value = [
223 | 'has-target' => false,
224 | ];
225 |
226 | $out = hasTarget($value);
227 |
228 | $this->assertEquals(false, $out);
229 |
230 | //
231 |
232 | $value = [
233 | 'has-target' => true,
234 | ];
235 |
236 | $out = hasTarget($value);
237 |
238 | $this->assertEquals(true, $out);
239 |
240 | //
241 |
242 | $value = [
243 | 'has-target' => '',
244 | ];
245 |
246 | $out = hasTarget($value);
247 |
248 | $this->assertEquals('', $out);
249 | }
250 |
251 | public function test_isFillable()
252 | {
253 | //
254 | $value = [];
255 | $event = '';
256 |
257 | $out = isFillable($value, $event);
258 |
259 | $this->assertEquals(isEditable($value), $out);
260 |
261 | //
262 |
263 | $value = '';
264 | $event = 'add';
265 |
266 | $out = isFillable($value, $event);
267 |
268 | $this->assertEquals(true, $out);
269 | }
270 |
271 | public function test_getAID()
272 | {
273 | //Check if there's no data inside the database, set id to 1
274 | Article::truncate();
275 | $article = new Article;
276 |
277 | $out = getAID($article);
278 |
279 | $this->assertEquals(1, $out);
280 |
281 | //If there's already data inside the database, increments new data by 1
282 |
283 | $articleModel = $this->prepareArticleData([]);
284 |
285 | $out = getAID($article);
286 |
287 | $this->assertEquals(2, $out);
288 |
289 | Article::truncate();
290 | }
291 |
292 | public function test_getArrayWithEmptyObj()
293 | {
294 | $article = new Article;
295 | $is_EO = true;
296 | $is_EM = [];
297 | $expectedArray = [
298 | (object) [
299 | 'autoincrement_id' => null,
300 | 'title' => null,
301 | 'content' => null,
302 | 'slug' => null,
303 | 'visibility' => null,
304 | 'status' => null,
305 | 'is_deleted' => null,
306 | 'is_active' => null,
307 | ],
308 | ];
309 | $out = getArrayWithEmptyObj($article, $is_EO, $is_EM);
310 |
311 | $this->assertEquals($expectedArray, $out);
312 | }
313 |
314 | public function test_getCounterForRelationships()
315 | {
316 | $is_EO = true;
317 | $is_EM = false;
318 | $i = null;
319 | $method = '';
320 |
321 | $out = getCounterForRelationships($method, $is_EO, $is_EM, $i);
322 |
323 | $this->assertEquals('', $out);
324 |
325 | //
326 |
327 | $is_EO = false;
328 | $is_EM = true;
329 | $i = null;
330 | $method = '';
331 |
332 | $out = getCounterForRelationships($method, $is_EO, $is_EM, $i);
333 |
334 | $this->assertEquals('', $out);
335 |
336 | //
337 |
338 | $is_EO = true;
339 | $is_EM = false;
340 | $i = null;
341 | $method = null;
342 |
343 | $out = getCounterForRelationships($method, $is_EO, $is_EM, $i);
344 |
345 | $this->assertEquals('', $out);
346 |
347 | //
348 |
349 | $is_EO = false;
350 | $is_EM = true;
351 | $i = null;
352 | $method = null;
353 |
354 | $out = getCounterForRelationships($method, $is_EO, $is_EM, $i);
355 |
356 | $this->assertEquals('-'.$i, $out);
357 | }
358 |
359 | public function test_getTypeOnTarget()
360 | {
361 | $EM = [
362 | 'typeOnTarget' => 'EmbedsMany',
363 | ];
364 | $EO = [
365 | 'typeOnTarget' => 'EmbedsOne',
366 | ];
367 | $defaultValue = [];
368 |
369 | $outEM = getTypeOnTarget($EM);
370 | $outEO = getTypeOnTarget($EO);
371 | $outDefaultValue = getTypeOnTarget($defaultValue);
372 |
373 | $this->assertEquals('EmbedsMany', $outEM);
374 | $this->assertEquals('EmbedsOne', $outEO);
375 | $this->assertEquals('EmbedsMany', $outDefaultValue);
376 | }
377 | }
378 |
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 | set('laravel-mongo-auto-sync.model_path', './tests/Models');
31 | $app['config']->set('laravel-mongo-auto-sync.model_namespace', 'Tests\Models');
32 |
33 | $config = require 'config/database.php';
34 |
35 | $app['config']->set('app.key', 'ZsZewWyUJ5FsKp9lMwv4tYbNlegQilM7');
36 |
37 | $app['config']->set('database.default', 'mongodb');
38 | $app['config']->set('database.connections.mongodb', $config['connections']['mongodb']);
39 | $app['config']->set('database.connections.mongodb2', $config['connections']['mongodb']);
40 | $app['config']->set('database.connections.dsn_mongodb', $config['connections']['dsn_mongodb']);
41 | $app['config']->set('database.connections.dsn_mongodb_db', $config['connections']['dsn_mongodb_db']);
42 |
43 | $app['config']->set('auth.model', 'User');
44 | $app['config']->set('auth.providers.users.model', 'User');
45 | $app['config']->set('cache.driver', 'array');
46 |
47 | $app['config']->set('queue.default', 'database');
48 | $app['config']->set('queue.connections.database', [
49 | 'driver' => 'mongodb',
50 | 'table' => 'jobs',
51 | 'queue' => 'default',
52 | 'expire' => 60,
53 | ]);
54 | $app['config']->set('queue.failed.database', 'mongodb2');
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/tests/UpdateWithSyncTest.php:
--------------------------------------------------------------------------------
1 | createSubItems(
20 | [
21 | 'text' => 'example sub item test',
22 | 'code' => 'HFGRT12345',
23 | 'href' => 'https://google.com',
24 | ]
25 | );
26 | $this->assertEquals('example sub item test', getTranslatedContent($sub_item->text));
27 | $this->assertEquals('HFGRT12345', $sub_item->code);
28 | $this->assertEquals('https://google.com', $sub_item->href);
29 |
30 | //Navigation Test
31 | $sub_items = json_encode(
32 | [
33 | (object) [
34 | 'ref_id' => $sub_item->id,
35 | 'text' => getTranslatedContent($sub_item->text),
36 | 'code' => $sub_item->code,
37 | 'href' => $sub_item->href,
38 | ],
39 | ]
40 | );
41 |
42 | $date = Date::now();
43 |
44 | $navigation = $this->createNavigation(
45 | [
46 | 'text' => 'example navigation text',
47 | 'code' => '1234ABHFGRT5',
48 | 'href' => 'https://www.netflix.com/browse',
49 | 'date' => $date,
50 | 'target' => '_blank',
51 | 'title' => 'Random title',
52 | 'sub_items' => $sub_items,
53 | ]
54 | );
55 |
56 | $this->assertTrue($this->isNavigationCreated($navigation));
57 | $this->assertIsString($navigation->text);
58 |
59 | $this->assertEquals('example navigation text', $navigation->text);
60 | $this->assertEquals('1234ABHFGRT5', $navigation->code);
61 | $this->assertEquals('https://www.netflix.com/browse', $navigation->href);
62 | //$this->assertEquals($date, $navigation->date); TODO: Precision to be fixed
63 | $this->assertEquals('_blank', $navigation->target);
64 | $this->assertEquals('Random title', getTranslatedContent($navigation->title));
65 | $this->assertInstanceOf(MongoCollection::class, $navigation->sub_items);
66 |
67 | //Check target
68 | $sub_item = SubItem::find($sub_item->id);
69 | $mini_navigation = $sub_item->navigation;
70 | $this->assertNotNull($mini_navigation);
71 |
72 | $this->assertEquals($navigation->id, $mini_navigation->ref_id);
73 | $this->assertEquals('1234ABHFGRT5', $mini_navigation->code);
74 | $this->assertEquals('Random title', getTranslatedContent($mini_navigation->title));
75 | $this->assertEquals('example navigation text', $navigation->text);
76 |
77 | //clean data
78 | $navigation->delete();
79 | $sub_item->delete();
80 | }
81 |
82 | public function test_update_with_embeds_many_on_target()
83 | {
84 | $faker = Factory::create();
85 |
86 | $navigation = new Navigation;
87 |
88 | $text = $faker->text(50);
89 | $code = $faker->creditCardNumber;
90 | $href = $faker->url;
91 | $date = Date::now();
92 | $target = $faker->text(50);
93 | $title = null;
94 | $items = json_encode([]);
95 |
96 | $arr = [
97 | 'text' => $text,
98 | 'code' => $code,
99 | 'href' => $href,
100 | 'date' => $date,
101 | 'target' => $target,
102 | 'title' => $title,
103 | 'sub_items' => $items,
104 | ];
105 | $request = new Request;
106 | $navigation = $navigation->storeWithSync($request, $arr);
107 |
108 | $this->assertTrue($this->isNavigationCreated($navigation));
109 | $this->assertEquals($text, $navigation->text);
110 |
111 | $this->assertEquals($text, $navigation->text);
112 | $this->assertEquals($code, $navigation->code);
113 | $this->assertEquals($href, $navigation->href);
114 | // $this->assertEquals($date, $navigation->date); TODO: Precision to be fixed
115 | $this->assertEquals($target, $navigation->target);
116 | $this->assertEquals($title, getTranslatedContent($navigation->title));
117 | $this->assertInstanceOf(MongoCollection::class, $navigation->sub_items);
118 | //Check target TODO
119 |
120 | $mini_navigation = $this->getMiniNavigation($navigation->id);
121 |
122 | $data = [
123 | 'navigation' => $mini_navigation,
124 | ];
125 |
126 | $sub_item = $this->createSubItems($data);
127 |
128 | $this->assertEquals($navigation->id, $sub_item->navigation->ref_id);
129 | $this->assertInstanceOf(MiniNavigation::class, $sub_item->navigation);
130 |
131 | //Check target
132 | $navigation_original = Navigation::find($navigation->id);
133 |
134 | /*$sub_item_mini = $navigation->sub_items[0];
135 |
136 | $this->assertNotEmpty($navigation_original->sub_items);
137 | $this->assertEquals($sub_item->id, $sub_item_mini->ref_id);
138 | $this->assertEquals($sub_item->text, $sub_item_mini->text);
139 | $this->assertEquals($sub_item->code, $sub_item_mini->code);
140 | $this->assertEquals($sub_item->title, $sub_item_mini->title);*/
141 |
142 | //Add more sub items and restart test
143 | $sub_items = $this->getMiniSubItem($sub_item->id);
144 | $date = Carbon::now();
145 | $data = [
146 | 'text' => 'text_updated',
147 | 'title' => 'title_updated',
148 | 'code' => 'code_updated',
149 | 'href' => 'href_updated',
150 | 'date' => $date,
151 | 'target' => 'target_updated',
152 | 'sub_items' => $sub_items,
153 | ];
154 |
155 | $options = [];
156 | $request = new Request;
157 | $navigation_updated = $navigation_original->updateWithSync($request, $data, $options);
158 |
159 | $this->assertEquals('text_updated', $navigation_updated->text);
160 | $this->assertEquals('title_updated', getTranslatedContent($navigation_updated->title));
161 | $this->assertEquals('code_updated', $navigation_updated->code);
162 | $this->assertEquals('href_updated', $navigation_updated->href);
163 | //$this->assertEquals($date,$navigation_updated->date );TODO: fix precision
164 | $this->assertEquals('target_updated', $navigation_updated->target);
165 | $this->assertEquals(1, $navigation_updated->sub_items->count());
166 |
167 | $mini_navigation = $this->getMiniNavigation($navigation->id);
168 | $data = [
169 | 'navigation' => $mini_navigation,
170 | ];
171 |
172 | $sub_item = $this->createSubItems($data);
173 | $navigation = Navigation::find($navigation->id);
174 |
175 | /*$this->assertTrue($navigation->sub_items->count() == 4);
176 |
177 | $sub_item_mini = $navigation->sub_items->where('ref_id', $sub_item->id)->first();
178 |
179 | $this->assertEquals($sub_item->id, $sub_item_mini->ref_id);
180 | $this->assertEquals($sub_item->text, $sub_item_mini->text);
181 | $this->assertEquals($sub_item->code, $sub_item_mini->code);
182 | $this->assertEquals($sub_item->title, $sub_item_mini->title);*/
183 |
184 | //clean data
185 | $navigation->delete();
186 | $sub_item->delete();
187 | }
188 |
189 | public function test_update_with_partial_request_updating_embeds_many_on_target()
190 | {
191 | $faker = Factory::create();
192 |
193 | $navigation = new Navigation;
194 | $navigation = $navigation->storeWithSync(new Request, [
195 | 'text' => $faker->text(50),
196 | 'code' => $faker->creditCardNumber,
197 | 'href' => $faker->url,
198 | 'date' => Date::now(),
199 | 'target' => $faker->text(50),
200 | 'title' => null,
201 | 'sub_items' => json_encode([]),
202 | ]);
203 |
204 | $this->assertTrue($this->isNavigationCreated($navigation));
205 | $this->assertInstanceOf(MongoCollection::class, $navigation->sub_items);
206 |
207 | // 1 navigation
208 |
209 | $sub_item = $this->createSubItems([
210 | 'navigation' => $this->getMiniNavigation($navigation->id),
211 | ]);
212 |
213 | $this->assertEquals($navigation->id, $sub_item->navigation->ref_id);
214 | $this->assertInstanceOf(MiniNavigation::class, $sub_item->navigation);
215 |
216 | // 1 navigation and 1 sub item with navigation
217 |
218 | $navigation_original = Navigation::find($navigation->id);
219 |
220 | $sub_items = $this->getMiniSubItem($sub_item->id);
221 |
222 | $navigation_updated = $navigation_original->updateWithSync(new Request, [
223 | 'text' => 'text_updated',
224 | 'title' => 'title_updated',
225 | 'code' => 'code_updated',
226 | 'href' => 'href_updated',
227 | 'date' => Carbon::now(),
228 | 'target' => 'target_updated',
229 | 'sub_items' => $sub_items,
230 | ], []);
231 |
232 | $this->assertEquals(1, $navigation_updated->sub_items->count());
233 |
234 | $sub_item = $this->createSubItems([
235 | 'navigation' => $this->getMiniNavigation($navigation->id),
236 | ]);
237 |
238 | $navigation = Navigation::find($navigation->id);
239 | $this->assertEquals(2, $navigation->sub_items->count());
240 |
241 | // 1 navigation with 2 sub items and 1 sub item with 1 navigation
242 |
243 | $sub_item->updateWithSync(new Request, [
244 | 'code' => 'partial_code_update',
245 | ], [
246 | 'request_type' => 'partial',
247 | ]);
248 |
249 | $navigation = Navigation::find($navigation->id);
250 | $this->assertEquals(2, $navigation->sub_items->count());
251 |
252 | foreach ($navigation->sub_items as $navigation_sub_item) {
253 | if ($navigation_sub_item->ref_id == $sub_item->id) {
254 | $this->assertEquals('partial_code_update', $navigation_sub_item->code);
255 | }
256 | }
257 |
258 | // 1 navigation with 2 sub items (1 of these updated) and 1 sub item with 1 navigation
259 |
260 | //clean data
261 | $navigation->delete();
262 | $sub_item->delete();
263 | }
264 |
265 | public function test_update_with_partial_request_plain_field()
266 | {
267 | //Navigation
268 | $this->partialUpdateNavigation();
269 |
270 | //SubItems
271 | $this->partialUpdateSubItems();
272 | }
273 |
274 | public function test_update_with_partial_request_relationship_field()
275 | {
276 | //Navigation
277 | $this->partialUpdateNavigationRelationship();
278 |
279 | //SubItem
280 | $this->partialUpdateSubItemsRelationship();
281 | }
282 |
283 | private function partialUpdateNavigation()
284 | {
285 | //Create a navigation and associated to the sub item on creation
286 | $navigation_original = $this->createNavigation();
287 |
288 | $data = [
289 | 'text' => 'updated',
290 | 'title' => 'updated',
291 | ];
292 |
293 | $options = [
294 | 'request_type' => 'partial',
295 | ];
296 | $request = new Request;
297 | $navigation_new = $navigation_original->updateWithSync($request, $data, $options);
298 |
299 | //text has been updated?
300 | $this->assertEquals('updated', $navigation_new->text);
301 | $this->assertEquals('updated', $navigation_new->title[cl()]);
302 |
303 | //all the other fields has not been updated?
304 | $this->assertEquals($navigation_original->code, $navigation_new->code);
305 | $this->assertEquals($navigation_original->href, $navigation_new->href);
306 | $this->assertEquals($navigation_original->date, $navigation_new->date);
307 | $this->assertEquals($navigation_original->target, $navigation_new->target);
308 | $this->assertEquals($navigation_original->sub_items, $navigation_new->sub_items);
309 |
310 | //clean data
311 | $navigation_new->delete();
312 | }
313 |
314 | private function partialUpdateSubItems()
315 | {
316 | //Create a navigation and associated to the sub item on creation
317 | $sub_item_original = $this->createSubItems();
318 |
319 | $data = [
320 | 'text' => 'updated',
321 | 'code' => 'updated',
322 | ];
323 |
324 | $options = [
325 | 'request_type' => 'partial',
326 | ];
327 | $request = new Request;
328 | $sub_item_new = $sub_item_original->updateWithSync($request, $data, $options);
329 |
330 | //text has been updated?
331 | $this->assertEquals('updated', $sub_item_new->text[cl()]);
332 | $this->assertEquals('updated', $sub_item_new->code);
333 |
334 | //all the other fields has not been updated?
335 | $this->assertEquals($sub_item_original->navigation->getAttributes(), $sub_item_new->navigation->getAttributes());
336 | $this->assertEquals($sub_item_original->href, $sub_item_new->href);
337 |
338 | //clean data
339 | $sub_item_new->delete();
340 | }
341 |
342 | private function test_is_skippable_on_processAllRelationships()
343 | {
344 | $this->markTestSkipped('to be implemented');
345 |
346 | /*
347 | *
348 | Relation type
349 | "relation" => [
350 | "type" => "EmbedsMany",
351 | "mode" => "classic",
352 | "model" => "App\Models\MiniRelation",
353 | "has-target" => false
354 | ]
355 |
356 | Request type
357 | [
358 | 'request_type' => 'partial'
359 | ]
360 | * */
361 | }
362 |
363 | private function partialUpdateNavigationRelationship()
364 | {
365 | //Create a sub_items and associated to the navigation on update
366 | $navigation_original = $this->createNavigation();
367 | $sub_item_original = $this->createSubItems();
368 |
369 | //Test Update from SubItem
370 | $mini_sub_items = $this->getMiniSubItem($sub_item_original->id);
371 | $data = [
372 | 'sub_items' => $mini_sub_items,
373 | ];
374 |
375 | $options = [
376 | 'request_type' => 'partial',
377 | ];
378 | $request = new Request;
379 | $navigation_updated = $navigation_original->updateWithSync($request, $data, $options);
380 | $mini_sub_item_updated = $navigation_updated->sub_items[0];
381 | $mini_sub_item_original = json_decode($mini_sub_items)[0];
382 |
383 | //navigation has been updated?
384 | $this->assertNotEmpty($navigation_updated->sub_items);
385 | $this->assertNotNull($mini_sub_item_updated);
386 |
387 | $this->assertEquals($mini_sub_item_original->ref_id, $mini_sub_item_updated->ref_id);
388 | $this->assertEquals($mini_sub_item_original->text, $mini_sub_item_updated->text[cl()]);
389 | $this->assertEquals($mini_sub_item_original->code, $mini_sub_item_updated->code);
390 | $this->assertEquals($mini_sub_item_original->href, $mini_sub_item_updated->href);
391 |
392 | //all the other fields has not been updated?
393 | $this->assertEquals($navigation_original->title[cl()], $navigation_updated->title[cl()]);
394 | $this->assertEquals($navigation_original->code, $navigation_updated->code);
395 | $this->assertEquals($navigation_original->href, $navigation_updated->href);
396 | $this->assertEquals($navigation_original->title, $navigation_updated->title);
397 | $this->assertEquals($navigation_original->date, $navigation_updated->date);
398 | $this->assertEquals($navigation_original->target, $navigation_updated->target);
399 |
400 | //check target - Sub_item
401 | $sub_item = SubItem::all()->where('id', $sub_item_original->id)->first();
402 |
403 | $this->assertEquals($navigation_updated->id, $sub_item->navigation->ref_id);
404 |
405 | $sub_item_original->delete();
406 | $navigation_original->delete();
407 | }
408 |
409 | private function partialUpdateSubItemsRelationship()
410 | {
411 | $navigation_original = $this->createNavigation();
412 | $mini_navigation_original = $this->getMiniNavigation($navigation_original->id);
413 |
414 | $sub_item_original = $this->createSubItems(['navigation' => $mini_navigation_original]);
415 | $navigation = $this->createNavigation();
416 |
417 | $original_count_subitems = $navigation->sub_items->count();
418 | //Test Update from SubItem
419 | $mini_navigation = $this->getMiniNavigation($navigation->id);
420 | $data = [
421 | 'navigation' => $mini_navigation,
422 | ];
423 |
424 | $options = [
425 | 'request_type' => 'partial',
426 | ];
427 | $request = new Request;
428 |
429 | $sub_item_updated = $sub_item_original->updateWithSync($request, $data, $options);
430 |
431 | //navigation has been updated?
432 | $this->assertNotEquals($sub_item_original->navigation->getAttributes(), $sub_item_updated->navigation->getAttributes());
433 | $this->assertNotNull($sub_item_updated->navigation);
434 |
435 | $navigation = Navigation::find($navigation->id);
436 | $updated_count_subitems = $navigation->sub_items->count();
437 |
438 | $this->assertEquals($navigation->id, $sub_item_updated->navigation->ref_id);
439 | $this->assertEquals($navigation->text, $sub_item_updated->navigation->text);
440 | $this->assertEquals($navigation->code, $sub_item_updated->navigation->code);
441 | $this->assertEquals($navigation->title[cl()], $sub_item_updated->navigation->title[cl()]);
442 |
443 | //all the other fields has not been updated?
444 | $this->assertEquals($sub_item_original->text[cl()], $sub_item_updated->text[cl()]);
445 | $this->assertEquals($sub_item_original->code, $sub_item_updated->code);
446 | $this->assertEquals($sub_item_original->href, $sub_item_updated->href);
447 |
448 | //check target - Navigation
449 |
450 | $this->assertTrue($navigation->sub_items->where('ref_id', $sub_item_updated->id)->count() === 1);
451 |
452 | //check target - Navigation subitem has been detached from navigation original?
453 | $navigation = Navigation::all()->where('id', $navigation_original->id)->first();
454 |
455 | $this->assertTrue($navigation->sub_items->where('ref_id', $sub_item_updated->id)->count() === 0);
456 |
457 | $this->assertEquals(1, $updated_count_subitems);
458 |
459 | //Update with a target already populated
460 |
461 | $mini_navigation = $this->getMiniNavigation($navigation->id);
462 | $data = [
463 | 'code' => 'code_updated',
464 | ];
465 |
466 | $options = [
467 | 'request_type' => 'partial',
468 | ];
469 | $request = new Request;
470 |
471 | $sub_item_updated = $sub_item_original->updateWithSync($request, $data, $options);
472 |
473 | $navigation = Navigation::find($navigation->id);
474 | $updated_count_subitems = $navigation->sub_items->count();
475 |
476 | $this->assertEquals($sub_item_updated->code, 'code_updated');
477 | $this->assertEquals(1, $updated_count_subitems);
478 |
479 | $subitem = $navigation->sub_items->first();
480 | $this->assertEquals($subitem->code, 'code_updated');
481 |
482 | $sub_item_original->delete();
483 | $navigation->delete();
484 | }
485 | }
486 |
--------------------------------------------------------------------------------
/tests/config/database.php:
--------------------------------------------------------------------------------
1 | [
10 |
11 | 'mongodb' => [
12 | 'name' => 'mongodb',
13 | 'driver' => 'mongodb',
14 | 'host' => $mongoHost,
15 | 'database' => env('MONGO_DATABASE', 'unittest'),
16 | ],
17 |
18 | 'dsn_mongodb' => [
19 | 'driver' => 'mongodb',
20 | 'dsn' => "mongodb://$mongoHost:$mongoPort",
21 | 'database' => env('MONGO_DATABASE', 'unittest'),
22 | ],
23 |
24 | 'dsn_mongodb_db' => [
25 | 'driver' => 'mongodb',
26 | 'dsn' => "mongodb://$mongoHost:$mongoPort/".env('MONGO_DATABASE', 'unittest'),
27 | ],
28 |
29 | 'mysql' => [
30 | 'driver' => 'mysql',
31 | 'host' => env('MYSQL_HOST', 'mysql'),
32 | 'port' => $mysqlPort,
33 | 'database' => env('MYSQL_DATABASE', 'unittest'),
34 | 'username' => env('MYSQL_USERNAME', 'root'),
35 | 'password' => env('MYSQL_PASSWORD', ''),
36 | 'charset' => 'utf8',
37 | 'collation' => 'utf8_unicode_ci',
38 | 'prefix' => '',
39 | ],
40 | ],
41 |
42 | ];
43 |
--------------------------------------------------------------------------------
/tests/config/queue.php:
--------------------------------------------------------------------------------
1 | env('QUEUE_CONNECTION'),
6 |
7 | 'connections' => [
8 |
9 | 'database' => [
10 | 'driver' => 'mongodb',
11 | 'table' => 'jobs',
12 | 'queue' => 'default',
13 | 'expire' => 60,
14 | ],
15 |
16 | ],
17 |
18 | 'failed' => [
19 | 'database' => env('MONGO_DATABASE'),
20 | 'table' => 'failed_jobs',
21 | ],
22 |
23 | ];
24 |
--------------------------------------------------------------------------------