[TikiWiki-commits] [Git][tikiwiki/tiki][master] Barcode enhancements support for code128 and upc

Benoit Grégoire (@benoitg) via TikiWiki-cvs <[email protected]>
Newsgroups gmane.comp.cms.tiki.cvs
Message-ID <69616740e9698_2c1808a8700cd@gitlab-sidekiq-low-urgency-cpu-bound-v2-5f6955b989-6c8x9.mail>

Benoit Grégoire pushed to branch master at Tiki Wiki CMS Groupware / Tiki


Commits:
c8850ae6 by Elvis Ansima at 2026-01-09T20:30:14+00:00
Barcode enhancements support for code128 and upc
---
* Remove unnecessary blank line in UpcTest.php

* [NEW] Implement UPC validation logic and corresponding unit tests

* [ENH] Add UPC barcode type support

* [FIX] Update Barcode128 validation tests

* [FIX] update validation logic for C128

See merge request tikiwiki/tiki!9273

- - - - -


5 changed files:

- lib/core/Tracker/Field/BarCode.php
- lib/test/Core/Validators/Barcode128Test.php
- + lib/test/Core/Validators/UpcTest.php
- lib/validators/validator_barcode128.php
- + lib/validators/validator_upc.php


Changes:

=====================================
lib/core/Tracker/Field/BarCode.php
=====================================
@@ -35,6 +35,7 @@ class Tracker_Field_BarCode extends Tracker_Field_Text
                             'QR_CODE' => tr('QR code'),
                             'EAN_13' => tr('EAN-13'),
                             'CODE_128' => tr('Code 128'),
+                            'UPC' => tr('UPC'),
                             'Auto' => tr('Auto')
                         ],
                     ]
@@ -81,6 +82,9 @@ class Tracker_Field_BarCode extends Tracker_Field_Text
                 if ($barcode_type == "EAN_13") {
                     $data['image_output'] = $this->generate1DCode("EAN13", intval($value));
                 }
+                if ($barcode_type == "UPC") {
+                    $data['image_output'] = $this->generate1DCode("UPCA", intval($value));
+                }
             }
             return $this->renderTemplate('trackeroutput/barcode.tpl', $context, $data);
         }
@@ -155,6 +159,9 @@ class Tracker_Field_BarCode extends Tracker_Field_Text
         if ($format == "CODE_128") {
             return $validatorslib->validateInput("barcode128");
         }
+        if ($format == "UPC") {
+            return $validatorslib->validateInput("upc");
+        }
         if ($format == "QR_CODE") {
             return strlen($value) > 1 || tra("QR Code very short"); //at least 2characters
         }


=====================================
lib/test/Core/Validators/Barcode128Test.php
=====================================
@@ -18,33 +18,36 @@ class Barcode128Test extends \PHPUnit\Framework\TestCase
         $this->validatorslib = TikiLib::lib('validators');
     }
 
-    public function testNullValuesShouldNotBeValidBarcode128()
+    public function testEmptyValuesShouldNotBeValidBarcode128()
     {
-        $this->validatorslib->setInput(0);
-        $this->assertNotSame(true, $this->validatorslib->validateInput("barcode128"));
         $this->validatorslib->setInput("");
         $this->assertNotSame(true, $this->validatorslib->validateInput("barcode128"));
+        $this->validatorslib->setInput(null);
+        $this->assertNotSame(true, $this->validatorslib->validateInput("barcode128"));
     }
 
