Repository: opensourcepos/opensourcepos (language: php)

Issue:
[Feature]: PHP 8.4 Compatibility
### Type of Feature

✨ New Feature

### OpensourcePOS Version

opensourcepos 3.4

### Description

The PHP Lint for PHP 8.4 fails with the following deprecation warnings.  These need to be resolved for the code to pass the linter.
Deprecated: to_decimals(): Implicitly marking parameter $decimals as nullable is deprecated, the explicit nullable type must be used instead in ./app/Helpers/locale_helper.php on line 437

Deprecated: parse_decimals(): Implicitly marking parameter $decimals as nullable is deprecated, the explicit nullable type must be used instead in ./app/Helpers/locale_helper.php on line 481

Deprecated: App\Models\Item::get_search_suggestion_format(): Implicitly marking parameter $seed as nullable is deprecated, the explicit nullable type must be used instead in ./app/Models/Item.php on line 575

Deprecated: App\Models\Item::change_cost_price(): Implicitly marking parameter $old_price as nullable is deprecated, the explicit nullable type must be used instead in ./app/Models/Item.php on line 1127

Deprecated: App\Models\Item::get_item_name(): Implicitly marking parameter $as_name as nullable is deprecated, the explicit nullable type must be used instead in ./app/Models/Item.php on line 1191

Deprecated: App\Models\Sale::get_all_suspended(): Implicitly marking parameter $customer_id as nullable is deprecated, the explicit nullable type must be used instead in ./app/Models/Sale.php on line 1234

Deprecated: app\Libraries\Tax_lib::update_taxes(): Implicitly marking parameter $tax_code_id as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Tax_lib.php on line 211

Deprecated: app\Libraries\Tax_lib::update_taxes(): Implicitly marking parameter $jurisdiction_id as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Tax_lib.php on line 211

Deprecated: app\Libraries\Tax_lib::update_taxes(): Implicitly marking parameter $tax_category_id as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Tax_lib.php on line 211

Deprecated: app\Libraries\Sale_lib::add_item(): Implicitly marking parameter $kit_price_option as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Sale_lib.php on line 1033

Deprecated: app\Libraries\Sale_lib::add_item(): Implicitly marking parameter $kit_print_option as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Sale_lib.php on line 1033

Deprecated: app\Libraries\Sale_lib::add_item(): Implicitly marking parameter $price_override as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Sale_lib.php on line 1033

Deprecated: app\Libraries\Sale_lib::add_item(): Implicitly marking parameter $description as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Sale_lib.php on line 1033

Deprecated: app\Libraries\Sale_lib::add_item(): Implicitly marking parameter $serialnumber as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Sale_lib.php on line 1033

Deprecated: app\Libraries\Sale_lib::add_item(): Implicitly marking parameter $sale_id as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Sale_lib.php on line 1033

Deprecated: app\Libraries\Sale_lib::add_item(): Implicitly marking parameter $print_option as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Sale_lib.php on line 1033

Deprecated: app\Libraries\Sale_lib::add_item(): Implicitly marking parameter $line as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Sale_lib.php on line 1033

Deprecated: app\Libraries\Email_lib::sendEmail(): Implicitly marking parameter $attachment as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Email_lib.php on line 56

Deprecated: app\Libraries\MY_Email::sendMail(): Implicitly marking parameter $to as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/MY_Email.php on line 31

Deprecated: app\Libraries\MY_Email::sendMail(): Implicitly marking parameter $reply_name as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/MY_Email.php on line 31

Deprecated: app\Libraries\MY_Email::sendMail(): Implicitly marking parameter $reply_mail as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/MY_Email.php on line 31

Deprecated: app\Libraries\MY_Email::sendMail(): Implicitly marking parameter $attachment as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/MY_Email.php on line 31

Deprecated: app\Libraries\Receiving_lib::add_item(): Implicitly marking parameter $item_location as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Receiving_lib.php on line 277

Deprecated: app\Libraries\Receiving_lib::add_item(): Implicitly marking parameter $price as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Receiving_lib.php on line 277

Deprecated: app\Libraries\Receiving_lib::add_item(): Implicitly marking parameter $description as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Receiving_lib.php on line 277

Deprecated: app\Libraries\Receiving_lib::add_item(): Implicitly marking parameter $serialnumber as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Receiving_lib.php on line 277

Deprecated: app\Libraries\Receiving_lib::add_item(): Implicitly marking parameter $receiving_quantity as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Receiving_lib.php on line 277

Deprecated: app\Libraries\Receiving_lib::add_item(): Implicitly marking parameter $receiving_id as nullable is deprecated, the explicit nullable type must be used instead in ./app/Libraries/Receiving_lib.php on line 277

Deprecated: App\Controllers\Persons::__construct(): Implicitly marking parameter $module_id as nullable is deprecated, the explicit nullable type must be used instead in ./app/Controllers/Persons.php on line 16

