├── .github
├── logo.jpg
└── workflows
│ └── main.yml
├── .gitignore
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── composer.json
├── phpstan.neon
├── phpunit.xml
├── src
├── Model
│ ├── Builder
│ │ └── OrderBuilder.php
│ ├── Customer.php
│ ├── Item.php
│ ├── Meta
│ │ └── ItemMeta.php
│ ├── Order.php
│ ├── Product.php
│ ├── ProductAttribute.php
│ ├── ProductCategory.php
│ ├── ProductTag.php
│ └── ProductType.php
├── Support
│ ├── Address.php
│ ├── BillingAddress.php
│ ├── Payment.php
│ └── ShippingAddress.php
├── Traits
│ ├── AddressesTrait.php
│ └── HasRelationsThroughMeta.php
└── WooCommerce.php
├── stubs
└── Corcel.stub
└── tests
├── TestCase.php
├── Unit
├── Model
│ ├── CustomerTest.php
│ ├── ItemTest.php
│ ├── OrderTest.php
│ ├── ProductAttributeTest.php
│ └── ProductTest.php
├── Support
│ ├── AddressTest.php
│ ├── BillingAddressTest.php
│ ├── PaymentTest.php
│ └── ShippingAddressTest.php
├── Traits
│ └── HasRelationsThroughMetaTest.php
└── WooCommerceTest.php
└── database
├── factories
├── CustomerFactory.php
├── ItemFactory.php
├── OrderFactory.php
└── ProductFactory.php
└── migrations
├── 2020_01_01_000000_create_options_table.php
├── 2020_01_01_000000_create_postmeta_table.php
├── 2020_01_01_000000_create_posts_table.php
├── 2020_01_01_000000_create_term_relationships_table.php
├── 2020_01_01_000000_create_term_taxonomy_table.php
├── 2020_01_01_000000_create_terms_table.php
├── 2020_01_01_000000_create_usermeta_table.php
├── 2020_01_01_000000_create_users_table.php
├── 2020_01_01_000000_create_woocommerce_attribute_taxonomies_table.php
├── 2020_01_01_000000_create_woocommerce_order_itemmeta_table.php
└── 2020_01_01_000000_create_woocommerce_order_items_table.php
/.github/logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/corcel/woocommerce/d2921dc3f2d32b751628b8a889be96f2be506fdf/.github/logo.jpg
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | # This is a basic workflow to help you get started with Actions
2 |
3 | name: CI
4 |
5 | # Controls when the action will run. Triggers the workflow on every push
6 | on: push
7 |
8 | jobs:
9 | run:
10 |
11 | strategy:
12 | matrix:
13 | php-version:
14 | - "8.2"
15 | - "8.3"
16 | - "8.4"
17 | operating-system:
18 | - ubuntu-latest
19 | - windows-latest
20 |
21 | runs-on: ${{ matrix.operating-system }}
22 |
23 | name: Analyse and test code (PHP ${{ matrix.php-version }}, ${{ matrix.operating-system }})
24 |
25 | steps:
26 |
27 | - name: Checkout
28 | uses: actions/checkout@v4
29 |
30 | - name: Setup PHP
31 | uses: shivammathur/setup-php@v2
32 | with:
33 | php-version: "${{ matrix.php-version }}"
34 | extensions: sqlite, pdo_sqlite, fileinfo
35 |
36 | - name: Get composer cache directory
37 | id: composercache
38 | run: echo "::set-output name=dir::$(composer config cache-files-dir)"
39 |
40 | - name: Cache dependencies
41 | uses: actions/cache@v4
42 | with:
43 | path: ${{ steps.composercache.outputs.dir }}
44 | key: php-${{ matrix.php-version }}-composer-${{ hashFiles('**/composer.json') }}
45 | restore-keys: php-${{ matrix.php-version }}-composer-
46 |
47 | - name: Install dependencies
48 | run: composer update --no-interaction --no-progress
49 |
50 | - name: PHPStan
51 | run: vendor/bin/phpstan analyse
52 |
53 | - name: PHPUnit
54 | run: vendor/bin/phpunit
55 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | composer.lock
3 | .phpunit.result.cache
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # WooCommerce Corcel Plugin changelog
2 |
3 | ## v6.0.0 - 2025-04-29
4 |
5 | * Laravel 12 support (#43)
6 | * Add support for Corcel v9
7 |
8 | ## v5.0.1 - 2024-06-16
9 |
10 | * Add support for Corcel v8 (#41)
11 |
12 | ## v5.0.0 - 2024-05-15
13 |
14 | * Laravel 11 support (#37, #40)
15 | * Add flexibility to inherit the models and define and update the model factories (#38, #39)
16 |
17 | ## v4.0.0 - 2023-06-12
18 |
19 | * Laravel 10 support (#35)
20 |
21 | ## v3.0.0 - 2022-06-25
22 |
23 | * Laravel 9 support (#29)
24 |
25 | ## v2.1.1 - 2022-06-25
26 |
27 | * Fix WooCommerce::currency() method return type (#30)
28 |
29 | ## v2.1.0 - 2021-10-21
30 |
31 | * PHP 8.0 support (c95576e)
32 |
33 | ## v2.0.3 - 2020-12-10
34 |
35 | * Fix: allow address to work with subclasses (#20)
36 |
37 | ## v2.0.2 - 2020-10-30
38 |
39 | * Fix error with parsing order completed and paid date from timestamp (#19)
40 |
41 | ## v2.0.1 - 2020-10-29
42 |
43 | * Fix invalid typehint in ProductAttribute model (#17)
44 |
45 | ## v2.0.0 - 2020-10-10
46 |
47 | * Add support for Corcel 5.x and Laravel 8.x
48 | * Drop support for PHP 7.2
49 |
50 | ## v1.0.1 - 2020-10-04
51 |
52 | * PHP 7.2 compatibility (f4d8265)
53 |
54 | ## v1.0.0 - 2020-10-04
55 |
56 | * Inital release
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at krzysztof@grabania.pl. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017-2020 Grabania.pl Krzysztof Grabania
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 |
2 |
3 |
4 |
5 |
6 | **A collection of Laravel models for WooCommerce.**
7 |
8 | This plugin extends base [Corcel](https://github.com/corcel/corcel) package and allows fetching WooCommerce data from WordPress database. Currently this plugin implements the following models:
9 |
10 | * [Customer](#customer-model) - wrapper for User model
11 | * [Order](#order-model) - wrapper for Post model
12 | * [Product](#product-model) - wrapper for Post model
13 | * [Item](#item-model)
14 | * Product Category - wrapper for Taxonomy model
15 | * Product Tag - wrapper for Taxonomy model
16 | * Product Attribute - helper model for getting product attributes (should not be used directly)
17 | * Product Type - helper model for getting product types (should not be used directly)
18 |
19 | Some meta values are collected into helper classes:
20 |
21 | * [BillingAddress](#billingaddress-helper) - helper for customer and order billing address
22 | * [ShippingAddress](#shippingaddress-helper) - helper for customer and order shipping address
23 | * [Payment](#payment-helper) - helper for order payment
24 |
25 | ## Compatibility list
26 |
27 | | Corcel WooCommerce | Laravel | PHP version | Supported |
28 | | ----------------------------------------------------- | -------------- | ------------- | ------------------ |
29 | | 6.x (master) | 11.x, 12.x | >= 8.2 | :white_check_mark: |
30 | | [5.x](https://github.com/corcel/woocommerce/tree/5.x) | 10.x, 11.x | >= 8.2 | :white_check_mark: |
31 | | [4.x](https://github.com/corcel/woocommerce/tree/4.x) | 10.x | >= 8.1 | :x: |
32 | | [3.x](https://github.com/corcel/woocommerce/tree/3.x) | 9.x | >= 8.0.3 | :x: |
33 | | [2.x](https://github.com/corcel/woocommerce/tree/2.x) | 6.x, 7.x, 8.x | >= 7.3 \| 8.0 | :x: |
34 | | [1.x](https://github.com/corcel/woocommerce/tree/1.x) | 6.x, 7.x | >= 7.2 | :x: |
35 |
36 | ## Installation
37 |
38 | ```bash
39 | composer require corcel/woocommerce
40 | ```
41 |
42 | ## Models list
43 |
44 | ### Customer model
45 |
46 | #### Get customer by id
47 |
48 | ```php
49 | $customer = Customer::find(1);
50 | ```
51 |
52 | #### Customer relation
53 |
54 | ```php
55 | $customer = Customer::find(1);
56 |
57 | $customerOrders = $customer->orders;
58 | ```
59 |
60 | #### Customer properties
61 |
62 | ```php
63 | $customer = Customer::find(1);
64 |
65 | $customer->order_count; // e.g. 10
66 | $customer->billing_address; // \Corcel\WooCommerce\Support\BillingAddress class instance
67 | $customer->shipping_address; // \Corcel\WooCommerce\Support\ShippingAddress class instance
68 | ```
69 |
70 | ### Order model
71 |
72 | #### Get order by id
73 |
74 | ```php
75 | $order = Order::find(1);
76 | ```
77 |
78 | #### Get completed orders
79 |
80 | ```php
81 | $completedOrders = Order::completed()->get();
82 | ```
83 |
84 | *For other statuses methods please check [OrderBuilder.php](src/Model/Builder/OrderBuilder.php).*
85 |
86 | #### Order relations
87 |
88 | ```php
89 | $order = Order::find(1);
90 |
91 | $orderItems = $order->items;
92 | $orderCustomer = $order->customer;
93 | ```
94 |
95 | #### Order properties
96 |
97 | ```php
98 | $order = Order::find(1);
99 |
100 | $order->currency; // e.g. EUR
101 | $order->total; // e.g. 10.20
102 | $order->tax; // e.g. 0.50
103 | $order->shipping_tax; // e.g. 0.20
104 | $order->status; // e.g. completed
105 | $order->date_completed; // e.g. 2020-06-01 10:00:00
106 | $order->date_paid; // e.g. 2020-06-01 10:00:00
107 | $order->payment; // \Corcel\WooCommerce\Support\Payment class instance
108 | $order->billing_address; // \Corcel\WooCommerce\Support\BillingAddress class instance
109 | $order->shipping_address; // \Corcel\WooCommerce\Support\ShippingAddress class instance
110 | ```
111 |
112 | ### Item model
113 |
114 | #### Get item by id
115 |
116 | ```php
117 | $item = Item::find(1);
118 | ```
119 |
120 | #### Item relations
121 |
122 | ```php
123 | $item = Item::find(1);
124 |
125 | $itemOrder = $item->order;
126 | $itemProduct = $item->product;
127 | ```
128 |
129 | #### Item properties
130 |
131 | ```php
132 | $item = Item::find(1);
133 |
134 | $item->order_item_id;
135 | $item->order_item_name;
136 | $item->order_item_type;
137 | $item->order_id;
138 | $item->product_id;
139 | $item->variation_id;
140 | $item->quantity; // e.g. 2
141 | $item->tax_class;
142 | $item->line_subtotal; // e.g. 5.50
143 | $item->line_subtotal_tax; // e.g. 0.50
144 | $item->line_total; // e.g. 10.50
145 | $item->line_tax; // e.g. 2.00
146 | ```
147 |
148 | ### Product model
149 |
150 | #### Get product by id
151 |
152 | ```php
153 | $product = Product::find(1);
154 | ```
155 |
156 | #### Product relations
157 |
158 | ```php
159 | $product = Product::find(1);
160 |
161 | $product->categories;
162 | $product->items;
163 | $product->tags;
164 | ```
165 |
166 | #### Product properties
167 |
168 | ```php
169 | $product = Product::find(1);
170 |
171 | $product->price;
172 | $product->regular_price;
173 | $product->sale_price;
174 | $product->on_sale;
175 | $product->sku;
176 | $product->tax_status;
177 | $product->is_taxable;
178 | $product->weight;
179 | $product->length;
180 | $product->width;
181 | $product->height;
182 | $product->is_virtual;
183 | $product->is_downloadable;
184 | $product->stock;
185 | $product->in_stock;
186 | $product->type;
187 | $product->attributes; // Collection of (variation) attributes
188 | $product->crosssells; // Collection of cross-sell products
189 | $product->upsells; // Collection of up-sell products
190 | $product->gallery; // Collection of gallery attachments
191 | ```
192 |
193 | ## Helper classes list
194 |
195 | ### BillingAddress helper
196 |
197 | This class collects customer and order meta related to billing address.
198 |
199 | ```php
200 | $order = Order::find(1);
201 | $address = $order->billingAddress;
202 |
203 | $address->first_name;
204 | $address->last_name;
205 | $address->company;
206 | $address->address_1;
207 | $address->address_2;
208 | $address->city;
209 | $address->state;
210 | $address->postcode;
211 | $address->country;
212 | $address->email;
213 | $address->phone;
214 | ```
215 |
216 | ### ShippingAddress helper
217 |
218 | This class collects customer and order meta related to billing address.
219 |
220 | ```php
221 | $order = Order::find(1);
222 | $address = $order->shippingAddress;
223 |
224 | $address->first_name;
225 | $address->last_name;
226 | $address->company;
227 | $address->address_1;
228 | $address->address_2;
229 | $address->city;
230 | $address->state;
231 | $address->postcode;
232 | $address->country;
233 | ```
234 |
235 | ### Payment helper
236 |
237 | This class collects order meta related to payment.
238 |
239 | ```php
240 | $order = Order::find(1);
241 | $payment = $order->payment;
242 |
243 | $payment->method;
244 | $payment->method_title;
245 | $payment->transaction_id;
246 | ```
247 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "corcel/woocommerce",
3 | "description": "WooCommerce plugin for Corcel",
4 | "homepage": "http://github.com/corcel/woocommerce",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Krzysztof Grabania",
9 | "email": "krzysztof@grabania.pl",
10 | "homepage": "https://grabania.pl"
11 | }
12 | ],
13 | "require": {
14 | "php": "^8.2",
15 | "illuminate/database": "^11.0|^12.0",
16 | "illuminate/support": "^11.0|^12.0",
17 | "jgrossi/corcel": "^8.0|^9.0",
18 | "nesbot/carbon": "^2.66|^3.0"
19 | },
20 | "require-dev": {
21 | "orchestra/testbench": "^8.0|^9.0|^10.0",
22 | "phpstan/phpstan": "^1.9|^2.1",
23 | "phpunit/phpunit": "^9.5.10|^10.5|^11.5.3",
24 | "larastan/larastan": "^2.4|^3.0",
25 | "laravel/pint": "^1.4"
26 | },
27 | "autoload": {
28 | "psr-4": {
29 | "Corcel\\WooCommerce\\": "src/"
30 | }
31 | },
32 | "autoload-dev": {
33 | "psr-4": {
34 | "Tests\\": "tests/",
35 | "Database\\Factories\\": "tests/database/factories/"
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/phpstan.neon:
--------------------------------------------------------------------------------
1 | includes:
2 | - ./vendor/larastan/larastan/extension.neon
3 |
4 | parameters:
5 | paths:
6 | - src
7 | - tests
8 |
9 | level: max
10 |
11 | noUnnecessaryCollectionCall: false
12 |
13 | stubFiles:
14 | - stubs/Corcel.stub
15 |
16 | ignoreErrors:
17 | -
18 | message: '#Access to an undefined property Faker\\Generator::\$[a-zA-Z]+?\.#'
19 | path: tests/*
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 | src/
18 |
19 |
20 |
21 |
22 |
23 | ./tests/Unit/
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/Model/Builder/OrderBuilder.php:
--------------------------------------------------------------------------------
1 | status('cancelled');
17 | }
18 |
19 | /**
20 | * Scope a query to only completed orders.
21 | */
22 | public function completed(): PostBuilder
23 | {
24 | return $this->status('completed');
25 | }
26 |
27 | /**
28 | * Scope a query to only failed orders.
29 | */
30 | public function failed(): PostBuilder
31 | {
32 | return $this->status('failed');
33 | }
34 |
35 | /**
36 | * Scope a query to only on hold orders.
37 | */
38 | public function onHold(): PostBuilder
39 | {
40 | return $this->status('on-hold');
41 | }
42 |
43 | /**
44 | * Scope a query to only pending orders.
45 | */
46 | public function pending(): PostBuilder
47 | {
48 | return $this->status('pending');
49 | }
50 |
51 | /**
52 | * Scope a query to only processing orders.
53 | */
54 | public function processing(): PostBuilder
55 | {
56 | return $this->status('processing');
57 | }
58 |
59 | /**
60 | * Scope a query to only refunded orders.
61 | */
62 | public function refunded(): PostBuilder
63 | {
64 | return $this->status('refunded');
65 | }
66 |
67 | /**
68 | * Scope a query to orders with given status.
69 | */
70 | public function status($status): PostBuilder
71 | {
72 | $status = substr($status, 0, 3) === 'wc-' ? substr($status, 3) : $status;
73 |
74 | $builtin = [
75 | 'cancelled',
76 | 'completed',
77 | 'failed',
78 | 'on-hold',
79 | 'pending',
80 | 'processing',
81 | 'refunded',
82 | ];
83 |
84 | if (in_array($status, $builtin)) {
85 | $status = 'wc-'.$status;
86 | }
87 |
88 | return parent::status($status);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/Model/Customer.php:
--------------------------------------------------------------------------------
1 | $orders
17 | */
18 | class Customer extends User
19 | {
20 | use AddressesTrait;
21 |
22 | /** @use HasFactory */
23 | use HasFactory;
24 |
25 | /** @use HasRelationsThroughMeta<\Illuminate\Database\Eloquent\Model, $this> */
26 | use HasRelationsThroughMeta;
27 |
28 | /**
29 | * {@inheritDoc}
30 | *
31 | * @var array
32 | */
33 | protected $appends = [
34 | 'order_count',
35 | ];
36 |
37 | /**
38 | * Create a new factory instance for the model.
39 | *
40 | * @return CustomerFactory
41 | */
42 | protected static function newFactory()
43 | {
44 | return CustomerFactory::new();
45 | }
46 |
47 | /**
48 | * Get order count attribute.
49 | */
50 | protected function getOrderCountAttribute(): int
51 | {
52 | $count = $this->getMeta('_order_count');
53 |
54 | return is_numeric($count) ? (int) $count : 0;
55 | }
56 |
57 | /**
58 | * Get the related orders.
59 | *
60 | * @return HasMany<\Illuminate\Database\Eloquent\Model, $this>
61 | */
62 | public function orders(): HasMany
63 | {
64 | return $this->hasManyThroughMeta(
65 | Order::class,
66 | '_customer_user',
67 | 'post_id',
68 | 'ID'
69 | );
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Model/Item.php:
--------------------------------------------------------------------------------
1 | */
40 | use HasFactory;
41 |
42 | use MetaFields;
43 |
44 | /**
45 | * The model aliases.
46 | *
47 | * @var array|array>
48 | */
49 | protected static $aliases = [
50 | 'id' => 'order_item_id',
51 | 'name' => 'order_item_name',
52 | 'type' => 'order_item_type',
53 | 'product_id' => ['meta' => '_product_id'],
54 | 'variation_id' => ['meta' => '_variation_id'],
55 | ];
56 |
57 | /**
58 | * {@inheritDoc}
59 | *
60 | * @var list
61 | */
62 | protected $appends = [
63 | 'quantity',
64 | 'tax_class',
65 | 'line_subtotal',
66 | 'line_subtotal_tax',
67 | 'line_total',
68 | 'line_tax',
69 | ];
70 |
71 | /**
72 | * {@inheritDoc}
73 | *
74 | * @var string
75 | */
76 | protected $table = 'woocommerce_order_items';
77 |
78 | /**
79 | * {@inheritDoc}
80 | *
81 | * @var string
82 | */
83 | protected $primaryKey = 'order_item_id';
84 |
85 | /**
86 | * {@inheritDoc}
87 | *
88 | * @var bool
89 | */
90 | public $timestamps = false;
91 |
92 | /**
93 | * Create a new factory instance for the model.
94 | *
95 | * @return ItemFactory
96 | */
97 | protected static function newFactory()
98 | {
99 | return ItemFactory::new();
100 | }
101 |
102 | /**
103 | * Get the line subtotal attribute.
104 | */
105 | protected function getLineSubtotalAttribute(): ?string
106 | {
107 | $lineSubtotal = $this->getMeta('_line_subtotal');
108 |
109 | return is_scalar($lineSubtotal) ? (string) $lineSubtotal : null;
110 | }
111 |
112 | /**
113 | * Get the line subtotal tax attribute.
114 | */
115 | protected function getLineSubtotalTaxAttribute(): ?string
116 | {
117 | $lineSubtotalTax = $this->getMeta('_line_subtotal_tax');
118 |
119 | return is_scalar($lineSubtotalTax) ? (string) $lineSubtotalTax : null;
120 | }
121 |
122 | /**
123 | * Get the line tax attribute.
124 | */
125 | protected function getLineTaxAttribute(): ?string
126 | {
127 | $lineTax = $this->getMeta('_line_tax');
128 |
129 | return is_scalar($lineTax) ? (string) $lineTax : null;
130 | }
131 |
132 | /**
133 | * Get the line total attribute.
134 | */
135 | protected function getLineTotalAttribute(): ?string
136 | {
137 | $lineTotal = $this->getMeta('_line_total');
138 |
139 | return is_scalar($lineTotal) ? (string) $lineTotal : null;
140 | }
141 |
142 | /**
143 | * Get the quantity attribute.
144 | */
145 | protected function getQuantityAttribute(): ?string
146 | {
147 | $quantity = $this->getMeta('_qty');
148 |
149 | return is_scalar($quantity) ? (string) $quantity : null;
150 | }
151 |
152 | /**
153 | * Get the tax class attribute.
154 | */
155 | protected function getTaxClassAttribute(): ?string
156 | {
157 | $taxClass = $this->getMeta('_tax_class');
158 |
159 | return is_scalar($taxClass) ? (string) $taxClass : null;
160 | }
161 |
162 | /**
163 | * {@inheritDoc}
164 | *
165 | * @return HasMany
166 | */
167 | public function meta(): HasMany
168 | {
169 | return $this->hasMany(ItemMeta::class, 'order_item_id', 'order_item_id');
170 | }
171 |
172 | /**
173 | * Get the related order.
174 | *
175 | * @return BelongsTo
176 | */
177 | public function order(): BelongsTo
178 | {
179 | return $this->belongsTo(Order::class);
180 | }
181 |
182 | /**
183 | * Get the related product.
184 | *
185 | * @return BelongsTo
186 | */
187 | public function product(): BelongsTo
188 | {
189 | return $this->belongsTo(Product::class);
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/src/Model/Meta/ItemMeta.php:
--------------------------------------------------------------------------------
1 | $items
34 | */
35 | class Order extends Post
36 | {
37 | use AddressesTrait;
38 | use Aliases;
39 |
40 | /** @use HasFactory */
41 | use HasFactory;
42 |
43 | use MetaFields;
44 |
45 | /**
46 | * The model aliases.
47 | *
48 | * @var array>
49 | */
50 | protected static $aliases = [
51 | 'customer_id' => ['meta' => '_customer_user'],
52 | ];
53 |
54 | /**
55 | * {@inheritDoc}
56 | *
57 | * @var array
58 | */
59 | protected $appends = [
60 | 'currency',
61 | 'total',
62 | 'shipping',
63 | 'tax',
64 | 'shipping_tax',
65 | 'status',
66 | 'date_completed',
67 | 'date_paid',
68 | 'payment',
69 | ];
70 |
71 | /**
72 | * The post type slug.
73 | *
74 | * @var string
75 | */
76 | protected $postType = 'shop_order';
77 |
78 | /**
79 | * Create a new factory instance for the model.
80 | *
81 | * @return OrderFactory
82 | */
83 | protected static function newFactory()
84 | {
85 | return OrderFactory::new();
86 | }
87 |
88 | /**
89 | * {@inheritDoc}
90 | */
91 | public function newEloquentBuilder($builder): OrderBuilder
92 | {
93 | return new OrderBuilder($builder);
94 | }
95 |
96 | /**
97 | * Get the currency attribute.
98 | */
99 | protected function getCurrencyAttribute(): ?string
100 | {
101 | $currency = $this->getMeta('_order_currency');
102 |
103 | return is_scalar($currency) ? (string) $currency : null;
104 | }
105 |
106 | /**
107 | * Get the total attribute.
108 | */
109 | protected function getTotalAttribute(): ?string
110 | {
111 | $total = $this->getMeta('_order_total');
112 |
113 | return is_scalar($total) ? (string) $total : null;
114 | }
115 |
116 | /**
117 | * Get the shipping attribute.
118 | */
119 | protected function getShippingAttribute(): ?string
120 | {
121 | $shipping = $this->getMeta('_order_shipping');
122 |
123 | return is_scalar($shipping) ? (string) $shipping : null;
124 | }
125 |
126 | /**
127 | * Get the tax attribute.
128 | */
129 | protected function getTaxAttribute(): ?string
130 | {
131 | $tax = $this->getMeta('_order_tax');
132 |
133 | return is_scalar($tax) ? (string) $tax : null;
134 | }
135 |
136 | /**
137 | * Get the shipping tax attribute.
138 | */
139 | protected function getShippingTaxAttribute(): ?string
140 | {
141 | $shippingTax = $this->getMeta('_order_shipping_tax');
142 |
143 | return is_scalar($shippingTax) ? (string) $shippingTax : null;
144 | }
145 |
146 | /**
147 | * Get the status attribute.
148 | */
149 | public function getStatusAttribute(): string
150 | {
151 | $status = $this->post_status;
152 |
153 | return substr($status, 0, 3) === 'wc-' ? substr($status, 3) : $status;
154 | }
155 |
156 | /**
157 | * Get the completed date attribute.
158 | */
159 | protected function getDateCompletedAttribute(): ?Carbon
160 | {
161 | $value = $this->getMeta('_date_completed');
162 |
163 | if (is_numeric($value)) {
164 | return Carbon::createFromTimestamp($value);
165 | }
166 |
167 | /**
168 | * WooCommerce in version 2.6.x has stored completed date in
169 | * "_completed_date" meta field in MySQL datetime format.
170 | */
171 | $value = $this->getMeta('_completed_date');
172 |
173 | return is_string($value)
174 | ? Carbon::createFromFormat('Y-m-d H:i:s', $value)
175 | : null;
176 | }
177 |
178 | /**
179 | * Get the paid date attribute.
180 | */
181 | public function getDatePaidAttribute(): ?Carbon
182 | {
183 | $value = $this->getMeta('_date_paid');
184 |
185 | if (is_numeric($value)) {
186 | return Carbon::createFromTimestamp($value);
187 | }
188 |
189 | /**
190 | * WooCommerce in version 2.6.x has stored paid date in "_paid_date"
191 | * meta field in MySQL datetime format.
192 | */
193 | $value = $this->getMeta('_paid_date');
194 |
195 | return is_string($value)
196 | ? Carbon::createFromFormat('Y-m-d H:i:s', $value)
197 | : null;
198 | }
199 |
200 | /**
201 | * Get the payment attribute.
202 | */
203 | public function getPaymentAttribute(): Payment
204 | {
205 | return new Payment($this);
206 | }
207 |
208 | /**
209 | * Get the related customer.
210 | *
211 | * @return BelongsTo
212 | */
213 | public function customer(): BelongsTo
214 | {
215 | return $this->belongsTo(Customer::class);
216 | }
217 |
218 | /**
219 | * Get related items.
220 | *
221 | * @return HasMany-
222 | */
223 | public function items(): HasMany
224 | {
225 | return $this->hasMany(Item::class, 'order_id');
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/src/Model/Product.php:
--------------------------------------------------------------------------------
1 | $attributes
38 | * @property Collection $crosssells
39 | * @property Collection $upsells
40 | * @property BaseCollection $gallery
41 | * @property Collection $categories
42 | * @property Collection $items
43 | * @property Collection $productTypes
44 | * @property Collection $tags
45 | */
46 | class Product extends Post
47 | {
48 | use Aliases;
49 |
50 | /** @use HasFactory */
51 | use HasFactory;
52 |
53 | /** @use HasRelationsThroughMeta<\Illuminate\Database\Eloquent\Model, $this> */
54 | use HasRelationsThroughMeta;
55 |
56 | use MetaFields;
57 |
58 | /**
59 | * Preloaded product attributes list.
60 | *
61 | * @var Collection
62 | */
63 | protected static $productAttributes;
64 |
65 | /**
66 | * {@inheritDoc}
67 | *
68 | * @var array
69 | */
70 | protected $appends = [
71 | 'price',
72 | 'regular_price',
73 | 'sale_price',
74 | 'on_sale',
75 | 'sku',
76 | 'tax_status',
77 | 'weight',
78 | 'length',
79 | 'width',
80 | 'height',
81 | 'is_virtual',
82 | 'is_downloadable',
83 | 'stock',
84 | 'in_stock',
85 | ];
86 |
87 | /**
88 | * The post type of model.
89 | *
90 | * @var string
91 | */
92 | protected $postType = 'product';
93 |
94 | /**
95 | * {@inheritDoc}
96 | */
97 | protected static function boot()
98 | {
99 | parent::boot();
100 |
101 | static::$productAttributes = ProductAttribute::all()->keyBy('attribute_name');
102 | }
103 |
104 | /**
105 | * Create a new factory instance for the model.
106 | *
107 | * @return ProductFactory
108 | */
109 | protected static function newFactory()
110 | {
111 | return ProductFactory::new();
112 | }
113 |
114 | /**
115 | * Get the price attribute.
116 | */
117 | protected function getPriceAttribute(): ?string
118 | {
119 | $price = $this->getMeta('_price');
120 |
121 | return is_scalar($price) ? (string) $price : null;
122 | }
123 |
124 | /**
125 | * Get the regular price attribute.
126 | */
127 | protected function getRegularPriceAttribute(): ?string
128 | {
129 | $regularPrice = $this->getMeta('_regular_price');
130 |
131 | return is_scalar($regularPrice) ? (string) $regularPrice : null;
132 | }
133 |
134 | /**
135 | * Get the sale price attribute
136 | */
137 | protected function getSalePriceAttribute(): ?string
138 | {
139 | $salePrice = $this->getMeta('_sale_price');
140 |
141 | return is_scalar($salePrice) ? (string) $salePrice : null;
142 | }
143 |
144 | /**
145 | * Get the on sale attribute
146 | */
147 | protected function getOnSaleAttribute(): bool
148 | {
149 | return ! empty($this->sale_price) && $this->sale_price < $this->regular_price;
150 | }
151 |
152 | /**
153 | * Get the SKU attribute.
154 | */
155 | protected function getSkuAttribute(): ?string
156 | {
157 | $sku = $this->getMeta('_sku');
158 |
159 | return is_scalar($sku) ? (string) $sku : null;
160 | }
161 |
162 | /**
163 | * Get the tax status attribute.
164 | */
165 | protected function getTaxStatusAttribute(): ?string
166 | {
167 | $taxStatus = $this->getMeta('_tax_status');
168 |
169 | return is_scalar($taxStatus) ? (string) $taxStatus : null;
170 | }
171 |
172 | /**
173 | * Get the is taxable attribute.
174 | */
175 | public function getIsTaxableAttribute(): bool
176 | {
177 | return $this->tax_status === 'taxable';
178 | }
179 |
180 | /**
181 | * Get the weight attribute.
182 | */
183 | protected function getWeightAttribute(): ?string
184 | {
185 | $weight = $this->getMeta('_weight');
186 |
187 | return is_scalar($weight) ? (string) $weight : null;
188 | }
189 |
190 | /**
191 | * Get the length attribute.
192 | */
193 | protected function getLengthAttribute(): ?string
194 | {
195 | $length = $this->getMeta('_length');
196 |
197 | return is_scalar($length) ? (string) $length : null;
198 | }
199 |
200 | /**
201 | * Get the width attribute.
202 | */
203 | protected function getWidthAttribute(): ?string
204 | {
205 | $width = $this->getMeta('_width');
206 |
207 | return is_scalar($width) ? (string) $width : null;
208 | }
209 |
210 | /**
211 | * Get the height attribute.
212 | */
213 | protected function getHeightAttribute(): ?string
214 | {
215 | $height = $this->getMeta('_height');
216 |
217 | return is_scalar($height) ? (string) $height : null;
218 | }
219 |
220 | /**
221 | * Get the is virtual attribute.
222 | */
223 | protected function getIsVirtualAttribute(): bool
224 | {
225 | return $this->getMeta('_virtual') === 'yes';
226 | }
227 |
228 | /**
229 | * Get the is downloadable attribute.
230 | */
231 | protected function getIsDownloadableAttribute(): bool
232 | {
233 | return $this->getMeta('_downloadable') === 'yes';
234 | }
235 |
236 | /**
237 | * Get the stock attribute.
238 | */
239 | protected function getStockAttribute(): ?string
240 | {
241 | $stock = $this->getMeta('_stock');
242 |
243 | return is_scalar($stock) ? (string) $stock : null;
244 | }
245 |
246 | /**
247 | * Get the in stock attribute.
248 | */
249 | protected function getInStockAttribute(): bool
250 | {
251 | return $this->getMeta('_stock_status') === 'instock';
252 | }
253 |
254 | /**
255 | * Get the product attributes attribute.
256 | *
257 | * @return BaseCollection
258 | */
259 | protected function getAttributesAttribute(): BaseCollection
260 | {
261 | $taxonomies = $this->taxonomies;
262 |
263 | return $taxonomies
264 | ->filter(function ($taxonomy) {
265 | return isset($taxonomy->taxonomy)
266 | && is_string($taxonomy->taxonomy)
267 | && Str::startsWith($taxonomy->taxonomy, 'pa_');
268 | })
269 | ->groupBy('taxonomy')
270 | ->map(function ($taxonomy, $taxonomyName) {
271 | $attributeName = substr($taxonomyName, 3);
272 | /** @var \Corcel\WooCommerce\Model\ProductAttribute */
273 | $attribute = static::$productAttributes->get($attributeName);
274 | $attribute->setTerms($taxonomy->pluck('term'));
275 |
276 | return $attribute;
277 | })
278 | ->keyBy('attribute_name');
279 | }
280 |
281 | /**
282 | * Get the cross-sells attribute.
283 | *
284 | * @return Collection
285 | */
286 | protected function getCrosssellsAttribute(): Collection
287 | {
288 | $crosssells = $this->getMeta('_crosssell_ids');
289 |
290 | if (! is_string($crosssells)) {
291 | return static::newCollection();
292 | }
293 |
294 | $crosssells = unserialize($crosssells);
295 |
296 | if (empty($crosssells)) {
297 | return static::newCollection();
298 | }
299 |
300 | /** @var Collection */
301 | return static::query()->whereIn('ID', $crosssells)->get();
302 | }
303 |
304 | /**
305 | * Get the up-sells attribute.
306 | *
307 | * @return Collection
308 | */
309 | public function getUpsellsAttribute(): Collection
310 | {
311 | $upsells = $this->getMeta('_upsell_ids');
312 |
313 | if (! is_string($upsells)) {
314 | return static::newCollection();
315 | }
316 |
317 | $upsells = unserialize($upsells);
318 |
319 | if (empty($upsells)) {
320 | return static::newCollection();
321 | }
322 |
323 | /** @var Collection */
324 | return static::query()->whereIn('ID', $upsells)->get();
325 | }
326 |
327 | /**
328 | * Get the gallery attribute.
329 | *
330 | * @return BaseCollection
331 | */
332 | public function getGalleryAttribute(): BaseCollection
333 | {
334 | $gallery = new BaseCollection;
335 |
336 | if (isset($this->thumbnail->attachment) && $this->thumbnail->attachment instanceof Attachment) {
337 | $gallery->push($this->thumbnail->attachment);
338 | }
339 |
340 | $attachmentsId = $this->getMeta('_product_image_gallery');
341 |
342 | if (! is_string($attachmentsId) || empty($attachmentsId)) {
343 | return $gallery;
344 | }
345 |
346 | $attachmentsId = explode(',', $attachmentsId);
347 | $attachments = Attachment::query()->whereIn('ID', $attachmentsId)->get();
348 |
349 | return $gallery->merge($attachments);
350 | }
351 |
352 | /**
353 | * Get the type attribute.
354 | */
355 | protected function getTypeAttribute(): ?string
356 | {
357 | /** @var BaseCollection */
358 | $productTypeNames = $this->productTypes->pluck('term.name');
359 |
360 | return $productTypeNames->first();
361 | }
362 |
363 | /**
364 | * Get the related categories.
365 | *
366 | * @return BelongsToMany
367 | */
368 | public function categories(): BelongsToMany
369 | {
370 | return $this->belongsToMany(
371 | ProductCategory::class,
372 | 'term_relationships',
373 | 'object_id',
374 | 'term_taxonomy_id'
375 | );
376 | }
377 |
378 | /**
379 | * Get the related items.
380 | *
381 | * @return HasMany<\Illuminate\Database\Eloquent\Model, $this>
382 | */
383 | public function items(): HasMany
384 | {
385 | return $this->hasManyThroughMeta(
386 | Item::class,
387 | '_product_id',
388 | 'order_item_id',
389 | 'order_item_id'
390 | );
391 | }
392 |
393 | /**
394 | * Get the related product types.
395 | *
396 | * @return BelongsToMany
397 | */
398 | public function productTypes(): BelongsToMany
399 | {
400 | return $this->belongsToMany(
401 | ProductType::class,
402 | 'term_relationships',
403 | 'object_id',
404 | 'term_taxonomy_id'
405 | );
406 | }
407 |
408 | /**
409 | * Get the related tags.
410 | *
411 | * @return BelongsToMany
412 | */
413 | public function tags(): BelongsToMany
414 | {
415 | return $this->belongsToMany(
416 | ProductTag::class,
417 | 'term_relationships',
418 | 'object_id',
419 | 'term_taxonomy_id'
420 | );
421 | }
422 | }
423 |
--------------------------------------------------------------------------------
/src/Model/ProductAttribute.php:
--------------------------------------------------------------------------------
1 |
33 | */
34 | public Collection $terms;
35 |
36 | /**
37 | * The model aliases.
38 | *
39 | * @var array
40 | */
41 | protected static $aliases = [
42 | 'id' => 'attribute_id',
43 | 'slug' => 'attribute_name',
44 | 'name' => 'attribute_label',
45 | 'type' => 'attribute_type',
46 | 'order_by' => 'attribute_orderby',
47 | 'public' => 'attribute_public',
48 | ];
49 |
50 | /**
51 | * {@inheritDoc}
52 | *
53 | * @var array
54 | */
55 | protected $casts = [
56 | 'attribute_public' => 'bool',
57 | ];
58 |
59 | /**
60 | * {@inheritDoc}
61 | */
62 | protected $primaryKey = 'attribute_id';
63 |
64 | /**
65 | * {@inheritDoc}
66 | */
67 | protected $table = 'woocommerce_attribute_taxonomies';
68 |
69 | /**
70 | * Set the product terms.
71 | *
72 | * @param Collection $terms
73 | */
74 | public function setTerms(Collection $terms): void
75 | {
76 | $this->terms = $terms;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/Model/ProductCategory.php:
--------------------------------------------------------------------------------
1 |
16 | */
17 | class Address implements Arrayable, Jsonable
18 | {
19 | /**
20 | * The model instance.
21 | */
22 | protected Model $model;
23 |
24 | /**
25 | * The address type.
26 | */
27 | protected string $type;
28 |
29 | /**
30 | * The address attributes.
31 | *
32 | * @var array
33 | */
34 | protected array $attributes = [];
35 |
36 | /**
37 | * The address constructor.
38 | */
39 | public function __construct(Model $model, string $type)
40 | {
41 | $this->model = $model;
42 | $this->type = $type;
43 |
44 | $this->parseAttributes();
45 | }
46 |
47 | /**
48 | * Parse address attributes.
49 | */
50 | protected function parseAttributes(): void
51 | {
52 | foreach ($this->attributeKeys() as $key) {
53 | $metaKey = $this->getMetaKey($key);
54 |
55 | // @phpstan-ignore-next-line
56 | $this->attributes[$key] = $this->model->getMeta($metaKey);
57 | }
58 | }
59 |
60 | /**
61 | * List of the attribute keys.
62 | *
63 | * @return array
64 | */
65 | protected function attributeKeys(): array
66 | {
67 | $keys = [
68 | 'first_name',
69 | 'last_name',
70 | 'company',
71 | 'address_1',
72 | 'address_2',
73 | 'city',
74 | 'state',
75 | 'postcode',
76 | 'country',
77 | ];
78 |
79 | if ($this->type === 'billing') {
80 | $keys = array_merge($keys, [
81 | 'email',
82 | 'phone',
83 | ]);
84 | }
85 |
86 | return $keys;
87 | }
88 |
89 | /**
90 | * Get meta key for given attribute name.
91 | */
92 | protected function getMetaKey(string $key): string
93 | {
94 | $pattern = $this->metaKeyPattern();
95 |
96 | return sprintf($pattern, $this->type, $key);
97 | }
98 |
99 | /**
100 | * Get meta key pattern based on model.
101 | */
102 | protected function metaKeyPattern(): string
103 | {
104 | if ($this->model instanceof Customer) {
105 | return '%s_%s';
106 | } elseif ($this->model instanceof Order) {
107 | return '_%s_%s';
108 | }
109 |
110 | throw new InvalidArgumentException(sprintf(
111 | 'Model "%s" cannot have address.',
112 | get_class($this->model)
113 | ));
114 | }
115 |
116 | /**
117 | * {@inheritDoc}
118 | *
119 | * @return array
120 | */
121 | public function toArray(): array
122 | {
123 | return $this->attributes;
124 | }
125 |
126 | /**
127 | * {@inheritDoc}
128 | *
129 | * @param int $options
130 | */
131 | public function toJson($options = 0): string
132 | {
133 | $json = json_encode($this->toArray(), $options);
134 |
135 | if ($json === false || json_last_error() !== JSON_ERROR_NONE) {
136 | throw new InvalidArgumentException('An error occured while converting order address to JSON.');
137 | }
138 |
139 | return $json;
140 | }
141 |
142 | /**
143 | * Magic method to get address attributes.
144 | *
145 | * @return mixed
146 | */
147 | public function __get(string $key)
148 | {
149 | if (array_key_exists($key, $this->attributes)) {
150 | return $this->attributes[$key];
151 | }
152 |
153 | throw new InvalidArgumentException("Property {$key} does not exists.");
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/src/Support/BillingAddress.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class Payment implements Arrayable, Jsonable
16 | {
17 | /**
18 | * The payment method.
19 | */
20 | public ?string $method = null;
21 |
22 | /**
23 | * The payment method title.
24 | */
25 | public ?string $method_title = null;
26 |
27 | /**
28 | * The payment transation identificator.
29 | */
30 | public ?string $transaction_id = null;
31 |
32 | /**
33 | * The payment constructor.
34 | */
35 | public function __construct(Order $order)
36 | {
37 | $method = $order->getMeta('_payment_method');
38 | $methodTitle = $order->getMeta('_payment_method_title');
39 | $transactionId = $order->getMeta('_transaction_id');
40 |
41 | $this->method = is_scalar($method) ? (string) $method : null;
42 | $this->method_title = is_scalar($methodTitle) ? (string) $methodTitle : null;
43 | $this->transaction_id = is_scalar($transactionId) ? (string) $transactionId : null;
44 | }
45 |
46 | /**
47 | * {@inheritDoc}
48 | *
49 | * @return array
50 | */
51 | public function toArray(): array
52 | {
53 | return [
54 | 'method' => $this->method,
55 | 'method_title' => $this->method_title,
56 | 'transaction_id' => $this->transaction_id,
57 | ];
58 | }
59 |
60 | /**
61 | * {@inheritDoc}
62 | *
63 | * @param int $options
64 | */
65 | public function toJson($options = 0): string
66 | {
67 | $json = json_encode($this->toArray(), $options);
68 |
69 | if ($json === false || json_last_error() !== JSON_ERROR_NONE) {
70 | throw new InvalidArgumentException('An error occured while converting order payment to JSON.');
71 | }
72 |
73 | return $json;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/Support/ShippingAddress.php:
--------------------------------------------------------------------------------
1 | appends = array_merge($this->appends, [
22 | 'billing_address',
23 | 'shipping_address',
24 | ]);
25 | }
26 |
27 | /**
28 | * Get the billing address attribute.
29 | */
30 | protected function getBillingAddressAttribute(): BillingAddress
31 | {
32 | return new BillingAddress($this);
33 | }
34 |
35 | /**
36 | * Get the shipping address attribute.
37 | */
38 | protected function getShippingAddressAttribute(): ShippingAddress
39 | {
40 | return new ShippingAddress($this);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Traits/HasRelationsThroughMeta.php:
--------------------------------------------------------------------------------
1 | $related
26 | * @return HasMany
27 | *
28 | * @throws InvalidArgumentException
29 | * @throws LogicException
30 | */
31 | public function hasManyThroughMeta(string $related, string $metaKey, ?string $foreignKey = null, ?string $localKey = null): HasMany
32 | {
33 | /** @var Model */
34 | $model = $this->newRelatedInstance($related);
35 | $meta = $this->metaInstance($model);
36 |
37 | $foreignKey = $foreignKey ?: $this->getForeignKey();
38 | $localKey = $localKey ?: $this->getKeyName();
39 |
40 | return $this->hasMany($related, $meta->qualifyColumn('meta_value'))
41 | ->leftJoin($meta->getTable(), $this->joinClause(
42 | $model->qualifyColumn($localKey),
43 | $meta->qualifyColumn($foreignKey),
44 | $metaKey
45 | ))
46 | ->select($model->qualifyColumn('*'));
47 | }
48 |
49 | /**
50 | * Make meta model instance.
51 | *
52 | * @throws InvalidArgumentException
53 | * @throws LogicException
54 | */
55 | private function metaInstance(Model $model): Meta
56 | {
57 | if (! method_exists($model, 'meta')) {
58 | throw new LogicException(sprintf(
59 | 'The model "%s" must have defined "meta" method. Adding "%s" trait will likely solve this problem.',
60 | get_class($model),
61 | MetaFields::class
62 | ));
63 | }
64 |
65 | /** @var \Illuminate\Database\Eloquent\Relations\HasMany */
66 | $relation = $model->meta();
67 | $meta = $relation->getRelated();
68 |
69 | if (! $meta instanceof Meta) {
70 | throw new InvalidArgumentException(sprintf(
71 | 'The meta method of "%s" model must extends "%s" model.',
72 | get_class($meta),
73 | Meta::class
74 | ));
75 | }
76 |
77 | return $meta;
78 | }
79 |
80 | /**
81 | * Build join clause between model and meta tables.
82 | */
83 | private function joinClause(string $localKey, string $foreignKey, string $metaKey): Closure
84 | {
85 | return function (JoinClause $join) use ($localKey, $foreignKey, $metaKey) {
86 | $join->on($localKey, '=', $foreignKey)
87 | ->where('meta_key', '=', $metaKey);
88 | };
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/WooCommerce.php:
--------------------------------------------------------------------------------
1 | loadMigrationsFrom([
19 | '--database' => 'wp',
20 | '--realpath' => true,
21 | '--path' => __DIR__.'/database/migrations',
22 | ]);
23 | }
24 |
25 | /**
26 | * {@inheritDoc}
27 | *
28 | * @param \Illuminate\Foundation\Application $app
29 | */
30 | protected function getEnvironmentSetUp($app): void
31 | {
32 | $this->configureDatabaseConfig($app);
33 | }
34 |
35 | /**
36 | * Configure database.
37 | *
38 | * @param \Illuminate\Foundation\Application $app
39 | */
40 | private function configureDatabaseConfig($app): void
41 | {
42 | $app['config']->set('database.connections.wp', [
43 | 'driver' => 'sqlite',
44 | 'database' => ':memory:',
45 | 'prefix' => 'wp_',
46 | ]);
47 |
48 | $app['config']->set('database.default', 'wp');
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tests/Unit/Model/CustomerTest.php:
--------------------------------------------------------------------------------
1 | createCustomer();
16 | $customer->createMeta([
17 | '_order_count' => 10,
18 | ]);
19 |
20 | $this->assertSame(10, $customer->order_count);
21 | }
22 |
23 | public function test_array_has_appended_values(): void
24 | {
25 | $customer = $this->createCustomer();
26 |
27 | $this->assertArrayHasKey('order_count', $customer->toArray());
28 | }
29 |
30 | public function test_related_orders(): void
31 | {
32 | $customer = $this->createCustomer();
33 |
34 | /** @var Order */
35 | $order = Order::factory()->create();
36 | $order->createMeta('_customer_user', $customer->ID);
37 |
38 | $this->assertTrue($customer->orders()->get()->first()->is($order)); // @phpstan-ignore-line
39 |
40 | /** @var Order */
41 | $order = Order::factory()->create();
42 | $order->createMeta('_customer_user', $customer->ID);
43 |
44 | $this->assertSame(2, $customer->orders()->count());
45 | }
46 |
47 | private function createCustomer(): Customer
48 | {
49 | /** @var Customer */
50 | return Customer::factory()->create();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tests/Unit/Model/ItemTest.php:
--------------------------------------------------------------------------------
1 | createItem();
17 | $item->createMeta('_line_subtotal', '9.99');
18 |
19 | $this->assertSame('9.99', $item->line_subtotal);
20 | }
21 |
22 | public function test_line_subtotal_tax_property(): void
23 | {
24 | $item = $this->createItem();
25 | $item->createMeta('_line_subtotal_tax', '8.88');
26 |
27 | $this->assertSame('8.88', $item->line_subtotal_tax);
28 | }
29 |
30 | public function test_line_tax_property(): void
31 | {
32 | $item = $this->createItem();
33 | $item->createMeta('_line_tax', '7.77');
34 |
35 | $this->assertSame('7.77', $item->line_tax);
36 | }
37 |
38 | public function test_line_total_property(): void
39 | {
40 | $item = $this->createItem();
41 | $item->createMeta('_line_total', '6.66');
42 |
43 | $this->assertSame('6.66', $item->line_total);
44 | }
45 |
46 | public function test_quantity_property(): void
47 | {
48 | $item = $this->createItem();
49 | $item->createMeta('_qty', '5');
50 |
51 | $this->assertSame('5', $item->quantity);
52 | }
53 |
54 | public function test_tax_class_property(): void
55 | {
56 | $item = $this->createItem();
57 | $item->createMeta('_tax_class', 'standard');
58 |
59 | $this->assertSame('standard', $item->tax_class);
60 | }
61 |
62 | public function test_related_order(): void
63 | {
64 | /** @var Order */
65 | $order = Order::factory()->create();
66 | $item = $this->createItem(['order_id' => $order->ID]);
67 |
68 | $this->assertTrue($item->order->is($order));
69 | }
70 |
71 | public function test_related_product(): void
72 | {
73 | /** @var \Corcel\WooCommerce\Model\Product */
74 | $product = Product::factory()->create();
75 |
76 | $item = $this->createItem();
77 | $item->createMeta('_product_id', $product->ID);
78 |
79 | $this->assertTrue($item->product->is($product));
80 | }
81 |
82 | /**
83 | * @param array $attributes
84 | */
85 | private function createItem(array $attributes = []): Item
86 | {
87 | /** @var Item */
88 | $item = Item::factory()->create($attributes);
89 |
90 | return $item;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/tests/Unit/Model/OrderTest.php:
--------------------------------------------------------------------------------
1 | createOrder();
21 | $order->createMeta('_order_currency', 'USD');
22 |
23 | $this->assertSame('USD', $order->currency);
24 | }
25 |
26 | public function test_total_property(): void
27 | {
28 | $order = $this->createOrder();
29 | $order->createMeta('_order_total', '9.99');
30 |
31 | $this->assertSame('9.99', $order->total);
32 | }
33 |
34 | public function test_shipping_property(): void
35 | {
36 | $order = $this->createOrder();
37 | $order->createMeta('_order_shipping', '8.88');
38 |
39 | $this->assertSame('8.88', $order->shipping);
40 | }
41 |
42 | public function test_tax_property(): void
43 | {
44 | $order = $this->createOrder();
45 | $order->createMeta('_order_tax', '7.77');
46 |
47 | $this->assertSame('7.77', $order->tax);
48 | }
49 |
50 | public function test_shipping_tax_property(): void
51 | {
52 | $order = $this->createOrder();
53 | $order->createMeta('_order_shipping_tax', '6.66');
54 |
55 | $this->assertSame('6.66', $order->shipping_tax);
56 | }
57 |
58 | public function test_status_property(): void
59 | {
60 | $order = $this->createOrder([
61 | 'post_status' => 'wc-refunded',
62 | ]);
63 |
64 | $this->assertSame('refunded', $order->status);
65 | }
66 |
67 | public function test_date_completed_property(): void
68 | {
69 | $order = $this->createOrder();
70 | $order->createMeta('_date_completed', 1577836800); // '2020-01-01 00:00:00'
71 |
72 | $this->assertInstanceOf(Carbon::class, $order->date_completed);
73 | $this->assertSame('2020-01-01 00:00:00', $order->date_completed->format('Y-m-d H:i:s'));
74 | }
75 |
76 | public function test_date_paid_property(): void
77 | {
78 | $order = $this->createOrder();
79 | $order->createMeta('_date_paid', 1577840400); // '2020-01-01 01:00:00'
80 |
81 | $this->assertInstanceOf(Carbon::class, $order->date_paid);
82 | $this->assertSame('2020-01-01 01:00:00', $order->date_paid->format('Y-m-d H:i:s'));
83 | }
84 |
85 | public function test_deprecated_date_formats(): void
86 | {
87 | $order = $this->createOrder();
88 | $order->createMeta('_completed_date', '2020-01-01 00:00:00');
89 | $order->createMeta('_paid_date', '2020-01-01 01:00:00');
90 |
91 | $this->assertInstanceOf(Carbon::class, $order->date_completed);
92 | $this->assertSame('2020-01-01 00:00:00', $order->date_completed->format('Y-m-d H:i:s'));
93 |
94 | $this->assertInstanceOf(Carbon::class, $order->date_paid);
95 | $this->assertSame('2020-01-01 01:00:00', $order->date_paid->format('Y-m-d H:i:s'));
96 | }
97 |
98 | public function test_payment_property(): void
99 | {
100 | $order = $this->createOrder();
101 |
102 | $this->assertInstanceOf(Payment::class, $order->payment);
103 | }
104 |
105 | public function test_billing_address_property(): void
106 | {
107 | $order = $this->createOrder();
108 |
109 | $this->assertInstanceOf(BillingAddress::class, $order->billing_address);
110 | }
111 |
112 | public function test_shipping_address_property(): void
113 | {
114 | $order = $this->createOrder();
115 |
116 | $this->assertInstanceOf(ShippingAddress::class, $order->shipping_address);
117 | }
118 |
119 | public function test_array_has_appended_values(): void
120 | {
121 | /** @var Order */
122 | $order = Order::factory()->create();
123 | $array = $order->toArray();
124 |
125 | $this->assertArrayHasKey('currency', $array);
126 | $this->assertArrayHasKey('total', $array);
127 | $this->assertArrayHasKey('shipping', $array);
128 | $this->assertArrayHasKey('tax', $array);
129 | $this->assertArrayHasKey('shipping_tax', $array);
130 | $this->assertArrayHasKey('status', $array);
131 | $this->assertArrayHasKey('date_completed', $array);
132 | $this->assertArrayHasKey('date_paid', $array);
133 | $this->assertArrayHasKey('payment', $array);
134 | $this->assertArrayHasKey('billing_address', $array);
135 | $this->assertArrayHasKey('shipping_address', $array);
136 | }
137 |
138 | public function test_related_customer(): void
139 | {
140 | /** @var Customer */
141 | $customer = Customer::factory()->create();
142 |
143 | $order = $this->createOrder();
144 | $order->createMeta('_customer_user', $customer->ID);
145 |
146 | /** @var Customer */
147 | $orderCustomer = $order->customer;
148 |
149 | $this->assertTrue($orderCustomer->is($customer));
150 | }
151 |
152 | public function test_guest_order(): void
153 | {
154 | $order = $this->createOrder();
155 |
156 | $this->assertNull($order->customer);
157 | }
158 |
159 | public function test_related_items(): void
160 | {
161 | $order = $this->createOrder();
162 |
163 | $item = Item::factory()->count(3)->create(['order_id' => $order->ID]);
164 |
165 | $this->assertSame(3, $order->items->count());
166 | }
167 |
168 | /**
169 | * @param array $attributes
170 | */
171 | private function createOrder(array $attributes = []): Order
172 | {
173 | /** @var Order */
174 | $order = Order::factory()->create($attributes);
175 |
176 | return $order;
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/tests/Unit/Model/ProductAttributeTest.php:
--------------------------------------------------------------------------------
1 | setTerms(new Collection);
17 |
18 | $this->assertInstanceOf(Collection::class, $productAttribute->terms);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/tests/Unit/Model/ProductTest.php:
--------------------------------------------------------------------------------
1 | createProduct();
16 | $product->createMeta('_price', '9.99');
17 |
18 | $this->assertSame('9.99', $product->price);
19 | }
20 |
21 | public function test_regular_price_property(): void
22 | {
23 | $product = $this->createProduct();
24 | $product->createMeta('_regular_price', '8.88');
25 |
26 | $this->assertSame('8.88', $product->regular_price);
27 | }
28 |
29 | public function test_sale_price_property(): void
30 | {
31 | $product = $this->createProduct();
32 | $product->createMeta('_sale_price', '7.77');
33 |
34 | $this->assertSame('7.77', $product->sale_price);
35 | }
36 |
37 | public function test_on_sale_property(): void
38 | {
39 | $product = $this->createProduct();
40 | $product->createMeta('_regular_price', '6.66');
41 | $product->createMeta('_sale_price', '5.55');
42 |
43 | $this->assertTrue($product->on_sale);
44 |
45 | $product = $this->createProduct();
46 | $product->createMeta('_regular_price', '4.44');
47 |
48 | $this->assertFalse($product->on_sale);
49 | }
50 |
51 | public function test_sku_property(): void
52 | {
53 | $product = $this->createProduct();
54 | $product->createMeta('_sku', 'UNIQUE');
55 |
56 | $this->assertSame('UNIQUE', $product->sku);
57 | }
58 |
59 | public function test_tax_status_property(): void
60 | {
61 | $product = $this->createProduct();
62 | $product->createMeta('_tax_status', 'taxable');
63 |
64 | $this->assertSame('taxable', $product->tax_status);
65 | }
66 |
67 | public function test_is_taxable_property(): void
68 | {
69 | $product = $this->createProduct();
70 | $product->createMeta('_tax_status', 'taxable');
71 |
72 | $this->assertTrue($product->is_taxable);
73 |
74 | $product = $this->createProduct();
75 | $product->createMeta('_tax_status', '');
76 |
77 | $this->assertFalse($product->is_taxable);
78 | }
79 |
80 | public function test_weight_property(): void
81 | {
82 | $product = $this->createProduct();
83 | $product->createMeta('_weight', '3.33');
84 |
85 | $this->assertSame('3.33', $product->weight);
86 | }
87 |
88 | public function test_length_property(): void
89 | {
90 | $product = $this->createProduct();
91 | $product->createMeta('_length', '2.22');
92 |
93 | $this->assertSame('2.22', $product->length);
94 | }
95 |
96 | public function test_width_property(): void
97 | {
98 | $product = $this->createProduct();
99 | $product->createMeta('_width', '1.11');
100 |
101 | $this->assertSame('1.11', $product->width);
102 | }
103 |
104 | public function test_height_property(): void
105 | {
106 | $product = $this->createProduct();
107 | $product->createMeta('_height', '0.00');
108 |
109 | $this->assertSame('0.00', $product->height);
110 | }
111 |
112 | public function test_is_virtual_property(): void
113 | {
114 | $product = $this->createProduct();
115 | $product->createMeta('_virtual', 'yes');
116 |
117 | $this->assertTrue($product->is_virtual);
118 |
119 | $product = $this->createProduct();
120 | $product->createMeta('_virtual', 'no');
121 |
122 | $this->assertFalse($product->is_virtual);
123 | }
124 |
125 | public function test_is_downloadable_property(): void
126 | {
127 | $product = $this->createProduct();
128 | $product->createMeta('_downloadable', 'yes');
129 |
130 | $this->assertTrue($product->is_downloadable);
131 |
132 | $product = $this->createProduct();
133 | $product->createMeta('_downloadable', 'no');
134 |
135 | $this->assertFalse($product->is_downloadable);
136 | }
137 |
138 | public function test_stock_property(): void
139 | {
140 | $product = $this->createProduct();
141 | $product->createMeta('_stock', '5');
142 |
143 | $this->assertSame('5', $product->stock);
144 | }
145 |
146 | public function test_in_stock_property(): void
147 | {
148 | $product = $this->createProduct();
149 | $product->createMeta('_stock_status', 'instock');
150 |
151 | $this->assertTrue($product->in_stock);
152 |
153 | $product = $this->createProduct();
154 | $product->createMeta('_stock_status', '');
155 |
156 | $this->assertFalse($product->in_stock);
157 | }
158 |
159 | public function test_crosssells_property(): void
160 | {
161 | /** @var \Illuminate\Database\Eloquent\Collection */
162 | $crosssellProducts = Product::factory()->count(2)->create();
163 |
164 | $product = $this->createProduct();
165 | $product->createMeta('_crosssell_ids', serialize($crosssellProducts->pluck('ID')->toArray()));
166 |
167 | $this->assertSame(2, $product->crosssells->count());
168 | // @phpstan-ignore-next-line
169 | $this->assertTrue($product->crosssells->first()->is($crosssellProducts->first()));
170 | }
171 |
172 | public function test_empty_crosssells(): void
173 | {
174 | $product = $this->createProduct();
175 | $product->createMeta('_crosssell_ids', serialize([]));
176 |
177 | $this->assertSame(0, $product->crosssells->count());
178 | }
179 |
180 | public function test_upsells_property(): void
181 | {
182 | /** @var \Illuminate\Database\Eloquent\Collection */
183 | $upsellProducts = Product::factory()->count(3)->create();
184 |
185 | $product = $this->createProduct();
186 | $product->createMeta('_upsell_ids', serialize($upsellProducts->pluck('ID')->toArray()));
187 |
188 | $this->assertSame(3, $product->upsells->count());
189 | // @phpstan-ignore-next-line
190 | $this->assertTrue($product->upsells->first()->is($upsellProducts->first()));
191 | }
192 |
193 | public function test_empty_upsells(): void
194 | {
195 | $product = $this->createProduct();
196 | $product->createMeta('_upsell_ids', serialize([]));
197 |
198 | $this->assertSame(0, $product->upsells->count());
199 | }
200 |
201 | public function test_related_items(): void
202 | {
203 | $product = $this->createProduct();
204 |
205 | /** @var Item */
206 | $firstItem = Item::factory()->create();
207 | $firstItem->createMeta('_product_id', $product->ID);
208 |
209 | /** @var Item */
210 | $secondItem = Item::factory()->create();
211 | $secondItem->createMeta('_product_id', $product->ID);
212 |
213 | $this->assertSame(2, $product->items->count());
214 | // @phpstan-ignore-next-line
215 | $this->assertTrue($product->items->first()->is($firstItem));
216 | }
217 |
218 | private function createProduct(): Product
219 | {
220 | /** @var Product */
221 | $product = Product::factory()->create();
222 |
223 | return $product;
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/tests/Unit/Support/AddressTest.php:
--------------------------------------------------------------------------------
1 | expectException(InvalidArgumentException::class);
18 |
19 | /** @var Item */
20 | $model = Item::factory()->create();
21 |
22 | new Address($model, 'billing');
23 | }
24 |
25 | public function test_invalid_json(): void
26 | {
27 | $this->expectException(InvalidArgumentException::class);
28 |
29 | /** @var Order */
30 | $order = Order::factory()->create();
31 | $address = new class($order, 'billing') extends Address
32 | {
33 | public function toArray(): array
34 | {
35 | return [
36 | 'invalid' => fopen('php://input', 'r'),
37 | ];
38 | }
39 | };
40 |
41 | $address->toJson();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/tests/Unit/Support/BillingAddressTest.php:
--------------------------------------------------------------------------------
1 | 'John',
17 | '_billing_last_name' => 'Doe',
18 | '_billing_company' => 'ACME corp.',
19 | '_billing_address_1' => 'Example Street 10',
20 | '_billing_address_2' => 'Test Address',
21 | '_billing_city' => 'Los Angeles',
22 | '_billing_state' => 'California',
23 | '_billing_postcode' => '00000',
24 | '_billing_country' => 'USA',
25 | '_billing_email' => 'john@doe.com',
26 | '_billing_phone' => '00-00-000-000',
27 | ];
28 |
29 | private const CUSTOMER_META_FIELDS = [
30 | 'billing_first_name' => 'John',
31 | 'billing_last_name' => 'Doe',
32 | 'billing_company' => 'ACME corp.',
33 | 'billing_address_1' => 'Example Street 10',
34 | 'billing_address_2' => 'Test Address',
35 | 'billing_city' => 'Los Angeles',
36 | 'billing_state' => 'California',
37 | 'billing_postcode' => '00000',
38 | 'billing_country' => 'USA',
39 | 'billing_email' => 'john@doe.com',
40 | 'billing_phone' => '00-00-000-000',
41 | ];
42 |
43 | public function test_order_billing_address_properties(): void
44 | {
45 | $billingAddress = $this->createOrderBillingAddress();
46 |
47 | $this->assertSame('John', $billingAddress->first_name);
48 | $this->assertSame('Doe', $billingAddress->last_name);
49 | $this->assertSame('ACME corp.', $billingAddress->company);
50 | $this->assertSame('Example Street 10', $billingAddress->address_1);
51 | $this->assertSame('Test Address', $billingAddress->address_2);
52 | $this->assertSame('Los Angeles', $billingAddress->city);
53 | $this->assertSame('California', $billingAddress->state);
54 | $this->assertSame('00000', $billingAddress->postcode);
55 | $this->assertSame('USA', $billingAddress->country);
56 | $this->assertSame('john@doe.com', $billingAddress->email);
57 | $this->assertSame('00-00-000-000', $billingAddress->phone);
58 | }
59 |
60 | public function test_customer_billing_address_properties(): void
61 | {
62 | $billingAddress = $this->createCustomerBillingAddress();
63 |
64 | $this->assertSame('John', $billingAddress->first_name);
65 | $this->assertSame('Doe', $billingAddress->last_name);
66 | $this->assertSame('ACME corp.', $billingAddress->company);
67 | $this->assertSame('Example Street 10', $billingAddress->address_1);
68 | $this->assertSame('Test Address', $billingAddress->address_2);
69 | $this->assertSame('Los Angeles', $billingAddress->city);
70 | $this->assertSame('California', $billingAddress->state);
71 | $this->assertSame('00000', $billingAddress->postcode);
72 | $this->assertSame('USA', $billingAddress->country);
73 | $this->assertSame('john@doe.com', $billingAddress->email);
74 | $this->assertSame('00-00-000-000', $billingAddress->phone);
75 | }
76 |
77 | public function test_to_array_method(): void
78 | {
79 | $billingAddress = $this->createOrderBillingAddress();
80 |
81 | $array = [
82 | 'first_name' => 'John',
83 | 'last_name' => 'Doe',
84 | 'company' => 'ACME corp.',
85 | 'address_1' => 'Example Street 10',
86 | 'address_2' => 'Test Address',
87 | 'city' => 'Los Angeles',
88 | 'state' => 'California',
89 | 'postcode' => '00000',
90 | 'country' => 'USA',
91 | 'email' => 'john@doe.com',
92 | 'phone' => '00-00-000-000',
93 | ];
94 |
95 | $this->assertSame($array, $billingAddress->toArray());
96 | }
97 |
98 | public function test_to_json_method(): void
99 | {
100 | $billingAddress = $this->createOrderBillingAddress();
101 |
102 | $json = '{"first_name":"John","last_name":"Doe","company":"ACME corp.","address_1":"Example Street 10","address_2":"Test Address","city":"Los Angeles","state":"California","postcode":"00000","country":"USA","email":"john@doe.com","phone":"00-00-000-000"}';
103 |
104 | $this->assertSame($json, $billingAddress->toJson());
105 | }
106 |
107 | public function test_invalid_property(): void
108 | {
109 | $this->expectException(InvalidArgumentException::class);
110 |
111 | $billingAddress = $this->createOrderBillingAddress();
112 | $billingAddress->unknown; // @phpstan-ignore-line
113 | }
114 |
115 | private function createOrderBillingAddress(): BillingAddress
116 | {
117 | /** @var Order */
118 | $order = Order::factory()->create();
119 | $order->createMeta(self::ORDER_META_FIELDS);
120 |
121 | return new BillingAddress($order);
122 | }
123 |
124 | private function createCustomerBillingAddress(): BillingAddress
125 | {
126 | /** @var Customer */
127 | $customer = Customer::factory()->create();
128 | $customer->createMeta(self::CUSTOMER_META_FIELDS);
129 |
130 | return new BillingAddress($customer);
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/tests/Unit/Support/PaymentTest.php:
--------------------------------------------------------------------------------
1 | createPayment();
17 |
18 | $this->assertSame('test', $payment->method);
19 | $this->assertSame('Test', $payment->method_title);
20 | $this->assertSame('tid-000', $payment->transaction_id);
21 | }
22 |
23 | public function test_to_array_method(): void
24 | {
25 | $payment = $this->createPayment();
26 | $array = [
27 | 'method' => 'test',
28 | 'method_title' => 'Test',
29 | 'transaction_id' => 'tid-000',
30 | ];
31 |
32 | $this->assertSame($array, $payment->toArray());
33 | }
34 |
35 | public function test_to_json_method(): void
36 | {
37 | $payment = $this->createPayment();
38 | $json = '{"method":"test","method_title":"Test","transaction_id":"tid-000"}';
39 |
40 | $this->assertSame($json, $payment->toJson());
41 | }
42 |
43 | public function test_invalid_json(): void
44 | {
45 | $this->expectException(InvalidArgumentException::class);
46 |
47 | /** @var Order */
48 | $order = Order::factory()->create();
49 | $payment = new class($order) extends Payment
50 | {
51 | public function toArray(): array
52 | {
53 | return [
54 | 'invalid' => fopen('php://input', 'r'),
55 | ];
56 | }
57 | };
58 |
59 | $payment->toJson();
60 | }
61 |
62 | private function createPayment(): Payment
63 | {
64 | /** @var Order */
65 | $order = Order::factory()->create();
66 | $order->createMeta([
67 | '_payment_method' => 'test',
68 | '_payment_method_title' => 'Test',
69 | '_transaction_id' => 'tid-000',
70 | ]);
71 |
72 | return new Payment($order);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/tests/Unit/Support/ShippingAddressTest.php:
--------------------------------------------------------------------------------
1 | 'John',
17 | '_shipping_last_name' => 'Doe',
18 | '_shipping_company' => 'ACME corp.',
19 | '_shipping_address_1' => 'Example Street 10',
20 | '_shipping_address_2' => 'Test Address',
21 | '_shipping_city' => 'Los Angeles',
22 | '_shipping_state' => 'California',
23 | '_shipping_postcode' => '00000',
24 | '_shipping_country' => 'USA',
25 | ];
26 |
27 | private const CUSTOMER_META_FIELDS = [
28 | 'shipping_first_name' => 'John',
29 | 'shipping_last_name' => 'Doe',
30 | 'shipping_company' => 'ACME corp.',
31 | 'shipping_address_1' => 'Example Street 10',
32 | 'shipping_address_2' => 'Test Address',
33 | 'shipping_city' => 'Los Angeles',
34 | 'shipping_state' => 'California',
35 | 'shipping_postcode' => '00000',
36 | 'shipping_country' => 'USA',
37 | ];
38 |
39 | public function test_order_shipping_address_properties(): void
40 | {
41 | $shippingAddress = $this->createOrderShippingAddress();
42 |
43 | $this->assertSame('John', $shippingAddress->first_name);
44 | $this->assertSame('Doe', $shippingAddress->last_name);
45 | $this->assertSame('ACME corp.', $shippingAddress->company);
46 | $this->assertSame('Example Street 10', $shippingAddress->address_1);
47 | $this->assertSame('Test Address', $shippingAddress->address_2);
48 | $this->assertSame('Los Angeles', $shippingAddress->city);
49 | $this->assertSame('California', $shippingAddress->state);
50 | $this->assertSame('00000', $shippingAddress->postcode);
51 | $this->assertSame('USA', $shippingAddress->country);
52 | }
53 |
54 | public function test_customer_shipping_address_properties(): void
55 | {
56 | $shippingAddress = $this->createCustomerShippingAddress();
57 |
58 | $this->assertSame('John', $shippingAddress->first_name);
59 | $this->assertSame('Doe', $shippingAddress->last_name);
60 | $this->assertSame('ACME corp.', $shippingAddress->company);
61 | $this->assertSame('Example Street 10', $shippingAddress->address_1);
62 | $this->assertSame('Test Address', $shippingAddress->address_2);
63 | $this->assertSame('Los Angeles', $shippingAddress->city);
64 | $this->assertSame('California', $shippingAddress->state);
65 | $this->assertSame('00000', $shippingAddress->postcode);
66 | $this->assertSame('USA', $shippingAddress->country);
67 | }
68 |
69 | public function test_to_array_method(): void
70 | {
71 | $shippingAddress = $this->createOrderShippingAddress();
72 |
73 | $array = [
74 | 'first_name' => 'John',
75 | 'last_name' => 'Doe',
76 | 'company' => 'ACME corp.',
77 | 'address_1' => 'Example Street 10',
78 | 'address_2' => 'Test Address',
79 | 'city' => 'Los Angeles',
80 | 'state' => 'California',
81 | 'postcode' => '00000',
82 | 'country' => 'USA',
83 | ];
84 |
85 | $this->assertSame($array, $shippingAddress->toArray());
86 | }
87 |
88 | public function test_to_json_method(): void
89 | {
90 | $shippingAddress = $this->createOrderShippingAddress();
91 |
92 | $json = '{"first_name":"John","last_name":"Doe","company":"ACME corp.","address_1":"Example Street 10","address_2":"Test Address","city":"Los Angeles","state":"California","postcode":"00000","country":"USA"}';
93 |
94 | $this->assertSame($json, $shippingAddress->toJson());
95 | }
96 |
97 | public function test_invalid_property(): void
98 | {
99 | $this->expectException(InvalidArgumentException::class);
100 |
101 | $shippingAddress = $this->createOrderShippingAddress();
102 | $shippingAddress->unknown; // @phpstan-ignore-line
103 | }
104 |
105 | private function createOrderShippingAddress(): ShippingAddress
106 | {
107 | /** @var Order */
108 | $order = Order::factory()->create();
109 | $order->createMeta(self::ORDER_META_FIELDS);
110 |
111 | return new ShippingAddress($order);
112 | }
113 |
114 | private function createCustomerShippingAddress(): ShippingAddress
115 | {
116 | /** @var Customer */
117 | $customer = Customer::factory()->create();
118 | $customer->createMeta(self::CUSTOMER_META_FIELDS);
119 |
120 | return new ShippingAddress($customer);
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/tests/Unit/Traits/HasRelationsThroughMetaTest.php:
--------------------------------------------------------------------------------
1 | expectException(LogicException::class);
19 |
20 | $model = new class extends Model
21 | {
22 | /** @use HasRelationsThroughMeta */
23 | use HasRelationsThroughMeta;
24 |
25 | /**
26 | * @return HasMany
27 | */
28 | public function relatedObjects(): HasMany
29 | {
30 | return $this->hasManyThroughMeta(Model::class, '_meta_key', 'foreign_key', 'local_key');
31 | }
32 | };
33 |
34 | $model->relatedObjects; // @phpstan-ignore-line
35 | }
36 |
37 | public function test_invalid_meta(): void
38 | {
39 | $this->expectException(InvalidArgumentException::class);
40 |
41 | $model = new class extends Model
42 | {
43 | /** @use HasRelationsThroughMeta */
44 | use HasRelationsThroughMeta;
45 |
46 | /** @var \Corcel\Model */
47 | private $relatedModel;
48 |
49 | public function setRelatedModel(Model $relatedModel): void
50 | {
51 | $this->relatedModel = $relatedModel;
52 | }
53 |
54 | /**
55 | * @return HasMany
56 | */
57 | public function relatedObjects(): HasMany
58 | {
59 | return $this->hasManyThroughMeta(get_class($this->relatedModel), '_meta_key', 'foreign_key', 'local_key');
60 | }
61 | };
62 |
63 | $model->setRelatedModel(new class extends Model
64 | {
65 | /**
66 | * @return HasMany<\Corcel\Model, Model>
67 | */
68 | public function meta(): HasMany
69 | {
70 | return $this->hasMany(Model::class);
71 | }
72 | });
73 |
74 | $model->relatedObjects; // @phpstan-ignore-line
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/tests/Unit/WooCommerceTest.php:
--------------------------------------------------------------------------------
1 | insert([
16 | 'option_name' => 'woocommerce_currency',
17 | 'option_value' => 'EUR',
18 | ]);
19 |
20 | $this->assertSame('EUR', WooCommerce::currency());
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tests/database/factories/CustomerFactory.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class CustomerFactory extends Factory
15 | {
16 | protected $model = Customer::class;
17 |
18 | /**
19 | * Define the model's default state.
20 | *
21 | * @return array
22 | */
23 | public function definition()
24 | {
25 | $name = $this->faker->firstName;
26 |
27 | return [
28 | 'user_login' => Str::lower(Str::ascii($name)),
29 | 'user_pass' => bcrypt('secret'),
30 | 'user_nicename' => $name,
31 | 'user_email' => $this->faker->email,
32 | 'user_url' => $this->faker->url,
33 | 'user_registered' => $this->faker->dateTime,
34 | 'user_activation_key' => Str::random(10),
35 | 'user_status' => 0,
36 | 'display_name' => $name,
37 | ];
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/database/factories/ItemFactory.php:
--------------------------------------------------------------------------------
1 |
12 | */
13 | class ItemFactory extends Factory
14 | {
15 | protected $model = Item::class;
16 |
17 | /**
18 | * Define the model's default state.
19 | *
20 | * @return array
21 | */
22 | public function definition()
23 | {
24 | return [
25 | 'order_item_name' => $this->faker->words(mt_rand(2, 4), true),
26 | 'order_item_type' => $this->faker->randomElement(['line_item', 'tax', 'coupon']),
27 | 'order_id' => $this->faker->numberBetween(1, 10000),
28 | ];
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tests/database/factories/OrderFactory.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class OrderFactory extends Factory
16 | {
17 | protected $model = Order::class;
18 |
19 | /**
20 | * Define the model's default state.
21 | *
22 | * @return array
23 | */
24 | public function definition()
25 | {
26 | $createdAt = DateTimeImmutable::createFromMutable($this->faker->dateTime('now', 'Europe/Warsaw'));
27 | $createdAtGMT = $createdAt->setTimezone(new DateTimeZone('UTC'));
28 |
29 | return [
30 | 'post_author' => $this->faker->numberBetween(1, 100),
31 | 'post_date' => $createdAt->format('Y-m-d H:i:s'),
32 | 'post_date_gmt' => $createdAtGMT->format('Y-m-d H:i:s'),
33 | 'post_content' => '',
34 | 'post_title' => sprintf('Order – %s', $createdAt->format('F j, Y @ h:i A')),
35 | 'post_excerpt' => '',
36 | 'post_status' => 'wc-completed',
37 | 'comment_status' => 'closed',
38 | 'ping_status' => 'closed',
39 | 'post_password' => '',
40 | 'post_name' => '',
41 | 'to_ping' => '',
42 | 'pinged' => '',
43 | 'post_modified' => $createdAt->format('Y-m-d H:i:s'),
44 | 'post_modified_gmt' => $createdAtGMT->format('Y-m-d H:i:s'),
45 | 'post_content_filtered' => '',
46 | 'post_parent' => 0,
47 | 'guid' => 'http://woocommerce.example/?post_type=shop_order&p=1',
48 | 'menu_order' => 0,
49 | 'post_type' => 'shop_order',
50 | 'post_mime_type' => '',
51 | 'comment_count' => 0,
52 | ];
53 | }
54 |
55 | /**
56 | * Applies pending state to model.
57 | *
58 | * @return Factory
59 | */
60 | public function pending(): Factory
61 | {
62 | return $this->state(fn () => ['post_status' => 'wc-pending']);
63 | }
64 |
65 | /**
66 | * Applies cancelling state to model.
67 | *
68 | * @return Factory
69 | */
70 | public function cancelled(): Factory
71 | {
72 | return $this->state(fn () => ['post_status' => 'wc-cancelled']);
73 | }
74 |
75 | /**
76 | * Applies refunded state to model.
77 | *
78 | * @return Factory
79 | */
80 | public function refunded(): Factory
81 | {
82 | return $this->state(fn () => ['post_status' => 'wc-refunded']);
83 | }
84 |
85 | /**
86 | * Applies withMeta state to model.
87 | *
88 | * @return Factory
89 | */
90 | public function withMeta(): Factory
91 | {
92 | return $this->afterCreating(function (Order $order) {
93 | $order->createMeta([
94 | '_order_currency' => $this->faker->currencyCode,
95 | '_order_total' => $this->faker->randomFloat(2, 0, 200),
96 | '_order_tax' => $this->faker->randomFloat(2, 0, 200),
97 | '_date_completed' => $this->faker->dateTime->format('Y-m-d H:i:s'),
98 | '_billing_first_name' => $this->faker->firstName,
99 | '_billing_last_name' => $this->faker->lastName,
100 | '_billing_company' => $this->faker->optional()->company,
101 | '_billing_address_1' => $this->faker->streetAddress,
102 | '_billing_address_2' => $this->faker->optional()->secondaryAddress,
103 | '_billing_city' => $this->faker->city,
104 | '_billing_state' => $this->faker->state,
105 | '_billing_postcode' => $this->faker->postcode,
106 | '_billing_country' => $this->faker->country,
107 | '_billing_email' => $this->faker->email,
108 | '_billing_phone' => $this->faker->phoneNumber,
109 | ]);
110 | });
111 | }
112 |
113 | /**
114 | * Applies withShipping state to model.
115 | *
116 | * @return Factory
117 | */
118 | public function withShipping(): Factory
119 | {
120 | return $this->afterCreating(function (Order $order) {
121 | $order->createMeta([
122 | '_order_shipping' => $this->faker->randomFloat(2, 0, 200),
123 | '_order_shipping_tax' => $this->faker->randomFloat(2, 0, 200),
124 | '_shipping_first_name' => $this->faker->firstName,
125 | '_shipping_last_name' => $this->faker->lastName,
126 | '_shipping_company' => $this->faker->optional()->company,
127 | '_shipping_address_1' => $this->faker->streetAddress,
128 | '_shipping_address_2' => $this->faker->optional()->secondaryAddress,
129 | '_shipping_city' => $this->faker->city,
130 | '_shipping_state' => $this->faker->state,
131 | '_shipping_postcode' => $this->faker->postcode,
132 | '_shipping_country' => $this->faker->country,
133 | ]);
134 | });
135 | }
136 |
137 | /**
138 | * Applies paid state to model.
139 | *
140 | * @return Factory
141 | */
142 | public function paid(): Factory
143 | {
144 | return $this->afterCreating(function (Order $order) {
145 | $paymentMethod = $this->faker->word;
146 |
147 | $order->createMeta([
148 | '_date_paid' => $this->faker->dateTime->format('Y-m-d H:i:s'),
149 | '_payment_method' => $paymentMethod,
150 | '_payment_method_title' => ucfirst($paymentMethod),
151 | '_transaction_id' => $this->faker->asciify('*******'),
152 | ]);
153 | });
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/tests/database/factories/ProductFactory.php:
--------------------------------------------------------------------------------
1 |
15 | */
16 | class ProductFactory extends Factory
17 | {
18 | protected $model = Product::class;
19 |
20 | /**
21 | * Define the model's default state.
22 | *
23 | * @return array
24 | */
25 | public function definition()
26 | {
27 | $createdAt = DateTimeImmutable::createFromMutable($this->faker->dateTime('now', 'Europe/Warsaw'));
28 | $createdAtGMT = $createdAt->setTimezone(new DateTimeZone('UTC'));
29 | $name = $this->faker->sentence;
30 |
31 | return [
32 | 'post_author' => $this->faker->numberBetween(1, 100),
33 | 'post_date' => $createdAt->format('Y-m-d H:i:s'),
34 | 'post_date_gmt' => $createdAtGMT->format('Y-m-d H:i:s'),
35 | 'post_content' => $this->faker->paragraphs(mt_rand(1, 5), true),
36 | 'post_title' => $name,
37 | 'post_excerpt' => $this->faker->paragraph,
38 | 'post_status' => 'publish',
39 | 'comment_status' => 'open',
40 | 'ping_status' => 'closed',
41 | 'post_password' => '',
42 | 'post_name' => Str::title($name),
43 | 'to_ping' => '',
44 | 'pinged' => '',
45 | 'post_modified' => $createdAt->format('Y-m-d H:i:s'),
46 | 'post_modified_gmt' => $createdAtGMT->format('Y-m-d H:i:s'),
47 | 'post_content_filtered' => '',
48 | 'post_parent' => 0,
49 | 'guid' => 'http://woocommerce.example/?post_type=product&p=1',
50 | 'menu_order' => 0,
51 | 'post_type' => 'product',
52 | 'post_mime_type' => '',
53 | 'comment_count' => 0,
54 | ];
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/tests/database/migrations/2020_01_01_000000_create_options_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('option_id');
20 | $table->string('option_name', 191)->default('')->index();
21 | $table->longText('option_value');
22 | $table->string('autoload', 20)->default('yes');
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('options');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/database/migrations/2020_01_01_000000_create_postmeta_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('meta_id');
20 | $table->unsignedBigInteger('post_id')->default(0)->index();
21 | $table->string('meta_key', 255)->nullable();
22 | $table->longText('meta_value')->nullable();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('postmeta');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/database/migrations/2020_01_01_000000_create_posts_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('ID');
20 | $table->unsignedBigInteger('post_author')->default(0)->index();
21 | $table->datetime('post_date')->default('0000-00-00 00:00:00')->index();
22 | $table->datetime('post_date_gmt')->default('0000-00-00 00:00:00');
23 | $table->longText('post_content');
24 | $table->text('post_title');
25 | $table->text('post_excerpt');
26 | $table->string('post_status', 20)->default('publish')->index();
27 | $table->string('comment_status', 20)->default('open');
28 | $table->string('ping_status', 20)->default('open');
29 | $table->string('post_password', 255)->default('');
30 | $table->string('post_name', 200)->default('')->index();
31 | $table->text('to_ping');
32 | $table->text('pinged');
33 | $table->datetime('post_modified')->default('0000-00-00 00:00:00');
34 | $table->datetime('post_modified_gmt')->default('0000-00-00 00:00:00');
35 | $table->longText('post_content_filtered');
36 | $table->unsignedBigInteger('post_parent')->default(0)->index();
37 | $table->string('guid', 255)->default('');
38 | $table->integer('menu_order')->default(0);
39 | $table->string('post_type', 20)->default('post');
40 | $table->string('post_mime_type', 100)->default('');
41 | $table->bigInteger('comment_count')->default(0);
42 | });
43 | }
44 |
45 | /**
46 | * Reverse the migrations.
47 | *
48 | * @return void
49 | */
50 | public function down()
51 | {
52 | Schema::dropIfExists('posts');
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/tests/database/migrations/2020_01_01_000000_create_term_relationships_table.php:
--------------------------------------------------------------------------------
1 | unsignedBigInteger('object_id')->default(0)->primary();
20 | $table->unsignedBigInteger('term_taxonomy_id')->default(0)->index();
21 | $table->integer('term_order');
22 | });
23 | }
24 |
25 | /**
26 | * Reverse the migrations.
27 | *
28 | * @return void
29 | */
30 | public function down()
31 | {
32 | Schema::dropIfExists('term_relationships');
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/tests/database/migrations/2020_01_01_000000_create_term_taxonomy_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('term_taxonomy_id');
20 | $table->unsignedBigInteger('term_id')->default(0)->index();
21 | $table->string('taxonomy', 32)->default('')->index();
22 | $table->longText('description');
23 | $table->unsignedBigInteger('parent_id')->default(0);
24 | $table->unsignedBigInteger('count')->default(0);
25 | });
26 | }
27 |
28 | /**
29 | * Reverse the migrations.
30 | *
31 | * @return void
32 | */
33 | public function down()
34 | {
35 | Schema::dropIfExists('term_taxonomy');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/database/migrations/2020_01_01_000000_create_terms_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('term_id');
20 | $table->string('name', 200)->default('')->index();
21 | $table->string('slug', 200)->default('')->index();
22 | $table->bigInteger('term_group')->default(0);
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('terms');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/database/migrations/2020_01_01_000000_create_usermeta_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('umeta_id');
20 | $table->unsignedBigInteger('user_id')->default(0)->index();
21 | $table->string('meta_key', 255)->nullable();
22 | $table->longText('meta_value')->nullable();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('usermeta');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/database/migrations/2020_01_01_000000_create_users_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('ID');
20 | $table->string('user_login', 60)->default('')->index();
21 | $table->string('user_pass', 255)->default('');
22 | $table->string('user_nicename', 50)->default('')->index();
23 | $table->string('user_email', 100)->default('')->index();
24 | $table->string('user_url', 100)->default('');
25 | $table->datetime('user_registered');
26 | $table->string('user_activation_key', 255)->default('');
27 | $table->integer('user_status')->default(0);
28 | $table->string('display_name', 250)->default('');
29 | });
30 | }
31 |
32 | /**
33 | * Reverse the migrations.
34 | *
35 | * @return void
36 | */
37 | public function down()
38 | {
39 | Schema::dropIfExists('users');
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/database/migrations/2020_01_01_000000_create_woocommerce_attribute_taxonomies_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('attribute_id');
20 | $table->string('attribute_name', 200)->index();
21 | $table->string('attribute_label', 200)->nullable();
22 | $table->string('attribute_type', 20);
23 | $table->string('attribute_orderby', 20);
24 | $table->tinyInteger('attribute_public')->default(1);
25 | });
26 | }
27 |
28 | /**
29 | * Reverse the migrations.
30 | *
31 | * @return void
32 | */
33 | public function down()
34 | {
35 | Schema::dropIfExists('woocommerce_attribute_taxonomies');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/database/migrations/2020_01_01_000000_create_woocommerce_order_itemmeta_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('meta_id');
20 | $table->unsignedBigInteger('order_item_id')->index();
21 | $table->string('meta_key', 255)->nullable()->index();
22 | $table->longText('meta_value')->nullable();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('woocommerce_order_itemmeta');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tests/database/migrations/2020_01_01_000000_create_woocommerce_order_items_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('order_item_id');
20 | $table->text('order_item_name');
21 | $table->string('order_item_type', 200)->default('');
22 | $table->unsignedBigInteger('order_id')->index();
23 | });
24 | }
25 |
26 | /**
27 | * Reverse the migrations.
28 | *
29 | * @return void
30 | */
31 | public function down()
32 | {
33 | Schema::dropIfExists('woocommerce_order_items');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------