-    public function testNonNumericValuesShouldNotBeValidBarcode128()
+    public function testValidBarcode128ShouldPassValidation()
     {
+        // Code 128 can encode all ASCII characters (0-127)
+        $this->validatorslib->setInput("0");
+        $this->assertSame(true, $this->validatorslib->validateInput("barcode128"));
+        $this->validatorslib->setInput("123456789012");
+        $this->assertSame(true, $this->validatorslib->validateInput("barcode128"));
         $this->validatorslib->setInput("ABC123");
-        $this->assertNotSame(true, $this->validatorslib->validateInput("barcode128"));
-        $this->validatorslib->setInput("123456A");
-        $this->assertNotSame(true, $this->validatorslib->validateInput("barcode128"));
+        $this->assertSame(true, $this->validatorslib->validateInput("barcode128"));
+        $this->validatorslib->setInput("Test-123");
+        $this->assertSame(true, $this->validatorslib->validateInput("barcode128"));
+        $maxLengthString = str_repeat("A", 255);
+        $this->validatorslib->setInput($maxLengthString);
+        $this->assertSame(true, $this->validatorslib->validateInput("barcode128"));
     }
 
     public function testInvalidBarcode128ShouldNotPassValidation()
     {
-        $this->validatorslib->setInput("12345678901234");
+        $longString = str_repeat("A", 256);
+        $this->validatorslib->setInput($longString);
+        $this->assertNotSame(true, $this->validatorslib->validateInput("barcode128"));
+        $this->validatorslib->setInput("Test" . chr(128));
         $this->assertNotSame(true, $this->validatorslib->validateInput("barcode128"));
-    }
-
-    public function testValidBarcode128ShouldPassValidation()
-    {
-        $this->validatorslib->setInput("123456789012");
-        $this->assertSame(true, $this->validatorslib->validateInput("barcode128"));
-        $this->validatorslib->setInput("1234567890123");
-        $this->assertSame(true, $this->validatorslib->validateInput("barcode128"));
     }
 }


=====================================
lib/test/Core/Validators/UpcTest.php
=====================================
@@ -0,0 +1,57 @@
+<?php
+
+// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
+//
+// All Rights Reserved. See copyright.txt for details and a complete list of authors.
+// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
+
+namespace test\Core\Validators;
+
+use TikiLib;
+
+class UpcTest extends \PHPUnit\Framework\TestCase
+{
+    public $validatorslib;
+
+    protected function setUp(): void
+    {
+        $this->validatorslib = TikiLib::lib('validators');
+    }
+
+    public function testEmptyValuesShouldNotBeValidUpc()
+    {
+        $this->validatorslib->setInput("");
+        $this->assertNotSame(true, $this->validatorslib->validateInput("upc"));
+        $this->validatorslib->setInput(null);
+        $this->assertNotSame(true, $this->validatorslib->validateInput("upc"));
+    }
+
+    public function testValidUpcShouldPassValidation()
+    {
+        // UPC-A: 12 digits (example from Wikipedia: 03600029145x12, where x12=2)
+        $this->validatorslib->setInput("036000291452");
+        $this->assertSame(true, $this->validatorslib->validateInput("upc"));
+        // UPC-A: Another valid example
+        $this->validatorslib->setInput("012345678905");
+        $this->assertSame(true, $this->validatorslib->validateInput("upc"));
+        // UPC-E: 6 digits (compressed version of UPC-A)
+        // For "01234": odd=0+2+4=6, even=1+3=4, sum=(6*3)+4=22, M=2, check=8
+        $this->validatorslib->setInput("012348");
+        $this->assertSame(true, $this->validatorslib->validateInput("upc"));
+    }
+
+    public function testInvalidUpcShouldNotPassValidation()
+    {
+        // Non-numeric
+        $this->validatorslib->setInput("01234567890A");
+        $this->assertNotSame(true, $this->validatorslib->validateInput("upc"));
+        // Wrong length (not 12 or 6)
+        $this->validatorslib->setInput("1234567890");
+        $this->assertNotSame(true, $this->validatorslib->validateInput("upc"));
+        $this->validatorslib->setInput("12345678"); // 8 digits (old incorrect UPC-E length)
+        $this->assertNotSame(true, $this->validatorslib->validateInput("upc"));
+        // Wrong check digit
+        $this->validatorslib->setInput("036000291451"); // should be 2
+        $this->assertNotSame(true, $this->validatorslib->validateInput("upc"));
+    }
+}


=====================================
lib/validators/validator_barcode128.php
=====================================
@@ -4,19 +4,43 @@
 //
 // All Rights Reserved. See copyright.txt for details and a complete list of authors.
 // Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