Deprecated: App\Controllers\Secure_Controller::__construct(): Implicitly marking parameter $submodule_id as nullable is deprecated, the explicit nullable type must be used instead in ./app/Controllers/Secure_Controller.php on line 35

Deprecated: App\Controllers\Secure_Controller::__construct(): Implicitly marking parameter $menu_group as nullable is deprecated, the explicit nullable type must be used instead in ./app/Controllers/Secure_Controller.php on line 35

### Additional Information

_No response_

### Verify you searched open requests in OpensourcePOS

- [x] I agree I have searched Open Requests


Discussion / hints:
You need version 3.4.0 for PHP 8.x support.
Version 3.3.9 only supports up to PHP 7.x


Fix patch:
diff --git a/app/Controllers/Persons.php b/app/Controllers/Persons.php
index 28ca277e1..0ad0f6798 100644
--- a/app/Controllers/Persons.php
+++ b/app/Controllers/Persons.php
@@ -13,7 +13,7 @@ abstract class Persons extends Secure_Controller
     /**
      * @param string|null $module_id
      */
-    public function __construct(string $module_id = null)
+    public function __construct(?string $module_id = null)
     {
         parent::__construct($module_id);
 
diff --git a/app/Controllers/Secure_Controller.php b/app/Controllers/Secure_Controller.php
index bbf4c6d3a..a6def7658 100644
--- a/app/Controllers/Secure_Controller.php
+++ b/app/Controllers/Secure_Controller.php
@@ -32,7 +32,7 @@ class Secure_Controller extends BaseController
      * @param string|null $submodule_id
      * @param string|null $menu_group
      */
-    public function __construct(string $module_id = '', string $submodule_id = null, string $menu_group = null)
+    public function __construct(string $module_id = '', ?string $submodule_id = null, ?string $menu_group = null)
     {
         $this->employee = model(Employee::class);
         $this->module = model(Module::class);
diff --git a/app/Helpers/locale_helper.php b/app/Helpers/locale_helper.php
index 95e8ad5e6..e9aa4798e 100644
--- a/app/Helpers/locale_helper.php
+++ b/app/Helpers/locale_helper.php
@@ -435,7 +435,7 @@ function to_quantity_decimals(?string $number): string
  * @param int $type
  * @return string
  */
-function to_decimals(?string $number, string $decimals = null, int $type = NumberFormatter::DECIMAL): string
+function to_decimals(?string $number, ?string $decimals = null, int $type = NumberFormatter::DECIMAL): string
 {
     if(!isset($number))
     {
@@ -479,7 +479,7 @@ function parse_tax(string $number): mixed
  * @param int|null $decimals
  * @return false|float|int|mixed|string
  */
-function parse_decimals(string $number, int $decimals = null): mixed
+function parse_decimals(string $number, ?int $decimals = null): mixed
 {
     if(empty($number))
     {
diff --git a/app/Libraries/Email_lib.php b/app/Libraries/Email_lib.php
index 05d10c988..3a2496515 100644
--- a/app/Libraries/Email_lib.php
+++ b/app/Libraries/Email_lib.php
@@ -53,7 +53,7 @@ public function __construct()
      * Email sending function
      * Example of use: $response = sendEmail('john@doe.com', 'Hello', 'This is a message', $filename);
      */
-    public function sendEmail(string $to, string $subject, string $message, string $attachment = null): bool
+    public function sendEmail(string $to, string $subject, string $message, ?string $attachment = null): bool
     {
         $email = $this->email;
 
diff --git a/app/Libraries/MY_Email.php b/app/Libraries/MY_Email.php
index f93ed287a..2e473617d 100644
--- a/app/Libraries/MY_Email.php
+++ b/app/Libraries/MY_Email.php
@@ -28,7 +28,7 @@ public function __construct(array $config = [])
      * @param string|null $attachment
      * @return bool
      */
-    public function sendMail(string $subject, string $body, string $to = null, string $reply_name = null, string $reply_mail = null, string $attachment = null): bool
+    public function sendMail(string $subject, string $body, ?string $to = null, ?string $reply_name = null, ?string $reply_mail = null, ?string $attachment = null): bool
     {
         $this->setReplyTo($reply_mail, $reply_name);
         $this->setFrom($this->default_sender_address, $this->default_sender_name, $this->default_bounce_address);
diff --git a/app/Libraries/Receiving_lib.php b/app/Libraries/Receiving_lib.php
index 4d2e4f4fd..09ae1abc1 100644
--- a/app/Libraries/Receiving_lib.php
+++ b/app/Libraries/Receiving_lib.php
@@ -274,7 +274,7 @@ public function clear_stock_destination(): void
      * @param bool $include_deleted
      * @return bool
      */
-    public function add_item(int $item_id, int $quantity = 1, int $item_location = null, float $discount = 0, int $discount_type = 0, float $price = null, string $description = null, string $serialnumber = null, float $receiving_quantity = null, int $receiving_id = null, bool $include_deleted = false): bool
+    public function add_item(int $item_id, int $quantity = 1, ?int $item_location = null, float $discount = 0, int $discount_type = 0, ?float $price = null, ?string $description = null, ?string $serialnumber = null, ?float $receiving_quantity = null, ?int $receiving_id = null, bool $include_deleted = false): bool
     {
         $config = config(OSPOS::class)->settings;
 
diff --git a/app/Libraries/Sale_lib.php b/app/Libraries/Sale_lib.php
index ffca37795..2960d4093 100644
--- a/app/Libraries/Sale_lib.php
+++ b/app/Libraries/Sale_lib.php
@@ -1030,7 +1030,7 @@ public function clear_rewards_remainder(): void
      * @param bool|null $line
      * @return bool
      */
-    public function add_item(int &$item_id, int $item_location, string $quantity = '1', string &$discount = '0.0', int $discount_type = 0, int $price_mode = PRICE_MODE_STANDARD, int $kit_price_option = null, int $kit_print_option = null, string $price_override = null, string $description = null, string $serialnumber = null, int $sale_id = null, bool $include_deleted = false, bool $print_option = null, bool $line = null): bool
+    public function add_item(int &$item_id, int $item_location, string $quantity = '1', string &$discount = '0.0', int $discount_type = 0, int $price_mode = PRICE_MODE_STANDARD, ?int $kit_price_option = null, ?int $kit_print_option = null, ?string $price_override = null, ?string $description = null, ?string $serialnumber = null, ?int $sale_id = null, bool $include_deleted = false, ?bool $print_option = null, ?bool $line = null): bool
     {
         $item_info = $this->item->get_info_by_id_or_number($item_id, $include_deleted);
 
diff --git a/app/Libraries/Tax_lib.php b/app/Libraries/Tax_lib.php
index 996b901d6..fab311277 100644
--- a/app/Libraries/Tax_lib.php
+++ b/app/Libraries/Tax_lib.php
@@ -208,7 +208,7 @@ public function get_included_tax(string $quantity, string $price, string $discou
     /**
     * Updates the sales_tax array which is later saved to the `sales_taxes` table and used for printing taxes on receipts and invoices
     */
-    public function update_taxes(array &$taxes, string $tax_type, string $tax_group, string $tax_rate, string $tax_basis, string $item_tax_amount, int $tax_group_sequence, int $rounding_code, int $sale_id, string $name = '', int $tax_code_id = null, int $jurisdiction_id = null, int $tax_category_id = null): void
+    public function update_taxes(array &$taxes, string $tax_type, string $tax_group, string $tax_rate, string $tax_basis, string $item_tax_amount, int $tax_group_sequence, int $rounding_code, int $sale_id, string $name = '', ?int $tax_code_id = null, ?int $jurisdiction_id = null, ?int $tax_category_id = null): void
     {
         $tax_group_index = $this->clean('X' . (float)$tax_rate . '% ' . $tax_group);    //TODO: Not sure we should be casting to a float here.  The clean() function takes a string, so it just gets converted back to a string and there's risk of inaccuracies in the value displayed.
 
diff --git a/app/Models/Item.php b/app/Models/Item.php
index 1701e0143..bbbed7712 100644
--- a/app/Models/Item.php
+++ b/app/Models/Item.php
@@ -572,7 +572,7 @@ public function delete_list(array $item_ids): bool
      * @param string|null $seed
      * @return string
      */
-    public function get_search_suggestion_format(string $seed = null): string
+    public function get_search_suggestion_format(?string $seed = null): string
     {
         $config = config(OSPOS::class)->settings;
         $seed .= ',' . $config['suggestions_first_column'];
@@ -1124,7 +1124,7 @@ public function get_categories(): ResultInterface|bool    //TODO: This function
      * caution: must be used before item_quantities gets updated, otherwise the average price is wrong!
      *
      */
-    public function change_cost_price(int $item_id, float $items_received, float $new_price, float $old_price = null): bool
+    public function change_cost_price(int $item_id, float $items_received, float $new_price, ?float $old_price = null): bool
     {
         if($old_price === null)
         {
@@ -1188,7 +1188,7 @@ public function update_item_description(int $item_id, string $item_description):
      * for a multipack environment then the item name should have the
      * pack appended to it
      */
-    public function get_item_name(string $as_name = null): string
+    public function get_item_name(?string $as_name = null): string
     {
         $config = config(OSPOS::class)->settings;
 
diff --git a/app/Models/Sale.php b/app/Models/Sale.php
index 3f56d9321..aeb3a5226 100644
--- a/app/Models/Sale.php
+++ b/app/Models/Sale.php
@@ -1231,7 +1231,7 @@ public function create_temp_table(array $inputs): void
     /**
      * Retrieves all sales that are in a suspended state
      */
-    public function get_all_suspended(int $customer_id = null): array
+    public function get_all_suspended(?int $customer_id = null): array
     {
         if($customer_id == NEW_ENTRY)
         {


Test patch: