This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | if ( ! defined( 'ABSPATH' ) ) { |
||
3 | exit; |
||
4 | } |
||
5 | |||
6 | /** |
||
7 | * Provides static methods as helpers. |
||
8 | * |
||
9 | * @since 4.0.0 |
||
10 | */ |
||
11 | class WC_Stripe_Helper { |
||
12 | const LEGACY_META_NAME_FEE = 'Stripe Fee'; |
||
13 | const LEGACY_META_NAME_NET = 'Net Revenue From Stripe'; |
||
14 | const META_NAME_FEE = '_stripe_fee'; |
||
15 | const META_NAME_NET = '_stripe_net'; |
||
16 | const META_NAME_STRIPE_CURRENCY = '_stripe_currency'; |
||
17 | |||
18 | /** |
||
19 | * Gets the Stripe currency for order. |
||
20 | * |
||
21 | * @since 4.1.0 |
||
22 | * @param object $order |
||
23 | * @return string $currency |
||
24 | */ |
||
25 | public static function get_stripe_currency( $order = null ) { |
||
26 | if ( is_null( $order ) ) { |
||
27 | return false; |
||
0 ignored issues
–
show
|
|||
28 | } |
||
29 | |||
30 | return $order->get_meta( self::META_NAME_STRIPE_CURRENCY, true ); |
||
31 | } |
||
32 | |||
33 | /** |
||
34 | * Updates the Stripe currency for order. |
||
35 | * |
||
36 | * @since 4.1.0 |
||
37 | * @param object $order |
||
38 | * @param string $currency |
||
39 | */ |
||
40 | public static function update_stripe_currency( $order = null, $currency ) { |
||
41 | if ( is_null( $order ) ) { |
||
42 | return false; |
||
43 | } |
||
44 | |||
45 | $order->update_meta_data( self::META_NAME_STRIPE_CURRENCY, $currency ); |
||
46 | } |
||
47 | |||
48 | /** |
||
49 | * Gets the Stripe fee for order. With legacy check. |
||
50 | * |
||
51 | * @since 4.1.0 |
||
52 | * @param object $order |
||
53 | * @return string $amount |
||
54 | */ |
||
55 | View Code Duplication | public static function get_stripe_fee( $order = null ) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
56 | if ( is_null( $order ) ) { |
||
57 | return false; |
||
0 ignored issues
–
show
The return type of
return false; (false ) is incompatible with the return type documented by WC_Stripe_Helper::get_stripe_fee of type string .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
58 | } |
||
59 | |||
60 | $amount = $order->get_meta( self::META_NAME_FEE, true ); |
||
61 | |||
62 | // If not found let's check for legacy name. |
||
63 | if ( empty( $amount ) ) { |
||
64 | $amount = $order->get_meta( self::LEGACY_META_NAME_FEE, true ); |
||
65 | |||
66 | // If found update to new name. |
||
67 | if ( $amount ) { |
||
68 | self::update_stripe_fee( $order, $amount ); |
||
69 | } |
||
70 | } |
||
71 | |||
72 | return $amount; |
||
73 | } |
||
74 | |||
75 | /** |
||
76 | * Updates the Stripe fee for order. |
||
77 | * |
||
78 | * @since 4.1.0 |
||
79 | * @param object $order |
||
80 | * @param float $amount |
||
81 | */ |
||
82 | public static function update_stripe_fee( $order = null, $amount = 0.0 ) { |
||
83 | if ( is_null( $order ) ) { |
||
84 | return false; |
||
85 | } |
||
86 | |||
87 | $order->update_meta_data( self::META_NAME_FEE, $amount ); |
||
88 | } |
||
89 | |||
90 | /** |
||
91 | * Deletes the Stripe fee for order. |
||
92 | * |
||
93 | * @since 4.1.0 |
||
94 | * @param object $order |
||
95 | */ |
||
96 | View Code Duplication | public static function delete_stripe_fee( $order = null ) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
97 | if ( is_null( $order ) ) { |
||
98 | return false; |
||
99 | } |
||
100 | |||
101 | $order_id = $order->get_id(); |
||
102 | |||
103 | delete_post_meta( $order_id, self::META_NAME_FEE ); |
||
104 | delete_post_meta( $order_id, self::LEGACY_META_NAME_FEE ); |
||
105 | } |
||
106 | |||
107 | /** |
||
108 | * Gets the Stripe net for order. With legacy check. |
||
109 | * |
||
110 | * @since 4.1.0 |
||
111 | * @param object $order |
||
112 | * @return string $amount |
||
113 | */ |
||
114 | View Code Duplication | public static function get_stripe_net( $order = null ) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
115 | if ( is_null( $order ) ) { |
||
116 | return false; |
||
0 ignored issues
–
show
The return type of
return false; (false ) is incompatible with the return type documented by WC_Stripe_Helper::get_stripe_net of type string .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
117 | } |
||
118 | |||
119 | $amount = $order->get_meta( self::META_NAME_NET, true ); |
||
120 | |||
121 | // If not found let's check for legacy name. |
||
122 | if ( empty( $amount ) ) { |
||
123 | $amount = $order->get_meta( self::LEGACY_META_NAME_NET, true ); |
||
124 | |||
125 | // If found update to new name. |
||
126 | if ( $amount ) { |
||
127 | self::update_stripe_net( $order, $amount ); |
||
128 | } |
||
129 | } |
||
130 | |||
131 | return $amount; |
||
132 | } |
||
133 | |||
134 | /** |
||
135 | * Updates the Stripe net for order. |
||
136 | * |
||
137 | * @since 4.1.0 |
||
138 | * @param object $order |
||
139 | * @param float $amount |
||
140 | */ |
||
141 | public static function update_stripe_net( $order = null, $amount = 0.0 ) { |
||
142 | if ( is_null( $order ) ) { |
||
143 | return false; |
||
144 | } |
||
145 | |||
146 | $order->update_meta_data( self::META_NAME_NET, $amount ); |
||
147 | } |
||
148 | |||
149 | /** |
||
150 | * Deletes the Stripe net for order. |
||
151 | * |
||
152 | * @since 4.1.0 |
||
153 | * @param object $order |
||
154 | */ |
||
155 | View Code Duplication | public static function delete_stripe_net( $order = null ) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
156 | if ( is_null( $order ) ) { |
||
157 | return false; |
||
158 | } |
||
159 | |||
160 | $order_id = $order->get_id(); |
||
161 | |||
162 | delete_post_meta( $order_id, self::META_NAME_NET ); |
||
163 | delete_post_meta( $order_id, self::LEGACY_META_NAME_NET ); |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * Get Stripe amount to pay |
||
168 | * |
||
169 | * @param float $total Amount due. |
||
170 | * @param string $currency Accepted currency. |
||
171 | * |
||
172 | * @return float|int |
||
173 | */ |
||
174 | public static function get_stripe_amount( $total, $currency = '' ) { |
||
175 | if ( ! $currency ) { |
||
176 | $currency = get_woocommerce_currency(); |
||
177 | } |
||
178 | |||
179 | if ( in_array( strtolower( $currency ), self::no_decimal_currencies() ) ) { |
||
180 | return absint( $total ); |
||
181 | } else { |
||
182 | return absint( wc_format_decimal( ( (float) $total * 100 ), wc_get_price_decimals() ) ); // In cents. |
||
183 | } |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Localize Stripe messages based on code |
||
188 | * |
||
189 | * @since 3.0.6 |
||
190 | * @version 3.0.6 |
||
191 | * @return array |
||
192 | */ |
||
193 | public static function get_localized_messages() { |
||
194 | return apply_filters( |
||
195 | 'wc_stripe_localized_messages', |
||
196 | array( |
||
197 | 'invalid_number' => __( 'The card number is not a valid credit card number.', 'woocommerce-gateway-stripe' ), |
||
198 | 'invalid_expiry_month' => __( 'The card\'s expiration month is invalid.', 'woocommerce-gateway-stripe' ), |
||
199 | 'invalid_expiry_year' => __( 'The card\'s expiration year is invalid.', 'woocommerce-gateway-stripe' ), |
||
200 | 'invalid_cvc' => __( 'The card\'s security code is invalid.', 'woocommerce-gateway-stripe' ), |
||
201 | 'incorrect_number' => __( 'The card number is incorrect.', 'woocommerce-gateway-stripe' ), |
||
202 | 'incomplete_number' => __( 'The card number is incomplete.', 'woocommerce-gateway-stripe' ), |
||
203 | 'incomplete_cvc' => __( 'The card\'s security code is incomplete.', 'woocommerce-gateway-stripe' ), |
||
204 | 'incomplete_expiry' => __( 'The card\'s expiration date is incomplete.', 'woocommerce-gateway-stripe' ), |
||
205 | 'expired_card' => __( 'The card has expired.', 'woocommerce-gateway-stripe' ), |
||
206 | 'incorrect_cvc' => __( 'The card\'s security code is incorrect.', 'woocommerce-gateway-stripe' ), |
||
207 | 'incorrect_zip' => __( 'The card\'s zip code failed validation.', 'woocommerce-gateway-stripe' ), |
||
208 | 'invalid_expiry_year_past' => __( 'The card\'s expiration year is in the past', 'woocommerce-gateway-stripe' ), |
||
209 | 'card_declined' => __( 'The card was declined.', 'woocommerce-gateway-stripe' ), |
||
210 | 'missing' => __( 'There is no card on a customer that is being charged.', 'woocommerce-gateway-stripe' ), |
||
211 | 'processing_error' => __( 'An error occurred while processing the card.', 'woocommerce-gateway-stripe' ), |
||
212 | 'invalid_sofort_country' => __( 'The billing country is not accepted by SOFORT. Please try another country.', 'woocommerce-gateway-stripe' ), |
||
213 | 'email_invalid' => __( 'Invalid email address, please correct and try again.', 'woocommerce-gateway-stripe' ), |
||
214 | 'invalid_request_error' => is_add_payment_method_page() |
||
215 | ? __( 'Unable to save this payment method, please try again or use alternative method.', 'woocommerce-gateway-stripe' ) |
||
216 | : __( 'Unable to process this payment, please try again or use alternative method.', 'woocommerce-gateway-stripe' ), |
||
217 | ) |
||
218 | ); |
||
219 | } |
||
220 | |||
221 | /** |
||
222 | * List of currencies supported by Stripe that has no decimals |
||
223 | * https://stripe.com/docs/currencies#zero-decimal from https://stripe.com/docs/currencies#presentment-currencies |
||
224 | * |
||
225 | * @return array $currencies |
||
226 | */ |
||
227 | public static function no_decimal_currencies() { |
||
228 | return array( |
||
229 | 'bif', // Burundian Franc |
||
230 | 'clp', // Chilean Peso |
||
231 | 'djf', // Djiboutian Franc |
||
232 | 'gnf', // Guinean Franc |
||
233 | 'jpy', // Japanese Yen |
||
234 | 'kmf', // Comorian Franc |
||
235 | 'krw', // South Korean Won |
||
236 | 'mga', // Malagasy Ariary |
||
237 | 'pyg', // Paraguayan Guaraní |
||
238 | 'rwf', // Rwandan Franc |
||
239 | 'ugx', // Ugandan Shilling |
||
240 | 'vnd', // Vietnamese Đồng |
||
241 | 'vuv', // Vanuatu Vatu |
||
242 | 'xaf', // Central African Cfa Franc |
||
243 | 'xof', // West African Cfa Franc |
||
244 | 'xpf', // Cfp Franc |
||
245 | ); |
||
246 | } |
||
247 | |||
248 | /** |
||
249 | * Stripe uses smallest denomination in currencies such as cents. |
||
250 | * We need to format the returned currency from Stripe into human readable form. |
||
251 | * The amount is not used in any calculations so returning string is sufficient. |
||
252 | * |
||
253 | * @param object $balance_transaction |
||
254 | * @param string $type Type of number to format |
||
255 | * @return string |
||
256 | */ |
||
257 | public static function format_balance_fee( $balance_transaction, $type = 'fee' ) { |
||
258 | if ( ! is_object( $balance_transaction ) ) { |
||
259 | return; |
||
260 | } |
||
261 | |||
262 | if ( in_array( strtolower( $balance_transaction->currency ), self::no_decimal_currencies() ) ) { |
||
263 | if ( 'fee' === $type ) { |
||
264 | return $balance_transaction->fee; |
||
265 | } |
||
266 | |||
267 | return $balance_transaction->net; |
||
268 | } |
||
269 | |||
270 | if ( 'fee' === $type ) { |
||
271 | return number_format( $balance_transaction->fee / 100, 2, '.', '' ); |
||
272 | } |
||
273 | |||
274 | return number_format( $balance_transaction->net / 100, 2, '.', '' ); |
||
275 | } |
||
276 | |||
277 | /** |
||
278 | * Checks Stripe minimum order value authorized per currency |
||
279 | */ |
||
280 | public static function get_minimum_amount() { |
||
281 | // Check order amount |
||
282 | switch ( get_woocommerce_currency() ) { |
||
283 | case 'USD': |
||
284 | case 'CAD': |
||
285 | case 'EUR': |
||
286 | case 'CHF': |
||
287 | case 'AUD': |
||
288 | case 'SGD': |
||
289 | $minimum_amount = 50; |
||
290 | break; |
||
291 | case 'GBP': |
||
292 | $minimum_amount = 30; |
||
293 | break; |
||
294 | case 'DKK': |
||
295 | $minimum_amount = 250; |
||
296 | break; |
||
297 | case 'NOK': |
||
298 | case 'SEK': |
||
299 | $minimum_amount = 300; |
||
300 | break; |
||
301 | case 'JPY': |
||
302 | $minimum_amount = 5000; |
||
303 | break; |
||
304 | case 'MXN': |
||
305 | $minimum_amount = 1000; |
||
306 | break; |
||
307 | case 'HKD': |
||
308 | $minimum_amount = 400; |
||
309 | break; |
||
310 | default: |
||
311 | $minimum_amount = 50; |
||
312 | break; |
||
313 | } |
||
314 | |||
315 | return $minimum_amount; |
||
316 | } |
||
317 | |||
318 | /** |
||
319 | * Gets all the saved setting options from a specific method. |
||
320 | * If specific setting is passed, only return that. |
||
321 | * |
||
322 | * @since 4.0.0 |
||
323 | * @version 4.0.0 |
||
324 | * @param string $method The payment method to get the settings from. |
||
325 | * @param string $setting The name of the setting to get. |
||
326 | */ |
||
327 | public static function get_settings( $method = null, $setting = null ) { |
||
328 | $all_settings = null === $method ? get_option( 'woocommerce_stripe_settings', array() ) : get_option( 'woocommerce_stripe_' . $method . '_settings', array() ); |
||
329 | |||
330 | if ( null === $setting ) { |
||
331 | return $all_settings; |
||
332 | } |
||
333 | |||
334 | return isset( $all_settings[ $setting ] ) ? $all_settings[ $setting ] : ''; |
||
335 | } |
||
336 | |||
337 | /** |
||
338 | * Checks if Pre Orders is available. |
||
339 | * |
||
340 | * @since 4.1.0 |
||
341 | * @return bool |
||
342 | */ |
||
343 | public static function is_pre_orders_exists() { |
||
344 | return class_exists( 'WC_Pre_Orders_Order' ); |
||
345 | } |
||
346 | |||
347 | /** |
||
348 | * Checks if WC version is less than passed in version. |
||
349 | * |
||
350 | * @since 4.1.11 |
||
351 | * @param string $version Version to check against. |
||
352 | * @return bool |
||
353 | */ |
||
354 | public static function is_wc_lt( $version ) { |
||
355 | return version_compare( WC_VERSION, $version, '<' ); |
||
356 | } |
||
357 | |||
358 | /** |
||
359 | * Gets the webhook URL for Stripe triggers. Used mainly for |
||
360 | * asyncronous redirect payment methods in which statuses are |
||
361 | * not immediately chargeable. |
||
362 | * |
||
363 | * @since 4.0.0 |
||
364 | * @version 4.0.0 |
||
365 | * @return string |
||
366 | */ |
||
367 | public static function get_webhook_url() { |
||
368 | return add_query_arg( 'wc-api', 'wc_stripe', trailingslashit( get_home_url() ) ); |
||
369 | } |
||
370 | |||
371 | /** |
||
372 | * Gets the order by Stripe source ID. |
||
373 | * |
||
374 | * @since 4.0.0 |
||
375 | * @version 4.0.0 |
||
376 | * @param string $source_id |
||
377 | */ |
||
378 | View Code Duplication | public static function get_order_by_source_id( $source_id ) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
379 | global $wpdb; |
||
380 | |||
381 | $order_id = $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT ID FROM $wpdb->posts as posts LEFT JOIN $wpdb->postmeta as meta ON posts.ID = meta.post_id WHERE meta.meta_value = %s AND meta.meta_key = %s", $source_id, '_stripe_source_id' ) ); |
||
382 | |||
383 | if ( ! empty( $order_id ) ) { |
||
384 | return wc_get_order( $order_id ); |
||
385 | } |
||
386 | |||
387 | return false; |
||
388 | } |
||
389 | |||
390 | /** |
||
391 | * Gets the order by Stripe charge ID. |
||
392 | * |
||
393 | * @since 4.0.0 |
||
394 | * @since 4.1.16 Return false if charge_id is empty. |
||
395 | * @param string $charge_id |
||
396 | */ |
||
397 | View Code Duplication | public static function get_order_by_charge_id( $charge_id ) { |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
398 | global $wpdb; |
||
399 | |||
400 | if ( empty( $charge_id ) ) { |
||
401 | return false; |
||
402 | } |
||
403 | |||
404 | $order_id = $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT ID FROM $wpdb->posts as posts LEFT JOIN $wpdb->postmeta as meta ON posts.ID = meta.post_id WHERE meta.meta_value = %s AND meta.meta_key = %s", $charge_id, '_transaction_id' ) ); |
||
405 | |||
406 | if ( ! empty( $order_id ) ) { |
||
407 | return wc_get_order( $order_id ); |
||
408 | } |
||
409 | |||
410 | return false; |
||
411 | } |
||
412 | |||
413 | /** |
||
414 | * Gets the order by Stripe PaymentIntent ID. |
||
415 | * |
||
416 | * @since 4.2 |
||
417 | * @param string $intent_id The ID of the intent. |
||
418 | * @return WC_Order|bool Either an order or false when not found. |
||
419 | */ |
||
420 | View Code Duplication | public static function get_order_by_intent_id( $intent_id ) { |
|
421 | global $wpdb; |
||
422 | |||
423 | $order_id = $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT ID FROM $wpdb->posts as posts LEFT JOIN $wpdb->postmeta as meta ON posts.ID = meta.post_id WHERE meta.meta_value = %s AND meta.meta_key = %s", $intent_id, '_stripe_intent_id' ) ); |
||
424 | |||
425 | if ( ! empty( $order_id ) ) { |
||
426 | return wc_get_order( $order_id ); |
||
427 | } |
||
428 | |||
429 | return false; |
||
430 | } |
||
431 | |||
432 | /** |
||
433 | * Gets the order by Stripe SetupIntent ID. |
||
434 | * |
||
435 | * @since 4.3 |
||
436 | * @param string $intent_id The ID of the intent. |
||
437 | * @return WC_Order|bool Either an order or false when not found. |
||
438 | */ |
||
439 | View Code Duplication | public static function get_order_by_setup_intent_id( $intent_id ) { |
|
440 | global $wpdb; |
||
441 | |||
442 | $order_id = $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT ID FROM $wpdb->posts as posts LEFT JOIN $wpdb->postmeta as meta ON posts.ID = meta.post_id WHERE meta.meta_value = %s AND meta.meta_key = %s", $intent_id, '_stripe_setup_intent' ) ); |
||
443 | |||
444 | if ( ! empty( $order_id ) ) { |
||
445 | return wc_get_order( $order_id ); |
||
446 | } |
||
447 | |||
448 | return false; |
||
449 | } |
||
450 | |||
451 | /** |
||
452 | * Sanitize statement descriptor text. |
||
453 | * |
||
454 | * Stripe requires max of 22 characters and no |
||
455 | * special characters with ><"'. |
||
456 | * |
||
457 | * @since 4.0.0 |
||
458 | * @param string $statement_descriptor |
||
459 | * @return string $statement_descriptor Sanitized statement descriptor |
||
460 | */ |
||
461 | public static function clean_statement_descriptor( $statement_descriptor = '' ) { |
||
462 | $disallowed_characters = array( '<', '>', '"', "'" ); |
||
463 | |||
464 | // Remove special characters. |
||
465 | $statement_descriptor = str_replace( $disallowed_characters, '', $statement_descriptor ); |
||
466 | |||
467 | $statement_descriptor = substr( trim( $statement_descriptor ), 0, 22 ); |
||
468 | |||
469 | return $statement_descriptor; |
||
470 | } |
||
471 | } |
||
472 |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.