+
+// Wikipedia specs : https://en.wikipedia.org/wiki/Code_128
+
 function validator_barcode128($input, $parameter = '', $message = '')
 {
-    if (empty($input)) {
+    // Check for empty input (but allow "0" as it's a valid Code 128 character)
+    if ($input === '' || $input === null) {
         return tra('Barcode128 code cannot be empty');
     }
 
-    if (! is_numeric($input)) {
-        return tra('Barcode128 Code should be a numeric value');
+    // Code 128 can encode all 128 ASCII characters (0-127)
+    // Code sets A and B cover all 128 ASCII characters
+    // Code set C is optimized for numeric data (two digits per symbol)
+    // Extended ASCII (128-255) can be encoded via FNC4, but is not commonly used
+    $length = strlen($input);
+
+    // Validate that all characters are within ASCII range (0-127)
+    for ($i = 0; $i < $length; $i++) {
+        $charCode = ord($input[$i]);
+        if ($charCode > 127) {
+            return tra('Barcode128 Code contains invalid characters. Only ASCII characters (0-127) are allowed');
+        }
     }
 
-    $length = strlen($input);
-    if ($length < 12 || $length > 13) {
-        return tra('Barcode128 Code should be 12 or 13 characters long');
+    // Code 128 length limits:
+    // - A single Code 128 symbol can encode up to 48 data characters
+    // - Multiple symbols can be used for longer data
+    // - Practical limit depends on barcode reader capabilities
+    // We set a reasonable maximum to prevent excessively long barcodes
+    if ($length > 255) {
+        return tra('Barcode128 Code is too long. Maximum length is 255 characters');
+    }
+
+    // Minimum length: Code 128 requires at least one data character
+    // (start symbol, data, check digit, stop symbol are added during encoding)
+    if ($length < 1) {
+        return tra('Barcode128 Code must contain at least one character');
     }
 
     return true;


=====================================
lib/validators/validator_upc.php
=====================================
@@ -0,0 +1,68 @@
+<?php
+
+// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
+//
+// All Rights Reserved. See copyright.txt for details and a complete list of authors.
+// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
+
+// UPC-A: 12 digits (most common)
+// UPC-E: 6 digits (compressed version of UPC-A)
+// Check digit calculation per Wikipedia: https://en.wikipedia.org/wiki/Universal_Product_Code
+
+function validator_upc($input, $parameter = '', $message = '')
+{
+    // Check for empty input (but allow "0" as it's a valid UPC character)
+    if ($input === '' || $input === null) {
+        return tra('UPC code cannot be empty');
+    }
+    if (! is_numeric($input)) {
+        return tra("UPC Code should be a numeric value");
+    }
+
+    $inputStr = (string) $input;
+    $length = strlen($inputStr);
+
+    // UPC-A: 12 digits, UPC-E: 6 digits
+    if ($length !== 12 && $length !== 6) {
+        return tra("UPC Code should be 12 digits (UPC-A) or 6 digits (UPC-E)");
+    }
+
+    $strArray = str_split($inputStr);
+
+    // Check digit calculation per Wikipedia specification:
+    // 1. Sum the digits at odd-numbered positions (1st, 3rd, 5th, ..., 11th)
+    // 2. Multiply the result by 3
+    // 3. Add the digit sum at even-numbered positions (2nd, 4th, 6th, ..., 10th)
+    // 4. Find the result modulo 10 (M)
+    // 5. If M is zero, check digit is 0; otherwise check digit is 10 - M
+    $dataLength = $length - 1;
+    $oddSum = 0;
+    $evenSum = 0;
+    $checkSumValueFromInput = -1;
+
+    foreach ($strArray as $key => $digit) {
+        if ($key < $dataLength) {
+            // Positions are 0-indexed: 0=1st (odd), 1=2nd (even), 2=3rd (odd), etc.
+            if ($key % 2 == 0) {
+                // Odd-numbered position (1st, 3rd, 5th, ...)
+                $oddSum += intval($digit);
+            } else {
+                // Even-numbered position (2nd, 4th, 6th, ...)
+                $evenSum += intval($digit);
+            }
+        } else {
+            $checkSumValueFromInput = intval($digit);
+        }
+    }
+
+    // Calculate expected check digit
+    $sum = ($oddSum * 3) + $evenSum;
+    $m = $sum % 10;
+    $expectedCheckSum = ($m == 0) ? 0 : (10 - $m);
+
+    if ($expectedCheckSum !== $checkSumValueFromInput) {
+        return tra("last digit is not correct, UPC code invalid!");
+    }
+
+    return true;
+}



View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/c8850ae6e5dae5b89ed7cd2f79fb45eb3a858bd6

-- 
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/c8850ae6e5dae5b89ed7cd2f79fb45eb3a858bd6
You're receiving this email because of your account on gitlab.com.

_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.