1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4: */
3// +----------------------------------------------------------------------+
4// | Copyright (c) 1997-2005 Piotr Klaban, Damien Seguy, Helgi �ormar     |
5// |                        �orbj�rnsson, Pierre-Alain Joye               |
6// +----------------------------------------------------------------------+
7// | This source file is subject to the New BSD license, That is bundled  |
8// | with this package in the file LICENSE, and is available through      |
9// | the world-wide-web at                                                |
10// | http://www.opensource.org/licenses/bsd-license.php                   |
11// | If you did not receive a copy of the new BSDlicense and are unable   |
12// | to obtain it through the world-wide-web, please send a note to       |
13// | pajoye@php.net so we can mail you a copy immediately.                |
14// +----------------------------------------------------------------------+
15// | Author: Tomas V.V.Cox  <cox@idecnet.com>                             |
16// |         Pierre-Alain Joye <pajoye@php.net>                           |
17// +----------------------------------------------------------------------+
18//
19/**
20 * Specific validation methods for International Standard Product Numbers (ISPN)
21 *
22 * @category   Validate
23 * @package    Validate_ISPN
24 * @author     Piotr Klaban <makler@man.torun.pl>
25 * @author     Damien Seguy <dams@nexen.net>
26 * @author     Helgi �ormar �orbj�rnsson <dufuz@php.net>
27 * @copyright   1997-2005 Piotr Klaban, Damien Seguy, Helgi �ormar �orbj�rnsson,
28 *                        Pierre-Alain Joye
29 * @license    http://www.opensource.org/licenses/bsd-license.php  new BSD
30 * @version    CVS: $Id$
31 * @link       http://pear.php.net/package/Validate_ISPN
32 */
33require_once 'Validate.php';
34
35/**
36 * Data validation class for International Standard Product Numbers (ISPN)
37 *
38 * This class provides methods to validate:
39 *  - ISBN (International Standard Book Number)
40 *  - ISSN (International Standard Serial Number)
41 *  - ISMN (International Standard Music Number)
42 *  - ISRC (International Standard Recording Code)
43 *  - EAN/UCC-8 number
44 *  - EAN/UCC-13 number
45 *  - EAN/UCC-14 number
46 *  - UCC-12 (U.P.C.) ID number
47 *  - SSCC (Serial Shipping Container Code)
48 *
49 * @category   Validate
50 * @package    Validate_ISPN
51 * @author     Piotr Klaban <makler@man.torun.pl>
52 * @author     Damien Seguy <dams@nexen.net>
53 * @author     Helgi �ormar �orbj�rnsson <dufuz@php.net>
54 * @copyright   1997-2005 Piotr Klaban, Damien Seguy, Helgi �ormar �orbj�rnsson,
55 *                        Pierre-Alain Joye
56 * @license    http://www.opensource.org/licenses/bsd-license.php  new BSD
57 * @version    Release: @package_version@
58 * @link       http://pear.php.net/package/Validate_ISPN
59 */
60class Validate_ISPN extends Validate
61{
62    public static function isbn($isbn)
63    {
64        if (preg_match("/[^0-9 IXSBN-]/", $isbn)) {
65            return false;
66        }
67
68        $isbn = strtoupper($isbn);
69        $isbn = str_replace(array('ISBN', '-', ' ', "\t", "\n"), '', $isbn);
70
71        if (strlen($isbn) == 13) {
72            return Validate_ISPN::isbn13($isbn);
73        } elseif (strlen($isbn) == 10) {
74            return Validate_ISPN::isbn10($isbn);
75        }
76
77        return false;
78    }
79
80    /**
81     * Validate a ISBN 13 number (basically ean13)
82     * The ISBN is a unique machine-readable identification number,
83     * which marks any book unmistakably.
84     *
85     * This function checks given number according
86     *
87     * Manual can be found at http://www.isbn-international.org
88     *
89     * @param  string  $isbn number (only numeric chars will be considered)
90     * @return bool    true if number is valid, otherwise false
91     * @access public
92     * @author Helgi �ormar �orbj�rnsson <dufuz@php.net>
93     * @author Piotr Klaban <makler@man.torun.pl>
94     */
95    public static function isbn13($isbn)
96    {
97        if (preg_match("/[^0-9 ISBN-]/", $isbn)) {
98            return false;
99        }
100
101        $isbn = strtoupper($isbn);
102        $isbn = str_replace(array('ISBN', '-', ' ', "\t", "\n"), '', $isbn);
103        if (!preg_match('/^[0-9]{13}$/', $isbn)) {
104            return false;
105        }
106
107        return Validate_ISPN::ean13($isbn);
108    }
109
110    /**
111     * Validate a ISBN 10 number
112     * The ISBN is a unique machine-readable identification number,
113     * which marks any book unmistakably.
114     *
115     * This function checks given number according
116     *
117     * Manual can be found at http://www.isbn-international.org
118     *
119     * @param  string  $isbn number (only numeric chars will be considered)
120     * @return bool    true if number is valid, otherwise false
121     * @access public
122     * @author Damien Seguy <dams@nexen.net>
123     * @author Helgi �ormar �orbj�rnsson <dufuz@php.net>
124     */
125    public static function isbn10($isbn)
126    {
127        static  $weights_isbn = array(10,9,8,7,6,5,4,3,2);
128
129        if (preg_match("/[^0-9 IXSBN-]/", $isbn)) {
130            return false;
131        }
132
133        $isbn = strtoupper($isbn);
134        $isbn = str_replace(array('ISBN', '-', ' ', "\t", "\n"), '', $isbn);
135        if (strlen($isbn) != 10) {
136            return false;
137        }
138
139        if (!preg_match('/^[0-9]{9}[0-9X]$/', $isbn)) {
140            return false;
141        }
142
143        // Inherits from base class Validate
144        return self::_checkControlNumber($isbn, $weights_isbn, 11, 11);
145    }
146
147
148    /**
149     * Validate an ISSN (International Standard Serial Number)
150     *
151     * This function checks given ISSN number
152     * ISSN identifies periodical publications:
153     * http://www.issn.org
154     *
155     * @param  string  $issn number (only numeric chars will be considered)
156     * @return bool    true if number is valid, otherwise false
157     * @access public
158     * @author Piotr Klaban <makler@man.torun.pl>
159     */
160    public static function issn($issn)
161    {
162        static $weights_issn = array(8,7,6,5,4,3,2);
163
164        $issn = strtoupper($issn);
165        $issn = str_replace(array('ISSN', '-', '/', ' ', "\t", "\n"), '', $issn);
166        $issn_num = str_replace('X', '0', $issn);
167
168        // check if this is an 8-digit number
169        if (!is_numeric($issn_num) || strlen($issn) != 8) {
170            return false;
171        }
172
173        // Inherits from base class Validate
174        return self::_checkControlNumber($issn, $weights_issn, 11, 11);
175    }
176
177    /**
178     * Validate a ISMN (International Standard Music Number)
179     *
180     * This function checks given ISMN number (ISO Standard 10957)
181     * ISMN identifies all printed music publications from all over the world
182     * whether available for sale, hire or gratis--whether a part, a score,
183     * or an element in a multi-media kit.
184     *
185     * Manual can be found at:
186     * http://www.ismn-international.org/
187     *
188     * @param  string  $ismn ISMN number
189     * @return bool    true if number is valid, otherwise false
190     * @access public
191     * @author Piotr Klaban <makler@man.torun.pl>
192     */
193    public static function ismn($ismn)
194    {
195        static $weights_ismn = array(3,1,3,1,3,1,3,1,3);
196
197        $ismn = strtoupper($ismn);
198        $ismn = str_replace(array('ISMN', '-', '/', ' ', "\t", "\n"), '', $ismn);
199        // First char has to be M (after ISMN has been stripped if present)
200        if ($ismn[0] != 'M') {
201            return false;
202        }
203
204        // change M to 3
205        $ismn[0] = 3;
206
207        // check if this is a 10-digit number
208        if (!is_numeric($ismn) || strlen($ismn) != 10) {
209            return false;
210        }
211
212        // Inherits from base class Validate
213        return self::_checkControlNumber($ismn, $weights_ismn, 10, 10);
214    }
215
216    /**
217     * Validate a ISRC (International Standard Recording Code)
218     *
219     * This function validates an International Standard Recording Code
220     * which is the international identification system for sound recordings
221     * and music videorecordings.
222     *
223     * @param  string  $isrc ISRC number
224     * @return bool    true if number is valid, otherwise false
225     * @see    http://www.ifpi.org/isrc/isrc_handbook.html
226     * @access public
227     * @author David Grant <david@grant.org.uk>
228     */
229    public static function isrc($isrc)
230    {
231        $isrc = str_replace(array('ISRC', '-', ' '), '', strtoupper($isrc));
232        if (!preg_match("/[A-Z]{2}[A-Z0-9]{3}[0-9]{7}/", $isrc)) {
233            return false;
234        }
235
236        return true;
237    }
238
239    /**
240     * Validate a EAN/UCC-8 number
241     *
242     * This function checks given EAN8 number
243     * used to identify trade items and special applications.
244     * http://www.ean-ucc.org/
245     * http://www.uc-council.org/checkdig.htm
246     *
247     * @param  string  $ean number (only numeric chars will be considered)
248     * @return bool    true if number is valid, otherwise false
249     * @access public
250     * @see Validate_ISPN::process()
251     * @author Piotr Klaban <makler@man.torun.pl>
252     */
253    public static function ean8($ean)
254    {
255        static $weights_ean8 = array(3,1,3,1,3,1,3);
256        return Validate_ISPN::process($ean, 8, $weights_ean8, 10, 10);
257    }
258
259    /**
260     * Validate a EAN/UCC-13 number
261     *
262     * This function checks given EAN/UCC-13 number used to identify
263     * trade items, locations, and special applications (e.g., coupons)
264     * http://www.ean-ucc.org/
265     * http://www.uc-council.org/checkdig.htm
266     *
267     * @param  string  $ean number (only numeric chars will be considered)
268     * @return bool    true if number is valid, otherwise false
269     * @access public
270     * @see Validate_ISPN::process()
271     * @author Piotr Klaban <makler@man.torun.pl>
272     */
273    public static function ean13($ean)
274    {
275        static $weights_ean13 = array(1,3,1,3,1,3,1,3,1,3,1,3);
276        return Validate_ISPN::process($ean, 13, $weights_ean13, 10, 10);
277    }
278
279    /**
280     * Validate a EAN/UCC-14 number
281     *
282     * This function checks given EAN/UCC-14 number
283     * used to identify trade items.
284     * http://www.ean-ucc.org/
285     * http://www.uc-council.org/checkdig.htm
286     *
287     * @param  string  $ean number (only numeric chars will be considered)
288     * @return bool    true if number is valid, otherwise false
289     * @access public
290     * @see Validate_ISPN::process()
291     * @author Piotr Klaban <makler@man.torun.pl>
292     */
293    public static function ean14($ean)
294    {
295        static $weights_ean14 = array(3,1,3,1,3,1,3,1,3,1,3,1,3);
296        return Validate_ISPN::process($ean, 14, $weights_ean14, 10, 10);
297    }
298
299    /**
300     * Validate a UCC-12 (U.P.C.) ID number
301     *
302     * This function checks given UCC-12 number used to identify
303     * trade items, locations, and special applications (e.g., * coupons)
304     * http://www.ean-ucc.org/
305     * http://www.uc-council.org/checkdig.htm
306     *
307     * @param  string  $ucc number (only numeric chars will be considered)
308     * @return bool    true if number is valid, otherwise false
309     * @access public
310     * @see Validate_ISPN::process()
311     * @author Piotr Klaban <makler@man.torun.pl>
312     */
313    public static function ucc12($ucc)
314    {
315        static $weights_ucc12 = array(3,1,3,1,3,1,3,1,3,1,3);
316        return Validate_ISPN::process($ucc, 12, $weights_ucc12, 10, 10);
317    }
318
319    /**
320     * Validate a SSCC (Serial Shipping Container Code)
321     *
322     * This function checks given SSCC number
323     * used to identify logistic units.
324     * http://www.ean-ucc.org/
325     * http://www.uc-council.org/checkdig.htm
326     *
327     * @param  string  $sscc number (only numeric chars will be considered)
328     * @return bool    true if number is valid, otherwise false
329     * @access public
330     * @see Validate_ISPN::process()
331     * @author Piotr Klaban <makler@man.torun.pl>
332     */
333    public static function sscc($sscc)
334    {
335        static $weights_sscc = array(3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3);
336        return Validate_ISPN::process($sscc, 18, $weights_sscc, 10, 10);
337    }
338
339    /**
340     * Does all the work for EAN8, EAN13, EAN14, UCC12 and SSCC
341     * and can be used for as base for similar kind of calculations
342     *
343     * @param int $data number (only numeric chars will be considered)
344     * @param int $lenght required length of number string
345     * @param int $modulo (optionsl) number
346     * @param int $subtract (optional) numbier
347     * @param array $weights holds the weight that will be used in calculations for the validation
348     * @return bool    true if number is valid, otherwise false
349     * @access public
350     * @see (new Validate)->_checkControlNumber()
351     */
352    public static function process($data, $length, &$weights, $modulo = 10, $subtract = 0)
353    {
354        $data = str_replace(array('-', '/', ' ', "\t", "\n"), '', $data);
355
356        // check if this is a digit number and is the right length
357        if (!is_numeric($data) || strlen($data) != $length) {
358            return false;
359        }
360
361        // Inherits from base class Validate
362        return self::_checkControlNumber($data, $weights, $modulo, $subtract);
363    }
364}
365