| @@ -0,0 +1,42 @@ | |||||
| composer.phar | |||||
| /old/ | |||||
| # Compiled source # | |||||
| ################### | |||||
| *.com | |||||
| *.class | |||||
| *.dll | |||||
| *.exe | |||||
| *.o | |||||
| *.so | |||||
| # Packages # | |||||
| ############ | |||||
| # it's better to unpack these files and commit the raw source | |||||
| # git has its own built in compression methods | |||||
| *.7z | |||||
| *.dmg | |||||
| *.gz | |||||
| *.iso | |||||
| *.jar | |||||
| *.rar | |||||
| *.tar | |||||
| *.zip | |||||
| # Logs and databases # | |||||
| ###################### | |||||
| *.log | |||||
| *.sql | |||||
| *.sqlite | |||||
| # OS generated files # | |||||
| ###################### | |||||
| .DS_Store | |||||
| .DS_Store? | |||||
| ._* | |||||
| .Spotlight-V100 | |||||
| .Trashes | |||||
| ehthumbs.db | |||||
| Thumbs.db | |||||
| @@ -0,0 +1,21 @@ | |||||
| ################################################## | |||||
| # Gustavo Arnosti Neves - 2016 Jul 11 | |||||
| # Simple makefile for system install / uninstall | |||||
| # PHP cli-barcode-generator | |||||
| # Change INSTDIR if you want to install somewhere else | |||||
| INSTDIR=/usr/local/bin | |||||
| BC_BASH=barcode | |||||
| all: | |||||
| install: | |||||
| cp ${BC_BASH} ${INSTDIR}/${BC_BASH} | |||||
| chmod 755 ${INSTDIR}/${BC_BASH} | |||||
| permissions: | |||||
| find . -type d -exec chmod 0755 {} \; | |||||
| find . -type f -exec chmod 0644 {} \; | |||||
| uninstall: | |||||
| rm ${INSTDIR}/${BC_BASH} | |||||
| @@ -0,0 +1,15 @@ | |||||
| #!/usr/bin/env bash | |||||
| ################################################## | |||||
| # Gustavo Arnosti Neves - 2016 Jul 11 | |||||
| # Simple bash script for global barcode executable | |||||
| # PHP cli-barcode-generator | |||||
| # | |||||
| # Please run "./barcode.php --create-bash" to update this script | |||||
| # You can then use sudo make install to copy it to /usr/local/bin | |||||
| # | |||||
| # This won't work on windows | |||||
| # | |||||
| BARCODE_LOCATION="./barcode.php" # enter full path here | |||||
| /usr/bin/env php "$BARCODE_LOCATION" "$@" | |||||
| @@ -0,0 +1,298 @@ | |||||
| #!/usr/bin/env php | |||||
| <?php | |||||
| ########################################################################## | |||||
| # Gustavo Arnosti Neves - 2016 Jul 11 | |||||
| # guneves < a t > gmail < d o t > com | |||||
| # | |||||
| # PHP cli-barcode-generator | |||||
| # | |||||
| # Most of the work here is for option / argument parsing. | |||||
| # Picqer's barcode framework makes it east on the bar coding generation. | |||||
| # While ulrichsg's getopt-php helps with the cli part. | |||||
| # | |||||
| ########################################################################## | |||||
| require_once 'vendor/autoload.php'; | |||||
| define("_BC_VERSION", "1.0.2"); | |||||
| # permission to set to barcode files | |||||
| define("_BC_PERMISSION", 0644); | |||||
| # group to set to barcode files (disabled at bot) | |||||
| define("_BC_SYSGROUP", "yourGrpHere"); | |||||
| # default padding for barcode | |||||
| define("_BC_PADDING", 30); | |||||
| $verbose = false; | |||||
| $quiet = false; | |||||
| $encoding = null; | |||||
| $format = null; | |||||
| $bc_string = null; | |||||
| $bc_file = null; | |||||
| $width = 2; | |||||
| $height = 30; | |||||
| $color = '#000000'; | |||||
| $encodings_list = array( | |||||
| 'CODE_39', | |||||
| 'CODE_39_CHECKSUM', | |||||
| 'CODE_39E', | |||||
| 'CODE_39E_CHECKSUM', | |||||
| 'CODE_93', | |||||
| 'STANDARD_2_5', | |||||
| 'STANDARD_2_5_CHECKSUM', | |||||
| 'INTERLEAVED_2_5', | |||||
| 'INTERLEAVED_2_5_CHECKSUM', | |||||
| 'CODE_128', | |||||
| 'CODE_128_A', | |||||
| 'CODE_128_B', | |||||
| 'CODE_128_C', | |||||
| 'EAN_2', | |||||
| 'EAN_5', | |||||
| 'EAN_8', | |||||
| 'EAN_13', | |||||
| 'UPC_A', | |||||
| 'UPC_E', | |||||
| 'MSI', | |||||
| 'MSI_CHECKSUM', | |||||
| 'POSTNET', | |||||
| 'PLANET', | |||||
| 'RMS4CC', | |||||
| 'KIX', | |||||
| 'IMB', | |||||
| 'CODABAR', | |||||
| 'CODE_11', | |||||
| 'PHARMA_CODE', | |||||
| 'PHARMA_CODE_TWO_TRACKS' | |||||
| ); | |||||
| sort($encodings_list); | |||||
| $formats_list = array( | |||||
| 'SVG', | |||||
| 'PNG', | |||||
| 'JPG', | |||||
| 'HTML' | |||||
| ); | |||||
| sort($formats_list); | |||||
| /////////////////// GETOPT STARTS | |||||
| use Ulrichsg\Getopt\Getopt; | |||||
| use Ulrichsg\Getopt\Option; | |||||
| use Ulrichsg\Getopt\Argument; | |||||
| // define and configure options | |||||
| $getopt = new Getopt(array( | |||||
| (new Option('e', 'encoding', Getopt::REQUIRED_ARGUMENT)) | |||||
| ->setDescription('Barcode encoding type selection') | |||||
| ->setValidation(function($value) { | |||||
| global $encodings_list; | |||||
| return in_array(strtoupper($value), $encodings_list); | |||||
| }) | |||||
| ->setArgument(new Argument(null, null, 'bar-type')), | |||||
| (new Option('f', 'format', Getopt::REQUIRED_ARGUMENT)) | |||||
| ->setDescription('Output format for the barcode') | |||||
| ->setValidation(function($value, $formats_list) { | |||||
| global $formats_list; | |||||
| return in_array(strtoupper($value), $formats_list); | |||||
| }) | |||||
| ->setArgument(new Argument(null, null, 'file-type')), | |||||
| (new Option('w', 'width', Getopt::REQUIRED_ARGUMENT)) | |||||
| ->setDescription('Width factor for bars to make wider, defaults to 2') | |||||
| ->setArgument(new Argument(2, 'is_numeric', 'points')), | |||||
| (new Option('h', 'height', Getopt::REQUIRED_ARGUMENT)) | |||||
| ->setDescription('Total height of the barcode, defaults to 30') | |||||
| ->setArgument(new Argument(30, 'is_numeric', 'points')), | |||||
| (new Option('c', 'color', Getopt::REQUIRED_ARGUMENT)) | |||||
| ->setDescription('Hex code of the foreground color, defaults to black') | |||||
| ->setArgument(new Argument('#000000', 'not_empty', 'hex-color')), | |||||
| (new Option('v', 'verbose')) | |||||
| ->setDescription('Display extra information') | |||||
| ->setDefaultValue(false), | |||||
| (new Option('q', 'quiet')) | |||||
| ->setDescription('Supress all messages') | |||||
| ->setDefaultValue(false), | |||||
| (new Option(null, 'help')) | |||||
| ->setDescription('Help Information, including encodings and formats'), | |||||
| (new Option(null, 'version')) | |||||
| ->setDescription('Display version information and exits'), | |||||
| (new Option(null, 'create-bash')) | |||||
| ->setDescription('Creates a bash script named barcode that can call this script') | |||||
| )); | |||||
| $getopt->setBanner("Usage: barcode -e <encoding> -f <output_format> [options] <barcode string> <output file>\n"); | |||||
| try { | |||||
| $getopt->parse(); | |||||
| if ($getopt['version']) { | |||||
| echo "PHP-CLI Barcode v"._BC_VERSION."\n"; | |||||
| exit(0); | |||||
| } | |||||
| if ($getopt['help']) { | |||||
| print_help($getopt); | |||||
| exit(0); | |||||
| } | |||||
| if ($getopt['create-bash']) { | |||||
| create_bash_script(); | |||||
| exit(1); | |||||
| } | |||||
| $verbose = $getopt['verbose']; | |||||
| $quiet = $getopt['quiet']; | |||||
| $encoding = $getopt['encoding']; | |||||
| $format = $getopt['format']; | |||||
| $width = $getopt['width']; | |||||
| $height = $getopt['height']; | |||||
| $color = $getopt['color']; | |||||
| $bc_string = $getopt->getOperand(0); | |||||
| $bc_file = $getopt->getOperand(1); | |||||
| } catch (UnexpectedValueException $e) { | |||||
| echo "Error: ".$e->getMessage()."\n"; | |||||
| echo $getopt->getHelpText(_BC_PADDING); | |||||
| exit(1); | |||||
| } | |||||
| // check if we can proceed | |||||
| if (empty($encoding) || empty($format) || empty($bc_string) || empty($bc_file)) { | |||||
| echo "Error: Invalid parameters or options.\n"; | |||||
| echo $getopt->getHelpText(_BC_PADDING); | |||||
| exit(1); | |||||
| } | |||||
| // Match case | |||||
| $encoding = strtoupper($encoding); | |||||
| $format = strtoupper($format); | |||||
| /////////////////// GETOPT ENDS | |||||
| /////////////////// CREATE BARCODE | |||||
| // creates a bash script named barcode that will run this script | |||||
| // from anywhere on the system. Assumes barcode.php is running | |||||
| // on its final installation location | |||||
| function create_bash_script() { | |||||
| $error = true; | |||||
| $bc_path = __FILE__; | |||||
| $bash_path = dirname($bc_path) . DIRECTORY_SEPARATOR . "barcode"; | |||||
| $bash_script = <<<EOF | |||||
| #!/usr/bin/env bash | |||||
| ################################################## | |||||
| # Gustavo Arnosti Neves - 2016 Jul 11 | |||||
| # Simple bash script for global barcode executable | |||||
| # PHP cli-barcode-generator | |||||
| # | |||||
| # Please run "./barcode.php --create-bash" to update this script | |||||
| # You can then use sudo make install to copy it to /usr/local/bin | |||||
| # | |||||
| # This won't work on windows | |||||
| # | |||||
| BARCODE_LOCATION="$bc_path" # enter full path here | |||||
| /usr/bin/env php "\$BARCODE_LOCATION" "\$@" | |||||
| EOF; | |||||
| if (file_exists($bash_path)) { | |||||
| unlink($bash_path) or die("Could not remove old barcode script, are you running from it?"); | |||||
| } | |||||
| $error = file_put_contents($bash_path, $bash_script) === true ? false : true; | |||||
| $error = chmod($bash_path, 0755) === true ? false : true; | |||||
| if ($error) { | |||||
| echo "\nAn error was detected during the process.\n"; | |||||
| echo "Please check for permissions and try again.\n\n"; | |||||
| exit(2); | |||||
| } | |||||
| echo "\nThe file \"$bash_path\" was successfully created.\n"; | |||||
| echo "You may perform a system install to /usr/local/bin by issuing\n"; | |||||
| echo "the command \"sudo make install\"\n\n"; | |||||
| exit(0); | |||||
| } | |||||
| // get actual barcode type string | |||||
| $bc_type = constant('Picqer\Barcode\BarcodeGenerator::TYPE_'.$encoding); | |||||
| // add trailling zero if odd digits on Code128C | |||||
| $bc_string = strlen($bc_string) % 2 == 0 && $encoding === 'CODE_128_C'? | |||||
| $bc_string : '0'.$bc_string; | |||||
| // create appropriate generator | |||||
| $generator = null; | |||||
| if ($format === 'SVG') { | |||||
| $generator = new Picqer\Barcode\BarcodeGeneratorSVG(); | |||||
| } else if ($format === 'PNG') { | |||||
| $generator = new Picqer\Barcode\BarcodeGeneratorPNG(); | |||||
| } else if ($format === 'JPG') { | |||||
| $generator = new Picqer\Barcode\BarcodeGeneratorJPG(); | |||||
| } else if ($format === 'HTML') { | |||||
| $generator = new Picqer\Barcode\BarcodeGeneratorHTML(); | |||||
| } else { | |||||
| exit(1); | |||||
| } | |||||
| // generate de barcode | |||||
| $bc_data = $generator->getBarcode($bc_string, $bc_type, $width, $height, $color); | |||||
| // save to file | |||||
| if (file_put_contents($bc_file, $bc_data) === false) { | |||||
| echo "Error: could not save file $bc_file!\n"; | |||||
| exit(1); | |||||
| } | |||||
| // set permissions and group | |||||
| chmod($bc_file, _BC_PERMISSION); | |||||
| #chgrp($bc_file, _BC_SYSGROUP); | |||||
| // prints help information | |||||
| function print_help($getopt) { | |||||
| global $encodings_list; | |||||
| global $formats_list; | |||||
| echo $getopt->getHelpText(_BC_PADDING); | |||||
| echo "\nRequired Options and Parameters:\n"; | |||||
| echo " -e <encoding>\n"; | |||||
| echo " -f <output format>\n"; | |||||
| echo " <input string>\n"; | |||||
| echo " <output file>\n"; | |||||
| echo "\nOutput Formats:\n"; | |||||
| foreach($formats_list as $for) { | |||||
| echo " $for\n"; | |||||
| } | |||||
| echo "\nEncodings:\n"; | |||||
| foreach($encodings_list as $enc) { | |||||
| echo " $enc\n"; | |||||
| } | |||||
| echo "\nExamples:\n"; | |||||
| echo " barcode -f HTML -e CODE_39 \"1234567890\" \"/tmp/1234567890.html\"\n"; | |||||
| echo " barcode -e CODE_128 -f PNG -c \"#888\" -w 3 -h 50 \"AGREATBAR\" \"/tmp/AGREATBAR.png\"\n"; | |||||
| echo " barcode \"1234567890\" \"/tmp/mybar.svg\" --encoding EAN_13 --format SVG\n"; | |||||
| } | |||||
| // check if empty (callback) | |||||
| function not_empty($str) { | |||||
| return (!empty($str)); | |||||
| } | |||||
| // done | |||||
| exit(0); | |||||
| ?> | |||||
| @@ -0,0 +1,6 @@ | |||||
| { | |||||
| "require": { | |||||
| "picqer/php-barcode-generator": "^0.1.0", | |||||
| "ulrichsg/getopt-php": "^2.3" | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,120 @@ | |||||
| { | |||||
| "_readme": [ | |||||
| "This file locks the dependencies of your project to a known state", | |||||
| "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", | |||||
| "This file is @generated automatically" | |||||
| ], | |||||
| "hash": "a723e9e5630e78d2303e845440a976b2", | |||||
| "content-hash": "8180bfe7b58f0f40617b074b3efc026a", | |||||
| "packages": [ | |||||
| { | |||||
| "name": "picqer/php-barcode-generator", | |||||
| "version": "v0.1", | |||||
| "source": { | |||||
| "type": "git", | |||||
| "url": "https://github.com/picqer/php-barcode-generator.git", | |||||
| "reference": "bd486cfb311989a506c62827fdee463b8a698002" | |||||
| }, | |||||
| "dist": { | |||||
| "type": "zip", | |||||
| "url": "https://api.github.com/repos/picqer/php-barcode-generator/zipball/bd486cfb311989a506c62827fdee463b8a698002", | |||||
| "reference": "bd486cfb311989a506c62827fdee463b8a698002", | |||||
| "shasum": "" | |||||
| }, | |||||
| "require": { | |||||
| "php": ">=5.4.0" | |||||
| }, | |||||
| "type": "library", | |||||
| "autoload": { | |||||
| "psr-4": { | |||||
| "Picqer\\Barcode\\": "src" | |||||
| } | |||||
| }, | |||||
| "notification-url": "https://packagist.org/downloads/", | |||||
| "license": [ | |||||
| "MIT" | |||||
| ], | |||||
| "authors": [ | |||||
| { | |||||
| "name": "Casper Bakker", | |||||
| "email": "info@picqer.com" | |||||
| } | |||||
| ], | |||||
| "description": "An easy to use, non-bloated, barcode generator in PHP. Creates SVG, PNG, JPG and HTML images from the most used 1D barcode standards.", | |||||
| "homepage": "http://github.com/picqer/exact-php-client", | |||||
| "keywords": [ | |||||
| "CODABAR", | |||||
| "Code11", | |||||
| "Code93", | |||||
| "EAN13", | |||||
| "KIX", | |||||
| "KIXCODE", | |||||
| "MSI", | |||||
| "POSTNET", | |||||
| "Pharma", | |||||
| "Standard 2 of 5", | |||||
| "barcode", | |||||
| "barcode generator", | |||||
| "code128", | |||||
| "code39", | |||||
| "ean", | |||||
| "html", | |||||
| "jpeg", | |||||
| "jpg", | |||||
| "php", | |||||
| "png", | |||||
| "svg", | |||||
| "upc" | |||||
| ], | |||||
| "time": "2015-08-13 07:59:44" | |||||
| }, | |||||
| { | |||||
| "name": "ulrichsg/getopt-php", | |||||
| "version": "2.3.0", | |||||
| "source": { | |||||
| "type": "git", | |||||
| "url": "https://github.com/ulrichsg/getopt-php.git", | |||||
| "reference": "a51554a16e206a6642bf1a0d7d1e4378ec2ba980" | |||||
| }, | |||||
| "dist": { | |||||
| "type": "zip", | |||||
| "url": "https://api.github.com/repos/ulrichsg/getopt-php/zipball/a51554a16e206a6642bf1a0d7d1e4378ec2ba980", | |||||
| "reference": "a51554a16e206a6642bf1a0d7d1e4378ec2ba980", | |||||
| "shasum": "" | |||||
| }, | |||||
| "require": { | |||||
| "php": ">=5.3.0" | |||||
| }, | |||||
| "require-dev": { | |||||
| "phpunit/phpunit": "3.7.*" | |||||
| }, | |||||
| "type": "library", | |||||
| "autoload": { | |||||
| "psr-0": { | |||||
| "Ulrichsg\\": "src" | |||||
| } | |||||
| }, | |||||
| "notification-url": "https://packagist.org/downloads/", | |||||
| "license": [ | |||||
| "MIT" | |||||
| ], | |||||
| "authors": [ | |||||
| { | |||||
| "name": "Ulrich Schmidt-Goertz", | |||||
| "email": "ulrich@schmidt-goertz.de" | |||||
| } | |||||
| ], | |||||
| "description": "Command line arguments parser for PHP 5.3", | |||||
| "homepage": "http://ulrichsg.github.io/getopt-php", | |||||
| "time": "2015-03-28 14:09:20" | |||||
| } | |||||
| ], | |||||
| "packages-dev": [], | |||||
| "aliases": [], | |||||
| "minimum-stability": "stable", | |||||
| "stability-flags": [], | |||||
| "prefer-stable": false, | |||||
| "prefer-lowest": false, | |||||
| "platform": [], | |||||
| "platform-dev": [] | |||||
| } | |||||
| @@ -0,0 +1,7 @@ | |||||
| <?php | |||||
| // autoload.php @generated by Composer | |||||
| require_once __DIR__ . '/composer' . '/autoload_real.php'; | |||||
| return ComposerAutoloaderInitf17787d2ecff231b84857fe0d96cbca5::getLoader(); | |||||
| @@ -0,0 +1,413 @@ | |||||
| <?php | |||||
| /* | |||||
| * This file is part of Composer. | |||||
| * | |||||
| * (c) Nils Adermann <naderman@naderman.de> | |||||
| * Jordi Boggiano <j.boggiano@seld.be> | |||||
| * | |||||
| * For the full copyright and license information, please view the LICENSE | |||||
| * file that was distributed with this source code. | |||||
| */ | |||||
| namespace Composer\Autoload; | |||||
| /** | |||||
| * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. | |||||
| * | |||||
| * $loader = new \Composer\Autoload\ClassLoader(); | |||||
| * | |||||
| * // register classes with namespaces | |||||
| * $loader->add('Symfony\Component', __DIR__.'/component'); | |||||
| * $loader->add('Symfony', __DIR__.'/framework'); | |||||
| * | |||||
| * // activate the autoloader | |||||
| * $loader->register(); | |||||
| * | |||||
| * // to enable searching the include path (eg. for PEAR packages) | |||||
| * $loader->setUseIncludePath(true); | |||||
| * | |||||
| * In this example, if you try to use a class in the Symfony\Component | |||||
| * namespace or one of its children (Symfony\Component\Console for instance), | |||||
| * the autoloader will first look for the class under the component/ | |||||
| * directory, and it will then fallback to the framework/ directory if not | |||||
| * found before giving up. | |||||
| * | |||||
| * This class is loosely based on the Symfony UniversalClassLoader. | |||||
| * | |||||
| * @author Fabien Potencier <fabien@symfony.com> | |||||
| * @author Jordi Boggiano <j.boggiano@seld.be> | |||||
| * @see http://www.php-fig.org/psr/psr-0/ | |||||
| * @see http://www.php-fig.org/psr/psr-4/ | |||||
| */ | |||||
| class ClassLoader | |||||
| { | |||||
| // PSR-4 | |||||
| private $prefixLengthsPsr4 = array(); | |||||
| private $prefixDirsPsr4 = array(); | |||||
| private $fallbackDirsPsr4 = array(); | |||||
| // PSR-0 | |||||
| private $prefixesPsr0 = array(); | |||||
| private $fallbackDirsPsr0 = array(); | |||||
| private $useIncludePath = false; | |||||
| private $classMap = array(); | |||||
| private $classMapAuthoritative = false; | |||||
| public function getPrefixes() | |||||
| { | |||||
| if (!empty($this->prefixesPsr0)) { | |||||
| return call_user_func_array('array_merge', $this->prefixesPsr0); | |||||
| } | |||||
| return array(); | |||||
| } | |||||
| public function getPrefixesPsr4() | |||||
| { | |||||
| return $this->prefixDirsPsr4; | |||||
| } | |||||
| public function getFallbackDirs() | |||||
| { | |||||
| return $this->fallbackDirsPsr0; | |||||
| } | |||||
| public function getFallbackDirsPsr4() | |||||
| { | |||||
| return $this->fallbackDirsPsr4; | |||||
| } | |||||
| public function getClassMap() | |||||
| { | |||||
| return $this->classMap; | |||||
| } | |||||
| /** | |||||
| * @param array $classMap Class to filename map | |||||
| */ | |||||
| public function addClassMap(array $classMap) | |||||
| { | |||||
| if ($this->classMap) { | |||||
| $this->classMap = array_merge($this->classMap, $classMap); | |||||
| } else { | |||||
| $this->classMap = $classMap; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Registers a set of PSR-0 directories for a given prefix, either | |||||
| * appending or prepending to the ones previously set for this prefix. | |||||
| * | |||||
| * @param string $prefix The prefix | |||||
| * @param array|string $paths The PSR-0 root directories | |||||
| * @param bool $prepend Whether to prepend the directories | |||||
| */ | |||||
| public function add($prefix, $paths, $prepend = false) | |||||
| { | |||||
| if (!$prefix) { | |||||
| if ($prepend) { | |||||
| $this->fallbackDirsPsr0 = array_merge( | |||||
| (array) $paths, | |||||
| $this->fallbackDirsPsr0 | |||||
| ); | |||||
| } else { | |||||
| $this->fallbackDirsPsr0 = array_merge( | |||||
| $this->fallbackDirsPsr0, | |||||
| (array) $paths | |||||
| ); | |||||
| } | |||||
| return; | |||||
| } | |||||
| $first = $prefix[0]; | |||||
| if (!isset($this->prefixesPsr0[$first][$prefix])) { | |||||
| $this->prefixesPsr0[$first][$prefix] = (array) $paths; | |||||
| return; | |||||
| } | |||||
| if ($prepend) { | |||||
| $this->prefixesPsr0[$first][$prefix] = array_merge( | |||||
| (array) $paths, | |||||
| $this->prefixesPsr0[$first][$prefix] | |||||
| ); | |||||
| } else { | |||||
| $this->prefixesPsr0[$first][$prefix] = array_merge( | |||||
| $this->prefixesPsr0[$first][$prefix], | |||||
| (array) $paths | |||||
| ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Registers a set of PSR-4 directories for a given namespace, either | |||||
| * appending or prepending to the ones previously set for this namespace. | |||||
| * | |||||
| * @param string $prefix The prefix/namespace, with trailing '\\' | |||||
| * @param array|string $paths The PSR-4 base directories | |||||
| * @param bool $prepend Whether to prepend the directories | |||||
| * | |||||
| * @throws \InvalidArgumentException | |||||
| */ | |||||
| public function addPsr4($prefix, $paths, $prepend = false) | |||||
| { | |||||
| if (!$prefix) { | |||||
| // Register directories for the root namespace. | |||||
| if ($prepend) { | |||||
| $this->fallbackDirsPsr4 = array_merge( | |||||
| (array) $paths, | |||||
| $this->fallbackDirsPsr4 | |||||
| ); | |||||
| } else { | |||||
| $this->fallbackDirsPsr4 = array_merge( | |||||
| $this->fallbackDirsPsr4, | |||||
| (array) $paths | |||||
| ); | |||||
| } | |||||
| } elseif (!isset($this->prefixDirsPsr4[$prefix])) { | |||||
| // Register directories for a new namespace. | |||||
| $length = strlen($prefix); | |||||
| if ('\\' !== $prefix[$length - 1]) { | |||||
| throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); | |||||
| } | |||||
| $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; | |||||
| $this->prefixDirsPsr4[$prefix] = (array) $paths; | |||||
| } elseif ($prepend) { | |||||
| // Prepend directories for an already registered namespace. | |||||
| $this->prefixDirsPsr4[$prefix] = array_merge( | |||||
| (array) $paths, | |||||
| $this->prefixDirsPsr4[$prefix] | |||||
| ); | |||||
| } else { | |||||
| // Append directories for an already registered namespace. | |||||
| $this->prefixDirsPsr4[$prefix] = array_merge( | |||||
| $this->prefixDirsPsr4[$prefix], | |||||
| (array) $paths | |||||
| ); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Registers a set of PSR-0 directories for a given prefix, | |||||
| * replacing any others previously set for this prefix. | |||||
| * | |||||
| * @param string $prefix The prefix | |||||
| * @param array|string $paths The PSR-0 base directories | |||||
| */ | |||||
| public function set($prefix, $paths) | |||||
| { | |||||
| if (!$prefix) { | |||||
| $this->fallbackDirsPsr0 = (array) $paths; | |||||
| } else { | |||||
| $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Registers a set of PSR-4 directories for a given namespace, | |||||
| * replacing any others previously set for this namespace. | |||||
| * | |||||
| * @param string $prefix The prefix/namespace, with trailing '\\' | |||||
| * @param array|string $paths The PSR-4 base directories | |||||
| * | |||||
| * @throws \InvalidArgumentException | |||||
| */ | |||||
| public function setPsr4($prefix, $paths) | |||||
| { | |||||
| if (!$prefix) { | |||||
| $this->fallbackDirsPsr4 = (array) $paths; | |||||
| } else { | |||||
| $length = strlen($prefix); | |||||
| if ('\\' !== $prefix[$length - 1]) { | |||||
| throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); | |||||
| } | |||||
| $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; | |||||
| $this->prefixDirsPsr4[$prefix] = (array) $paths; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Turns on searching the include path for class files. | |||||
| * | |||||
| * @param bool $useIncludePath | |||||
| */ | |||||
| public function setUseIncludePath($useIncludePath) | |||||
| { | |||||
| $this->useIncludePath = $useIncludePath; | |||||
| } | |||||
| /** | |||||
| * Can be used to check if the autoloader uses the include path to check | |||||
| * for classes. | |||||
| * | |||||
| * @return bool | |||||
| */ | |||||
| public function getUseIncludePath() | |||||
| { | |||||
| return $this->useIncludePath; | |||||
| } | |||||
| /** | |||||
| * Turns off searching the prefix and fallback directories for classes | |||||
| * that have not been registered with the class map. | |||||
| * | |||||
| * @param bool $classMapAuthoritative | |||||
| */ | |||||
| public function setClassMapAuthoritative($classMapAuthoritative) | |||||
| { | |||||
| $this->classMapAuthoritative = $classMapAuthoritative; | |||||
| } | |||||
| /** | |||||
| * Should class lookup fail if not found in the current class map? | |||||
| * | |||||
| * @return bool | |||||
| */ | |||||
| public function isClassMapAuthoritative() | |||||
| { | |||||
| return $this->classMapAuthoritative; | |||||
| } | |||||
| /** | |||||
| * Registers this instance as an autoloader. | |||||
| * | |||||
| * @param bool $prepend Whether to prepend the autoloader or not | |||||
| */ | |||||
| public function register($prepend = false) | |||||
| { | |||||
| spl_autoload_register(array($this, 'loadClass'), true, $prepend); | |||||
| } | |||||
| /** | |||||
| * Unregisters this instance as an autoloader. | |||||
| */ | |||||
| public function unregister() | |||||
| { | |||||
| spl_autoload_unregister(array($this, 'loadClass')); | |||||
| } | |||||
| /** | |||||
| * Loads the given class or interface. | |||||
| * | |||||
| * @param string $class The name of the class | |||||
| * @return bool|null True if loaded, null otherwise | |||||
| */ | |||||
| public function loadClass($class) | |||||
| { | |||||
| if ($file = $this->findFile($class)) { | |||||
| includeFile($file); | |||||
| return true; | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Finds the path to the file where the class is defined. | |||||
| * | |||||
| * @param string $class The name of the class | |||||
| * | |||||
| * @return string|false The path if found, false otherwise | |||||
| */ | |||||
| public function findFile($class) | |||||
| { | |||||
| // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 | |||||
| if ('\\' == $class[0]) { | |||||
| $class = substr($class, 1); | |||||
| } | |||||
| // class map lookup | |||||
| if (isset($this->classMap[$class])) { | |||||
| return $this->classMap[$class]; | |||||
| } | |||||
| if ($this->classMapAuthoritative) { | |||||
| return false; | |||||
| } | |||||
| $file = $this->findFileWithExtension($class, '.php'); | |||||
| // Search for Hack files if we are running on HHVM | |||||
| if ($file === null && defined('HHVM_VERSION')) { | |||||
| $file = $this->findFileWithExtension($class, '.hh'); | |||||
| } | |||||
| if ($file === null) { | |||||
| // Remember that this class does not exist. | |||||
| return $this->classMap[$class] = false; | |||||
| } | |||||
| return $file; | |||||
| } | |||||
| private function findFileWithExtension($class, $ext) | |||||
| { | |||||
| // PSR-4 lookup | |||||
| $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; | |||||
| $first = $class[0]; | |||||
| if (isset($this->prefixLengthsPsr4[$first])) { | |||||
| foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { | |||||
| if (0 === strpos($class, $prefix)) { | |||||
| foreach ($this->prefixDirsPsr4[$prefix] as $dir) { | |||||
| if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { | |||||
| return $file; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // PSR-4 fallback dirs | |||||
| foreach ($this->fallbackDirsPsr4 as $dir) { | |||||
| if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { | |||||
| return $file; | |||||
| } | |||||
| } | |||||
| // PSR-0 lookup | |||||
| if (false !== $pos = strrpos($class, '\\')) { | |||||
| // namespaced class name | |||||
| $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) | |||||
| . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); | |||||
| } else { | |||||
| // PEAR-like class name | |||||
| $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; | |||||
| } | |||||
| if (isset($this->prefixesPsr0[$first])) { | |||||
| foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { | |||||
| if (0 === strpos($class, $prefix)) { | |||||
| foreach ($dirs as $dir) { | |||||
| if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { | |||||
| return $file; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| // PSR-0 fallback dirs | |||||
| foreach ($this->fallbackDirsPsr0 as $dir) { | |||||
| if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { | |||||
| return $file; | |||||
| } | |||||
| } | |||||
| // PSR-0 include paths. | |||||
| if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { | |||||
| return $file; | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Scope isolated include. | |||||
| * | |||||
| * Prevents access to $this/self from included files. | |||||
| */ | |||||
| function includeFile($file) | |||||
| { | |||||
| include $file; | |||||
| } | |||||
| @@ -0,0 +1,21 @@ | |||||
| Copyright (c) 2016 Nils Adermann, Jordi Boggiano | |||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
| of this software and associated documentation files (the "Software"), to deal | |||||
| in the Software without restriction, including without limitation the rights | |||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
| copies of the Software, and to permit persons to whom the Software is furnished | |||||
| to do so, subject to the following conditions: | |||||
| The above copyright notice and this permission notice shall be included in all | |||||
| copies or substantial portions of the Software. | |||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||||
| THE SOFTWARE. | |||||
| @@ -0,0 +1,9 @@ | |||||
| <?php | |||||
| // autoload_classmap.php @generated by Composer | |||||
| $vendorDir = dirname(dirname(__FILE__)); | |||||
| $baseDir = dirname($vendorDir); | |||||
| return array( | |||||
| ); | |||||
| @@ -0,0 +1,10 @@ | |||||
| <?php | |||||
| // autoload_namespaces.php @generated by Composer | |||||
| $vendorDir = dirname(dirname(__FILE__)); | |||||
| $baseDir = dirname($vendorDir); | |||||
| return array( | |||||
| 'Ulrichsg\\' => array($vendorDir . '/ulrichsg/getopt-php/src'), | |||||
| ); | |||||
| @@ -0,0 +1,10 @@ | |||||
| <?php | |||||
| // autoload_psr4.php @generated by Composer | |||||
| $vendorDir = dirname(dirname(__FILE__)); | |||||
| $baseDir = dirname($vendorDir); | |||||
| return array( | |||||
| 'Picqer\\Barcode\\' => array($vendorDir . '/picqer/php-barcode-generator/src'), | |||||
| ); | |||||
| @@ -0,0 +1,45 @@ | |||||
| <?php | |||||
| // autoload_real.php @generated by Composer | |||||
| class ComposerAutoloaderInitf17787d2ecff231b84857fe0d96cbca5 | |||||
| { | |||||
| private static $loader; | |||||
| public static function loadClassLoader($class) | |||||
| { | |||||
| if ('Composer\Autoload\ClassLoader' === $class) { | |||||
| require __DIR__ . '/ClassLoader.php'; | |||||
| } | |||||
| } | |||||
| public static function getLoader() | |||||
| { | |||||
| if (null !== self::$loader) { | |||||
| return self::$loader; | |||||
| } | |||||
| spl_autoload_register(array('ComposerAutoloaderInitf17787d2ecff231b84857fe0d96cbca5', 'loadClassLoader'), true, true); | |||||
| self::$loader = $loader = new \Composer\Autoload\ClassLoader(); | |||||
| spl_autoload_unregister(array('ComposerAutoloaderInitf17787d2ecff231b84857fe0d96cbca5', 'loadClassLoader')); | |||||
| $map = require __DIR__ . '/autoload_namespaces.php'; | |||||
| foreach ($map as $namespace => $path) { | |||||
| $loader->set($namespace, $path); | |||||
| } | |||||
| $map = require __DIR__ . '/autoload_psr4.php'; | |||||
| foreach ($map as $namespace => $path) { | |||||
| $loader->setPsr4($namespace, $path); | |||||
| } | |||||
| $classMap = require __DIR__ . '/autoload_classmap.php'; | |||||
| if ($classMap) { | |||||
| $loader->addClassMap($classMap); | |||||
| } | |||||
| $loader->register(true); | |||||
| return $loader; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,107 @@ | |||||
| [ | |||||
| { | |||||
| "name": "picqer/php-barcode-generator", | |||||
| "version": "v0.1", | |||||
| "version_normalized": "0.1.0.0", | |||||
| "source": { | |||||
| "type": "git", | |||||
| "url": "https://github.com/picqer/php-barcode-generator.git", | |||||
| "reference": "bd486cfb311989a506c62827fdee463b8a698002" | |||||
| }, | |||||
| "dist": { | |||||
| "type": "zip", | |||||
| "url": "https://api.github.com/repos/picqer/php-barcode-generator/zipball/bd486cfb311989a506c62827fdee463b8a698002", | |||||
| "reference": "bd486cfb311989a506c62827fdee463b8a698002", | |||||
| "shasum": "" | |||||
| }, | |||||
| "require": { | |||||
| "php": ">=5.4.0" | |||||
| }, | |||||
| "time": "2015-08-13 07:59:44", | |||||
| "type": "library", | |||||
| "installation-source": "dist", | |||||
| "autoload": { | |||||
| "psr-4": { | |||||
| "Picqer\\Barcode\\": "src" | |||||
| } | |||||
| }, | |||||
| "notification-url": "https://packagist.org/downloads/", | |||||
| "license": [ | |||||
| "MIT" | |||||
| ], | |||||
| "authors": [ | |||||
| { | |||||
| "name": "Casper Bakker", | |||||
| "email": "info@picqer.com" | |||||
| } | |||||
| ], | |||||
| "description": "An easy to use, non-bloated, barcode generator in PHP. Creates SVG, PNG, JPG and HTML images from the most used 1D barcode standards.", | |||||
| "homepage": "http://github.com/picqer/exact-php-client", | |||||
| "keywords": [ | |||||
| "CODABAR", | |||||
| "Code11", | |||||
| "Code93", | |||||
| "EAN13", | |||||
| "KIX", | |||||
| "KIXCODE", | |||||
| "MSI", | |||||
| "POSTNET", | |||||
| "Pharma", | |||||
| "Standard 2 of 5", | |||||
| "barcode", | |||||
| "barcode generator", | |||||
| "code128", | |||||
| "code39", | |||||
| "ean", | |||||
| "html", | |||||
| "jpeg", | |||||
| "jpg", | |||||
| "php", | |||||
| "png", | |||||
| "svg", | |||||
| "upc" | |||||
| ] | |||||
| }, | |||||
| { | |||||
| "name": "ulrichsg/getopt-php", | |||||
| "version": "2.3.0", | |||||
| "version_normalized": "2.3.0.0", | |||||
| "source": { | |||||
| "type": "git", | |||||
| "url": "https://github.com/ulrichsg/getopt-php.git", | |||||
| "reference": "a51554a16e206a6642bf1a0d7d1e4378ec2ba980" | |||||
| }, | |||||
| "dist": { | |||||
| "type": "zip", | |||||
| "url": "https://api.github.com/repos/ulrichsg/getopt-php/zipball/a51554a16e206a6642bf1a0d7d1e4378ec2ba980", | |||||
| "reference": "a51554a16e206a6642bf1a0d7d1e4378ec2ba980", | |||||
| "shasum": "" | |||||
| }, | |||||
| "require": { | |||||
| "php": ">=5.3.0" | |||||
| }, | |||||
| "require-dev": { | |||||
| "phpunit/phpunit": "3.7.*" | |||||
| }, | |||||
| "time": "2015-03-28 14:09:20", | |||||
| "type": "library", | |||||
| "installation-source": "dist", | |||||
| "autoload": { | |||||
| "psr-0": { | |||||
| "Ulrichsg\\": "src" | |||||
| } | |||||
| }, | |||||
| "notification-url": "https://packagist.org/downloads/", | |||||
| "license": [ | |||||
| "MIT" | |||||
| ], | |||||
| "authors": [ | |||||
| { | |||||
| "name": "Ulrich Schmidt-Goertz", | |||||
| "email": "ulrich@schmidt-goertz.de" | |||||
| } | |||||
| ], | |||||
| "description": "Command line arguments parser for PHP 5.3", | |||||
| "homepage": "http://ulrichsg.github.io/getopt-php" | |||||
| } | |||||
| ] | |||||
| @@ -0,0 +1,2 @@ | |||||
| .idea | |||||
| .DS_Store | |||||
| @@ -0,0 +1,76 @@ | |||||
| # PHP Barcode Generator | |||||
| This is an easy to use, non-bloated, framework independent, barcode generator in PHP. | |||||
| It creates SVG, PNG, JPG and HTML images, from the most used 1D barcode standards. | |||||
| *The codebase is largely from the TCPDF barcode generator. It is still a bit of a mess, bit I will clean it in the future. I do not expect the interface of this class will change during the clean ups.* | |||||
| ## Installation | |||||
| Install through [composer](https://getcomposer.org/doc/00-intro.md): | |||||
| ``` | |||||
| composer require picqer/php-barcode-generator | |||||
| ``` | |||||
| ## Usage | |||||
| Initiate the barcode generator for the output you want, then call the ->getBarcode() routine as many times as you want. | |||||
| ```php | |||||
| $generator = new Picqer\Barcode\BarcodeGeneratorHTML(); | |||||
| echo $generator->getBarcode('081231723897', $generator::TYPE_CODE_128); | |||||
| ``` | |||||
| The ->getBarcode() routine accepts the following: | |||||
| - $code Data for the barcode | |||||
| - $type Type of barcode, use the constants defined in the class | |||||
| - $widthFactor Width is based on the length of the data, with this factor you can make the barcode bars wider then default | |||||
| - $totalHeight The total height of the barcode | |||||
| - $color Hex code of the foreground color | |||||
| ## Image types | |||||
| ```php | |||||
| $generatorSVG = new Picqer\Barcode\BarcodeGeneratorSVG(); | |||||
| $generatorPNG = new Picqer\Barcode\BarcodeGeneratorPNG(); | |||||
| $generatorJPG = new Picqer\Barcode\BarcodeGeneratorJPG(); | |||||
| $generatorHTML = new Picqer\Barcode\BarcodeGeneratorHTML(); | |||||
| ``` | |||||
| ## Accepted types | |||||
| - TYPE_CODE_39 | |||||
| - TYPE_CODE_39_CHECKSUM | |||||
| - TYPE_CODE_39E | |||||
| - TYPE_CODE_39E_CHECKSUM | |||||
| - TYPE_CODE_93 | |||||
| - TYPE_STANDARD_2_5 | |||||
| - TYPE_STANDARD_2_5_CHECKSUM | |||||
| - TYPE_INTERLEAVED_2_5 | |||||
| - TYPE_INTERLEAVED_2_5_CHECKSUM | |||||
| - TYPE_CODE_128 | |||||
| - TYPE_CODE_128_A | |||||
| - TYPE_CODE_128_B | |||||
| - TYPE_CODE_128_C | |||||
| - TYPE_EAN_2 | |||||
| - TYPE_EAN_5 | |||||
| - TYPE_EAN_8 | |||||
| - TYPE_EAN_13 | |||||
| - TYPE_UPC_A | |||||
| - TYPE_UPC_E | |||||
| - TYPE_MSI | |||||
| - TYPE_MSI_CHECKSUM | |||||
| - TYPE_POSTNET | |||||
| - TYPE_PLANET | |||||
| - TYPE_RMS4CC | |||||
| - TYPE_KIX | |||||
| - TYPE_IMB | |||||
| - TYPE_CODABAR | |||||
| - TYPE_CODE_11 | |||||
| - TYPE_PHARMA_CODE | |||||
| - TYPE_PHARMA_CODE_TWO_TRACKS | |||||
| ## Examples | |||||
| Embedded PNG image in HTML: | |||||
| ```php | |||||
| $generator = new Picqer\Barcode\BarcodeGeneratorPNG(); | |||||
| echo '<img src="data:image/png;base64,' . base64_encode($generator->getBarcode('081231723897', $generator::TYPE_CODE_128)) . '">'; | |||||
| ``` | |||||
| @@ -0,0 +1,22 @@ | |||||
| { | |||||
| "name": "picqer/php-barcode-generator", | |||||
| "type": "library", | |||||
| "description": "An easy to use, non-bloated, barcode generator in PHP. Creates SVG, PNG, JPG and HTML images from the most used 1D barcode standards.", | |||||
| "keywords": [ "php", "barcode", "barcode generator", "EAN", "EAN13", "UPC", "Code39", "Code128", "Code93", "Standard 2 of 5", "MSI", "POSTNET", "KIX", "KIXCODE", "CODABAR", "PHARMA", "Code11", "SVG", "PNG", "HTML", "JPG", "JPEG" ], | |||||
| "homepage": "http://github.com/picqer/exact-php-client", | |||||
| "license": "MIT", | |||||
| "authors": [ | |||||
| { | |||||
| "name": "Casper Bakker", | |||||
| "email": "info@picqer.com" | |||||
| } | |||||
| ], | |||||
| "require": { | |||||
| "php": ">=5.4.0" | |||||
| }, | |||||
| "autoload": { | |||||
| "psr-4": { | |||||
| "Picqer\\Barcode\\": "src" | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,14 @@ | |||||
| <?php | |||||
| include('src/BarcodeGenerator.php'); | |||||
| include('src/BarcodeGeneratorPNG.php'); | |||||
| include('src/BarcodeGeneratorSVG.php'); | |||||
| include('src/BarcodeGeneratorHTML.php'); | |||||
| $generatorPNG = new Picqer\Barcode\BarcodeGeneratorPNG(); | |||||
| $generatorSVG = new Picqer\Barcode\BarcodeGeneratorSVG(); | |||||
| $generatorHTML = new Picqer\Barcode\BarcodeGeneratorHTML(); | |||||
| echo $generatorHTML->getBarcode('081231723897', $generatorPNG::TYPE_CODE_128); | |||||
| echo $generatorSVG->getBarcode('081231723897', $generatorPNG::TYPE_EAN_13); | |||||
| echo '<img src="data:image/png;base64,' . base64_encode($generatorPNG->getBarcode('081231723897', $generatorPNG::TYPE_CODE_128)) . '">'; | |||||
| @@ -0,0 +1,44 @@ | |||||
| <?php | |||||
| namespace Picqer\Barcode; | |||||
| class BarcodeGeneratorHTML extends BarcodeGenerator | |||||
| { | |||||
| /** | |||||
| * Return an HTML representation of barcode. | |||||
| * | |||||
| * @param string $code code to print | |||||
| * @param string $type type of barcode | |||||
| * @param int $widthFactor Width of a single bar element in pixels. | |||||
| * @param int $totalHeight Height of a single bar element in pixels. | |||||
| * @param int $color Foreground color for bar elements (background is transparent). | |||||
| * @return string HTML code. | |||||
| * @public | |||||
| */ | |||||
| public function getBarcode($code, $type, $widthFactor = 2, $totalHeight = 30, $color = 'black') | |||||
| { | |||||
| $barcodeData = $this->getBarcodeData($code, $type); | |||||
| $html = '<div style="font-size:0;position:relative;width:' . ($barcodeData['maxWidth'] * $widthFactor) . 'px;height:' . ($totalHeight) . 'px;">' . "\n"; | |||||
| $positionHorizontal = 0; | |||||
| foreach ($barcodeData['bars'] as $bar) { | |||||
| $barWidth = round(($bar['width'] * $widthFactor), 3); | |||||
| $barHeight = round(($bar['height'] * $totalHeight / $barcodeData['maxHeight']), 3); | |||||
| if ($bar['drawBar']) { | |||||
| $positionVertical = round(($bar['positionVertical'] * $totalHeight / $barcodeData['maxHeight']), 3); | |||||
| // draw a vertical bar | |||||
| $html .= '<div style="background-color:' . $color . ';width:' . $barWidth . 'px;height:' . $barHeight . 'px;position:absolute;left:' . $positionHorizontal . 'px;top:' . $positionVertical . 'px;"> </div>' . "\n"; | |||||
| } | |||||
| $positionHorizontal += $barWidth; | |||||
| } | |||||
| $html .= '</div>' . "\n"; | |||||
| return $html; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,74 @@ | |||||
| <?php | |||||
| namespace Picqer\Barcode; | |||||
| class BarcodeGeneratorJPG extends BarcodeGenerator | |||||
| { | |||||
| /** | |||||
| * Return a JPG image representation of barcode (requires GD or Imagick library). | |||||
| * | |||||
| * @param string $code code to print | |||||
| * @param string $type type of barcode: | |||||
| * @param int $widthFactor Width of a single bar element in pixels. | |||||
| * @param int $totalHeight Height of a single bar element in pixels. | |||||
| * @param array $color RGB (0-255) foreground color for bar elements (background is transparent). | |||||
| * @return string image data or false in case of error. | |||||
| * @public | |||||
| */ | |||||
| public function getBarcode($code, $type, $widthFactor = 2, $totalHeight = 30, $color = array(0, 0, 0)) | |||||
| { | |||||
| $barcodeData = $this->getBarcodeData($code, $type); | |||||
| // calculate image size | |||||
| $width = ($barcodeData['maxWidth'] * $widthFactor); | |||||
| $height = $totalHeight; | |||||
| if (function_exists('imagecreate')) { | |||||
| // GD library | |||||
| $imagick = false; | |||||
| $jpg = imagecreate($width, $height); | |||||
| $colorBackground = imagecolorallocate($jpg, 255, 255, 255); | |||||
| imagecolortransparent($jpg, $colorBackground); | |||||
| $colorForeground = imagecolorallocate($jpg, $color[0], $color[1], $color[2]); | |||||
| } elseif (extension_loaded('imagick')) { | |||||
| $imagick = true; | |||||
| $colorForeground = new \imagickpixel('rgb(' . $color[0] . ',' . $color[1] . ',' . $color[2] . ')'); | |||||
| $jpg = new \Imagick(); | |||||
| $jpg->newImage($width, $height, 'none', 'jpg'); | |||||
| $imageMagickObject = new \imagickdraw(); | |||||
| $imageMagickObject->setfillcolor($colorForeground); | |||||
| } else { | |||||
| return false; | |||||
| } | |||||
| // print bars | |||||
| $positionHorizontal = 0; | |||||
| foreach ($barcodeData['bars'] as $bar) { | |||||
| $bw = round(($bar['width'] * $widthFactor), 3); | |||||
| $bh = round(($bar['height'] * $totalHeight / $barcodeData['maxHeight']), 3); | |||||
| if ($bar['drawBar']) { | |||||
| $y = round(($bar['positionVertical'] * $totalHeight / $barcodeData['maxHeight']), 3); | |||||
| // draw a vertical bar | |||||
| if ($imagick) { | |||||
| $imageMagickObject->rectangle($positionHorizontal, $y, ($positionHorizontal + $bw), ($y + $bh)); | |||||
| } else { | |||||
| imagefilledrectangle($jpg, $positionHorizontal, $y, ($positionHorizontal + $bw) - 1, ($y + $bh), | |||||
| $colorForeground); | |||||
| } | |||||
| } | |||||
| $positionHorizontal += $bw; | |||||
| } | |||||
| ob_start(); | |||||
| if ($imagick) { | |||||
| $jpg->drawimage($imageMagickObject); | |||||
| echo $jpg; | |||||
| } else { | |||||
| imagejpeg($jpg); | |||||
| imagedestroy($jpg); | |||||
| } | |||||
| $image = ob_get_clean(); | |||||
| return $image; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,74 @@ | |||||
| <?php | |||||
| namespace Picqer\Barcode; | |||||
| class BarcodeGeneratorPNG extends BarcodeGenerator | |||||
| { | |||||
| /** | |||||
| * Return a PNG image representation of barcode (requires GD or Imagick library). | |||||
| * | |||||
| * @param string $code code to print | |||||
| * @param string $type type of barcode: | |||||
| * @param int $widthFactor Width of a single bar element in pixels. | |||||
| * @param int $totalHeight Height of a single bar element in pixels. | |||||
| * @param array $color RGB (0-255) foreground color for bar elements (background is transparent). | |||||
| * @return string image data or false in case of error. | |||||
| * @public | |||||
| */ | |||||
| public function getBarcode($code, $type, $widthFactor = 2, $totalHeight = 30, $color = array(0, 0, 0)) | |||||
| { | |||||
| $barcodeData = $this->getBarcodeData($code, $type); | |||||
| // calculate image size | |||||
| $width = ($barcodeData['maxWidth'] * $widthFactor); | |||||
| $height = $totalHeight; | |||||
| if (function_exists('imagecreate')) { | |||||
| // GD library | |||||
| $imagick = false; | |||||
| $png = imagecreate($width, $height); | |||||
| $colorBackground = imagecolorallocate($png, 255, 255, 255); | |||||
| imagecolortransparent($png, $colorBackground); | |||||
| $colorForeground = imagecolorallocate($png, $color[0], $color[1], $color[2]); | |||||
| } elseif (extension_loaded('imagick')) { | |||||
| $imagick = true; | |||||
| $colorForeground = new \imagickpixel('rgb(' . $color[0] . ',' . $color[1] . ',' . $color[2] . ')'); | |||||
| $png = new \Imagick(); | |||||
| $png->newImage($width, $height, 'none', 'png'); | |||||
| $imageMagickObject = new \imagickdraw(); | |||||
| $imageMagickObject->setfillcolor($colorForeground); | |||||
| } else { | |||||
| return false; | |||||
| } | |||||
| // print bars | |||||
| $positionHorizontal = 0; | |||||
| foreach ($barcodeData['bars'] as $bar) { | |||||
| $bw = round(($bar['width'] * $widthFactor), 3); | |||||
| $bh = round(($bar['height'] * $totalHeight / $barcodeData['maxHeight']), 3); | |||||
| if ($bar['drawBar']) { | |||||
| $y = round(($bar['positionVertical'] * $totalHeight / $barcodeData['maxHeight']), 3); | |||||
| // draw a vertical bar | |||||
| if ($imagick) { | |||||
| $imageMagickObject->rectangle($positionHorizontal, $y, ($positionHorizontal + $bw), ($y + $bh)); | |||||
| } else { | |||||
| imagefilledrectangle($png, $positionHorizontal, $y, ($positionHorizontal + $bw) - 1, ($y + $bh), | |||||
| $colorForeground); | |||||
| } | |||||
| } | |||||
| $positionHorizontal += $bw; | |||||
| } | |||||
| ob_start(); | |||||
| if ($imagick) { | |||||
| $png->drawimage($imageMagickObject); | |||||
| echo $png; | |||||
| } else { | |||||
| imagepng($png); | |||||
| imagedestroy($png); | |||||
| } | |||||
| $image = ob_get_clean(); | |||||
| return $image; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,49 @@ | |||||
| <?php | |||||
| namespace Picqer\Barcode; | |||||
| class BarcodeGeneratorSVG extends BarcodeGenerator | |||||
| { | |||||
| /** | |||||
| * Return a SVG string representation of barcode. | |||||
| * | |||||
| * @param $code (string) code to print | |||||
| * @param $type (const) type of barcode | |||||
| * @param $widthFactor (int) Minimum width of a single bar in user units. | |||||
| * @param $totalHeight (int) Height of barcode in user units. | |||||
| * @param $color (string) Foreground color (in SVG format) for bar elements (background is transparent). | |||||
| * @return string SVG code. | |||||
| * @public | |||||
| */ | |||||
| public function getBarcode($code, $type, $widthFactor = 2, $totalHeight = 30, $color = 'black') | |||||
| { | |||||
| $barcodeData = $this->getBarcodeData($code, $type); | |||||
| // replace table for special characters | |||||
| $repstr = array("\0" => '', '&' => '&', '<' => '<', '>' => '>'); | |||||
| $svg = '<?xml version="1.0" standalone="no" ?>' . "\n"; | |||||
| $svg .= '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' . "\n"; | |||||
| $svg .= '<svg width="' . round(($barcodeData['maxWidth'] * $widthFactor), | |||||
| 3) . '" height="' . $totalHeight . '" version="1.1" xmlns="http://www.w3.org/2000/svg">' . "\n"; | |||||
| $svg .= "\t" . '<desc>' . strtr($barcodeData['code'], $repstr) . '</desc>' . "\n"; | |||||
| $svg .= "\t" . '<g id="bars" fill="' . $color . '" stroke="none">' . "\n"; | |||||
| // print bars | |||||
| $positionHorizontal = 0; | |||||
| foreach ($barcodeData['bars'] as $bar) { | |||||
| $barWidth = round(($bar['width'] * $widthFactor), 3); | |||||
| $barHeight = round(($bar['height'] * $totalHeight / $barcodeData['maxHeight']), 3); | |||||
| if ($bar['drawBar']) { | |||||
| $positionVertical = round(($bar['positionVertical'] * $totalHeight / $barcodeData['maxHeight']), 3); | |||||
| // draw a vertical bar | |||||
| $svg .= "\t\t" . '<rect x="' . $positionHorizontal . '" y="' . $positionVertical . '" width="' . $barWidth . '" height="' . $barHeight . '" />' . "\n"; | |||||
| } | |||||
| $positionHorizontal += $barWidth; | |||||
| } | |||||
| $svg .= "\t" . '</g>' . "\n"; | |||||
| $svg .= '</svg>' . "\n"; | |||||
| return $svg; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,6 @@ | |||||
| bin | |||||
| build | |||||
| composer.lock | |||||
| vendor | |||||
| nbproject | |||||
| _site | |||||
| @@ -0,0 +1,10 @@ | |||||
| language: php | |||||
| php: | |||||
| - 5.6 | |||||
| - 5.5 | |||||
| - 5.4 | |||||
| - 5.3 | |||||
| - hhvm | |||||
| before_script: | |||||
| - composer install | |||||
| @@ -0,0 +1,77 @@ | |||||
| ## 2.3.0 (2015-03-28) | |||||
| Features: | |||||
| * Optional argument descriptions (courtesy of @sabl0r) | |||||
| Bugfixes: | |||||
| * Passing a single hyphen as an option value works now (courtesy of @tistre) | |||||
| ## 2.2.0 (2014-09-13) | |||||
| Features: | |||||
| * Added method to customize the help message (courtesy of @mfn) | |||||
| * Option now has a static create method for call chaining in PHP 5.3 (courtesy of @kamermans) | |||||
| ## 2.1.0 (2014-02-28) | |||||
| Features: | |||||
| * Added setters for default values and validation to Option | |||||
| ## 2.0.0 (2014-01-30) | |||||
| Features: | |||||
| * Argument validation (courtesy of @jochenvdv) | |||||
| ## 2.0.0-RC.1 (2014-01-17) | |||||
| Changes: | |||||
| * Namespace is now Ulrichsg\Getopt | |||||
| * Public API has been cleaned up, please refer to the documentation | |||||
| ## 1.4.1 (2013-12-13) | |||||
| Bugfixes: | |||||
| * Long options are required to be longer than 1 character | |||||
| * Passing duplicate option names to the constructor is forbidden by default | |||||
| ## 1.4.0 (2013-12-13) | |||||
| Features: | |||||
| * Options can be numeric (courtesy of @patinthehat) | |||||
| * Additional convenience methods for working with operands (ditto) | |||||
| ## 1.3.0 (2013-12-07) | |||||
| Features: | |||||
| * Default values for options | |||||
| * ArrayAccess, Countable and Traversable support | |||||
| * Can set program name to enhance help message (courtesy of @misterion) | |||||
| ## 1.2.0 (2013-11-14) | |||||
| Features: | |||||
| * Allow passing incomplete option arrays | |||||
| ## 1.1.0 (2013-06-19) | |||||
| Features: | |||||
| * Added help text printing functionality | |||||
| Bugfixes: | |||||
| * Fixed passing a mandatory argument to the last in a sequence of collapsed short options | |||||
| ## 1.0.1 (2012-05-20) | |||||
| Bugfixes: | |||||
| * Fixed bug where '0' could not be passed as an option value | |||||
| @@ -0,0 +1,17 @@ | |||||
| Copyright (c) 2011-2014 Ulrich Schmidt-Goertz <ulrich at schmidt-goertz.de> | |||||
| Permission is hereby granted, free of charge, to any person obtaining a copy of this software | |||||
| and associated documentation files (the "Software"), to deal in the Software without restriction, | |||||
| including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||||
| and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, | |||||
| subject to the following conditions: | |||||
| The above copyright notice and this permission notice shall be included in all copies or substantial | |||||
| portions of the Software. | |||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | |||||
| INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | |||||
| PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |||||
| HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |||||
| TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||||
| DEALINGS IN THE SOFTWARE. | |||||
| @@ -0,0 +1,35 @@ | |||||
| # vim: tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab | |||||
| help: | |||||
| @echo "Usual targets:" | |||||
| @echo " test - run test suites" | |||||
| @echo "" | |||||
| @echo "Other targets:" | |||||
| @echo " install-composer - install composer" | |||||
| @echo " install-dependencies - install/update all vendor libraries using composer" | |||||
| @echo " install-dev-dependencies - install/update all vendor libraries necessary for development" | |||||
| @echo "" | |||||
| @exit 0 | |||||
| test: | |||||
| @vendor/bin/phpunit | |||||
| install-composer: | |||||
| @if [ ! -d ./bin ]; then mkdir bin; fi | |||||
| @if [ ! -f ./bin/composer.phar ]; then curl -s http://getcomposer.org/installer | php -n -d allow_url_fopen=1 -d date.timezone="Europe/Berlin" -- --install-dir=./bin/; fi | |||||
| install-dependencies: | |||||
| @make install-composer | |||||
| @php -n -d allow_url_fopen=1 -d date.timezone="Europe/Berlin" ./bin/composer.phar -- update | |||||
| install-dev-dependencies: | |||||
| @make install-composer | |||||
| @php -n -d allow_url_fopen=1 -d date.timezone="Europe/Berlin" ./bin/composer.phar update --dev | |||||
| .PHONY: test help | |||||
| @@ -0,0 +1,28 @@ | |||||
| Getopt.PHP | |||||
| ========== | |||||
| Getopt.PHP is a library for command-line argument processing. It supports PHP version 5.3 and above. | |||||
| Features | |||||
| -------- | |||||
| * Supports both short (eg. `-v`) and long (eg. `--version`) options | |||||
| * Option aliasing, ie. an option can have both a long and a short version | |||||
| * Collapsed short options (eg. `-abc` instead of `-a -b -c`) | |||||
| * Cumulative options (eg. `-vvv`) | |||||
| * Options may take optional or mandatory arguments | |||||
| * Two alternative notations for long options with arguments: `--option value` and `--option=value` | |||||
| * Collapsed short options with mandatory argument at the end (eg. `-ab 1` instead of `-a -b 1`) | |||||
| Documentation | |||||
| ------------- | |||||
| * [Documentation for the current version (2.0+)](http://ulrichsg.github.io/getopt-php/) | |||||
| * [Legacy documentation (1.4)](https://github.com/ulrichsg/getopt-php/blob/2aa8ab1be57200af4cc51447d2a6c244b75ca70b/README.markdown) | |||||
| License | |||||
| ------- | |||||
| Getopt.PHP is published under the [MIT License](http://www.opensource.org/licenses/mit-license.php). | |||||
| [](https://travis-ci.org/ulrichsg/getopt-php) | |||||
| @@ -0,0 +1,24 @@ | |||||
| { | |||||
| "name": "ulrichsg/getopt-php", | |||||
| "type": "library", | |||||
| "description": "Command line arguments parser for PHP 5.3", | |||||
| "homepage": "http://ulrichsg.github.io/getopt-php", | |||||
| "license": "MIT", | |||||
| "authors": [ | |||||
| { | |||||
| "name": "Ulrich Schmidt-Goertz", | |||||
| "email": "ulrich@schmidt-goertz.de" | |||||
| } | |||||
| ], | |||||
| "require": { | |||||
| "php": ">=5.3.0" | |||||
| }, | |||||
| "require-dev": { | |||||
| "phpunit/phpunit": "3.7.*" | |||||
| }, | |||||
| "autoload": { | |||||
| "psr-0": { | |||||
| "Ulrichsg\\": "src" | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,35 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <phpunit | |||||
| bootstrap="vendor/autoload.php" | |||||
| colors="true" | |||||
| convertErrorsToExceptions="true" | |||||
| convertNoticesToExceptions="true" | |||||
| convertWarningsToExceptions="true" | |||||
| stopOnFailure="true" | |||||
| syntaxCheck="true" | |||||
| > | |||||
| <testsuites> | |||||
| <testsuite name="basic"> | |||||
| <directory>test</directory> | |||||
| </testsuite> | |||||
| </testsuites> | |||||
| <filter> | |||||
| <whitelist> | |||||
| <directory suffix=".php">src</directory> | |||||
| </whitelist> | |||||
| </filter> | |||||
| <logging> | |||||
| <log type="coverage-html" | |||||
| target="build/coverage" | |||||
| charset="UTF-8" | |||||
| yui="true" | |||||
| highlight="true" | |||||
| lowUpperBound="40" | |||||
| highLowerBound="70" | |||||
| /> | |||||
| </logging> | |||||
| </phpunit> | |||||
| @@ -0,0 +1,115 @@ | |||||
| <?php | |||||
| namespace Ulrichsg\Getopt; | |||||
| class Argument | |||||
| { | |||||
| /** @var string */ | |||||
| private $default; | |||||
| /** @var callable */ | |||||
| private $validation; | |||||
| /** @var string */ | |||||
| private $name; | |||||
| /** | |||||
| * Creates a new argument. | |||||
| * | |||||
| * @param scalar|null $default Default value or NULL | |||||
| * @param callable|null $validation a validation function (optional) | |||||
| * @throws \InvalidArgumentException | |||||
| */ | |||||
| public function __construct($default = null, $validation = null, $name = "arg") | |||||
| { | |||||
| if (!is_null($default)) { | |||||
| $this->setDefaultValue($default); | |||||
| } | |||||
| if (!is_null($validation)) { | |||||
| $this->setValidation($validation); | |||||
| } | |||||
| $this->name = $name; | |||||
| } | |||||
| /** | |||||
| * Set the default value | |||||
| * | |||||
| * @param scalar $value | |||||
| * @return Argument this object (for chaining calls) | |||||
| * @throws \InvalidArgumentException | |||||
| */ | |||||
| public function setDefaultValue($value) | |||||
| { | |||||
| if (!is_scalar($value)) { | |||||
| throw new \InvalidArgumentException("Default value must be scalar"); | |||||
| } | |||||
| $this->default = $value; | |||||
| return $this; | |||||
| } | |||||
| /** | |||||
| * Set a validation function. | |||||
| * The function must take a string and return true if it is valid, false otherwise. | |||||
| * | |||||
| * @param callable $callable | |||||
| * @return Argument this object (for chaining calls) | |||||
| * @throws \InvalidArgumentException | |||||
| */ | |||||
| public function setValidation($callable) | |||||
| { | |||||
| if (!is_callable($callable)) { | |||||
| throw new \InvalidArgumentException("Validation must be a callable"); | |||||
| } | |||||
| $this->validation = $callable; | |||||
| return $this; | |||||
| } | |||||
| /** | |||||
| * Check if an argument validates according to the specification. | |||||
| * | |||||
| * @param string $arg | |||||
| * @return bool | |||||
| */ | |||||
| public function validates($arg) | |||||
| { | |||||
| return (bool)call_user_func($this->validation, $arg); | |||||
| } | |||||
| /** | |||||
| * Check if the argument has a validation function | |||||
| * | |||||
| * @return bool | |||||
| */ | |||||
| public function hasValidation() | |||||
| { | |||||
| return isset($this->validation); | |||||
| } | |||||
| /** | |||||
| * Check whether the argument has a default value | |||||
| * | |||||
| * @return boolean | |||||
| */ | |||||
| public function hasDefaultValue() | |||||
| { | |||||
| return !empty($this->default); | |||||
| } | |||||
| /** | |||||
| * Retrieve the default value | |||||
| * | |||||
| * @return scalar|null | |||||
| */ | |||||
| public function getDefaultValue() | |||||
| { | |||||
| return $this->default; | |||||
| } | |||||
| /** | |||||
| * Retrieve the argument name | |||||
| * | |||||
| * @return string | |||||
| */ | |||||
| public function getName() | |||||
| { | |||||
| return $this->name; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,233 @@ | |||||
| <?php | |||||
| namespace Ulrichsg\Getopt; | |||||
| /** | |||||
| * Parses command line arguments according to a list of allowed options. | |||||
| */ | |||||
| class CommandLineParser | |||||
| { | |||||
| /** @var Option[] */ | |||||
| private $optionList; | |||||
| private $options = array(); | |||||
| private $operands = array(); | |||||
| /** | |||||
| * Creates a new instance. | |||||
| * | |||||
| * @param Option[] $optionList the list of allowed options | |||||
| */ | |||||
| public function __construct(array $optionList) | |||||
| { | |||||
| $this->optionList = $optionList; | |||||
| } | |||||
| /** | |||||
| * Parses the given arguments and converts them into options and operands. | |||||
| * | |||||
| * @param mixed $arguments a string or an array with one argument per element | |||||
| */ | |||||
| public function parse($arguments) | |||||
| { | |||||
| if (!is_array($arguments)) { | |||||
| $arguments = explode(' ', $arguments); | |||||
| } | |||||
| $operands = array(); | |||||
| $numArgs = count($arguments); | |||||
| for ($i = 0; $i < $numArgs; ++$i) { | |||||
| $arg = trim($arguments[$i]); | |||||
| if (empty($arg)) { | |||||
| continue; | |||||
| } | |||||
| if (($arg === '--') || ($arg === '-') || (mb_substr($arg, 0, 1) !== '-')){ | |||||
| // no more options, treat the remaining arguments as operands | |||||
| $firstOperandIndex = ($arg == '--') ? $i + 1 : $i; | |||||
| $operands = array_slice($arguments, $firstOperandIndex); | |||||
| break; | |||||
| } | |||||
| if (mb_substr($arg, 0, 2) == '--') { | |||||
| $this->addLongOption($arguments, $i); | |||||
| } else { | |||||
| $this->addShortOption($arguments, $i); | |||||
| } | |||||
| } // endfor | |||||
| $this->addDefaultValues(); | |||||
| // remove '--' from operands array | |||||
| foreach ($operands as $operand) { | |||||
| if ($operand !== '--') { | |||||
| $this->operands[] = $operand; | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Returns the options created by a previous invocation of parse(). | |||||
| * | |||||
| * @return array | |||||
| */ | |||||
| public function getOptions() | |||||
| { | |||||
| return $this->options; | |||||
| } | |||||
| /** | |||||
| * Returns the operands created by a previous invocation of parse(), | |||||
| * | |||||
| * @return array | |||||
| */ | |||||
| public function getOperands() | |||||
| { | |||||
| return $this->operands; | |||||
| } | |||||
| private function addShortOption($arguments, &$i) | |||||
| { | |||||
| $numArgs = count($arguments); | |||||
| $option = mb_substr($arguments[$i], 1); | |||||
| if (mb_strlen($option) > 1) { | |||||
| // multiple options strung together | |||||
| $options = $this->splitString($option, 1); | |||||
| foreach ($options as $j => $ch) { | |||||
| if ($j < count($options) - 1 | |||||
| || !( | |||||
| $i < $numArgs - 1 | |||||
| && ((mb_substr($arguments[$i + 1], 0, 1) !== '-') || ($arguments[$i + 1] === '-')) | |||||
| && $this->optionHasArgument($ch) | |||||
| ) | |||||
| ) { | |||||
| $this->addOption($ch, null); | |||||
| } else { // e.g. `ls -sw 100` | |||||
| $value = $arguments[$i + 1]; | |||||
| ++$i; | |||||
| $this->addOption($ch, $value); | |||||
| } | |||||
| } | |||||
| } else { | |||||
| if ($i < $numArgs - 1 | |||||
| && ((mb_substr($arguments[$i + 1], 0, 1) !== '-') || ($arguments[$i + 1] === '-')) | |||||
| && $this->optionHasArgument($option) | |||||
| ) { | |||||
| $value = $arguments[$i + 1]; | |||||
| ++$i; | |||||
| } else { | |||||
| $value = null; | |||||
| } | |||||
| $this->addOption($option, $value); | |||||
| } | |||||
| } | |||||
| private function addLongOption($arguments, &$i) | |||||
| { | |||||
| $option = mb_substr($arguments[$i], 2); | |||||
| if (strpos($option, '=') === false) { | |||||
| if ($i < count($arguments) - 1 | |||||
| && ((mb_substr($arguments[$i + 1], 0, 1) !== '-') || ($arguments[$i + 1] === '-')) | |||||
| && $this->optionHasArgument($option) | |||||
| ) { | |||||
| $value = $arguments[$i + 1]; | |||||
| ++$i; | |||||
| } else { | |||||
| $value = null; | |||||
| } | |||||
| } else { | |||||
| list($option, $value) = explode('=', $option, 2); | |||||
| } | |||||
| $this->addOption($option, $value); | |||||
| } | |||||
| /** | |||||
| * Add an option to the list of known options. | |||||
| * | |||||
| * @param string $string the option's name | |||||
| * @param string $value the option's value (or null) | |||||
| * @throws \UnexpectedValueException | |||||
| * @return void | |||||
| */ | |||||
| private function addOption($string, $value) | |||||
| { | |||||
| foreach ($this->optionList as $option) { | |||||
| if ($option->matches($string)) { | |||||
| if ($option->mode() == Getopt::REQUIRED_ARGUMENT && !mb_strlen($value)) { | |||||
| throw new \UnexpectedValueException("Option '$string' must have a value"); | |||||
| } | |||||
| if ($option->getArgument()->hasValidation()) { | |||||
| if ((mb_strlen($value) > 0) && !$option->getArgument()->validates($value)) { | |||||
| throw new \UnexpectedValueException("Option '$string' has an invalid value"); | |||||
| } | |||||
| } | |||||
| // for no-argument options, check if they are duplicate | |||||
| if ($option->mode() == Getopt::NO_ARGUMENT) { | |||||
| $oldValue = isset($this->options[$string]) ? $this->options[$string] : null; | |||||
| $value = is_null($oldValue) ? 1 : $oldValue + 1; | |||||
| } | |||||
| // for optional-argument options, set value to 1 if none was given | |||||
| $value = (mb_strlen($value) > 0) ? $value : 1; | |||||
| // add both long and short names (if they exist) to the option array to facilitate lookup | |||||
| if ($option->short()) { | |||||
| $this->options[$option->short()] = $value; | |||||
| } | |||||
| if ($option->long()) { | |||||
| $this->options[$option->long()] = $value; | |||||
| } | |||||
| return; | |||||
| } | |||||
| } | |||||
| throw new \UnexpectedValueException("Option '$string' is unknown"); | |||||
| } | |||||
| /** | |||||
| * If there are options with default values that were not overridden by the parsed option string, | |||||
| * add them to the list of known options. | |||||
| */ | |||||
| private function addDefaultValues() | |||||
| { | |||||
| foreach ($this->optionList as $option) { | |||||
| if ($option->getArgument()->hasDefaultValue() | |||||
| && !isset($this->options[$option->short()]) | |||||
| && !isset($this->options[$option->long()]) | |||||
| ) { | |||||
| if ($option->short()) { | |||||
| $this->addOption($option->short(), $option->getArgument()->getDefaultValue()); | |||||
| } | |||||
| if ($option->long()) { | |||||
| $this->addOption($option->long(), $option->getArgument()->getDefaultValue()); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Return true if the given option can take an argument, false if it can't or is unknown. | |||||
| * | |||||
| * @param string $name the option's name | |||||
| * @return boolean | |||||
| */ | |||||
| private function optionHasArgument($name) | |||||
| { | |||||
| foreach ($this->optionList as $option) { | |||||
| if ($option->matches($name)) { | |||||
| return $option->mode() != Getopt::NO_ARGUMENT; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /** | |||||
| * Split the string into individual characters, | |||||
| * | |||||
| * @param string $string string to split | |||||
| * @return array | |||||
| */ | |||||
| private function splitString($string) | |||||
| { | |||||
| $result = array(); | |||||
| for ($i = 0; $i < mb_strlen($string, "UTF-8"); ++$i) { | |||||
| $result[] = mb_substr($string, $i, 1, "UTF-8"); | |||||
| } | |||||
| return $result; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,295 @@ | |||||
| <?php | |||||
| namespace Ulrichsg\Getopt; | |||||
| /** | |||||
| * Getopt.PHP allows for easy processing of command-line arguments. | |||||
| * It is a more powerful, object-oriented alternative to PHP's built-in getopt() function. | |||||
| * | |||||
| * @version 2.1.0 | |||||
| * @license MIT | |||||
| * @link http://ulrichsg.github.io/getopt-php | |||||
| */ | |||||
| class Getopt implements \Countable, \ArrayAccess, \IteratorAggregate | |||||
| { | |||||
| const NO_ARGUMENT = 0; | |||||
| const REQUIRED_ARGUMENT = 1; | |||||
| const OPTIONAL_ARGUMENT = 2; | |||||
| /** @var OptionParser */ | |||||
| private $optionParser; | |||||
| /** @var string */ | |||||
| private $scriptName; | |||||
| /** @var Option[] */ | |||||
| private $optionList = array(); | |||||
| /** @var array */ | |||||
| private $options = array(); | |||||
| /** @var array */ | |||||
| private $operands = array(); | |||||
| /** @var string */ | |||||
| private $banner = "Usage: %s [options] [operands]\n"; | |||||
| /** | |||||
| * Creates a new Getopt object. | |||||
| * | |||||
| * The argument $options can be either a string in the format accepted by the PHP library | |||||
| * function getopt() or an array. | |||||
| * | |||||
| * @param mixed $options Array of options, a String, or null (see documentation for details) | |||||
| * @param int $defaultType The default option type to use when omitted (optional) | |||||
| * @throws \InvalidArgumentException | |||||
| * | |||||
| * @link https://www.gnu.org/s/hello/manual/libc/Getopt.html GNU Getopt manual | |||||
| */ | |||||
| public function __construct($options = null, $defaultType = Getopt::NO_ARGUMENT) | |||||
| { | |||||
| $this->optionParser = new OptionParser($defaultType); | |||||
| if ($options !== null) { | |||||
| $this->addOptions($options); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Extends the list of known options. Takes the same argument types as the constructor. | |||||
| * | |||||
| * @param mixed $options | |||||
| * @throws \InvalidArgumentException | |||||
| */ | |||||
| public function addOptions($options) | |||||
| { | |||||
| if (is_string($options)) { | |||||
| $this->mergeOptions($this->optionParser->parseString($options)); | |||||
| } elseif (is_array($options)) { | |||||
| $this->mergeOptions($this->optionParser->parseArray($options)); | |||||
| } else { | |||||
| throw new \InvalidArgumentException("Getopt(): argument must be string or array"); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Merges new options with the ones already in the Getopt optionList, making sure the resulting list is free of | |||||
| * conflicts. | |||||
| * | |||||
| * @param Option[] $options The list of new options | |||||
| * @throws \InvalidArgumentException | |||||
| */ | |||||
| private function mergeOptions(array $options) | |||||
| { | |||||
| /** @var Option[] $mergedList */ | |||||
| $mergedList = array_merge($this->optionList, $options); | |||||
| $duplicates = array(); | |||||
| foreach ($mergedList as $option) { | |||||
| foreach ($mergedList as $otherOption) { | |||||
| if (($option === $otherOption) || in_array($otherOption, $duplicates)) { | |||||
| continue; | |||||
| } | |||||
| if ($this->optionsConflict($option, $otherOption)) { | |||||
| throw new \InvalidArgumentException('Failed to add options due to conflict'); | |||||
| } | |||||
| if (($option->short() === $otherOption->short()) && ($option->long() === $otherOption->long())) { | |||||
| $duplicates[] = $option; | |||||
| } | |||||
| } | |||||
| } | |||||
| foreach ($mergedList as $index => $option) { | |||||
| if (in_array($option, $duplicates)) { | |||||
| unset($mergedList[$index]); | |||||
| } | |||||
| } | |||||
| $this->optionList = array_values($mergedList); | |||||
| } | |||||
| private function optionsConflict(Option $option1, Option $option2) { | |||||
| if ((is_null($option1->short()) && is_null($option2->short())) | |||||
| || (is_null($option1->long()) && is_null($option2->long()))) { | |||||
| return false; | |||||
| } | |||||
| return ((($option1->short() === $option2->short()) && ($option1->long() !== $option2->long())) | |||||
| || (($option1->short() !== $option2->short()) && ($option1->long() === $option2->long()))); | |||||
| } | |||||
| /** | |||||
| * Evaluate the given arguments. These can be passed either as a string or as an array. | |||||
| * If nothing is passed, the running script's command line arguments are used. | |||||
| * | |||||
| * An {@link \UnexpectedValueException} or {@link \InvalidArgumentException} is thrown | |||||
| * when the arguments are not well-formed or do not conform to the options passed by the user. | |||||
| * | |||||
| * @param mixed $arguments optional ARGV array or space separated string | |||||
| */ | |||||
| public function parse($arguments = null) | |||||
| { | |||||
| $this->options = array(); | |||||
| if (!isset($arguments)) { | |||||
| global $argv; | |||||
| $arguments = $argv; | |||||
| $this->scriptName = array_shift($arguments); // $argv[0] is the script's name | |||||
| } elseif (is_string($arguments)) { | |||||
| $this->scriptName = $_SERVER['PHP_SELF']; | |||||
| $arguments = explode(' ', $arguments); | |||||
| } | |||||
| $parser = new CommandLineParser($this->optionList); | |||||
| $parser->parse($arguments); | |||||
| $this->options = $parser->getOptions(); | |||||
| $this->operands = $parser->getOperands(); | |||||
| } | |||||
| /** | |||||
| * Returns the value of the given option. Must be invoked after parse(). | |||||
| * | |||||
| * The return value can be any of the following: | |||||
| * <ul> | |||||
| * <li><b>null</b> if the option is not given and does not have a default value</li> | |||||
| * <li><b>the default value</b> if it has been defined and the option is not given</li> | |||||
| * <li><b>an integer</b> if the option is given without argument. The | |||||
| * returned value is the number of occurrences of the option.</li> | |||||
| * <li><b>a string</b> if the option is given with an argument. The returned value is that argument.</li> | |||||
| * </ul> | |||||
| * | |||||
| * @param string $name The (short or long) option name. | |||||
| * @return mixed | |||||
| */ | |||||
| public function getOption($name) | |||||
| { | |||||
| return isset($this->options[$name]) ? $this->options[$name] : null; | |||||
| } | |||||
| /** | |||||
| * Returns the list of options. Must be invoked after parse() (otherwise it returns an empty array). | |||||
| * | |||||
| * @return array | |||||
| */ | |||||
| public function getOptions() | |||||
| { | |||||
| return $this->options; | |||||
| } | |||||
| /** | |||||
| * Returns the list of operands. Must be invoked after parse(). | |||||
| * | |||||
| * @return array | |||||
| */ | |||||
| public function getOperands() | |||||
| { | |||||
| return $this->operands; | |||||
| } | |||||
| /** | |||||
| * Returns the i-th operand (starting with 0), or null if it does not exist. Must be invoked after parse(). | |||||
| * | |||||
| * @param int $i | |||||
| * @return string | |||||
| */ | |||||
| public function getOperand($i) | |||||
| { | |||||
| return ($i < count($this->operands)) ? $this->operands[$i] : null; | |||||
| } | |||||
| /** | |||||
| * Returns the banner string | |||||
| * | |||||
| * @return string | |||||
| */ | |||||
| public function getBanner() | |||||
| { | |||||
| return $this->banner; | |||||
| } | |||||
| /** | |||||
| * Set the banner string | |||||
| * | |||||
| * @param string $banner The banner string; will be passed to sprintf(), can include %s for current scripts name. | |||||
| * Be sure to include a trailing line feed. | |||||
| * @return Getopt | |||||
| */ | |||||
| public function setBanner($banner) | |||||
| { | |||||
| $this->banner = $banner; | |||||
| return $this; | |||||
| } | |||||
| /** | |||||
| * Returns an usage information text generated from the given options. | |||||
| * @param int $padding Number of characters to pad output of options to | |||||
| * @return string | |||||
| */ | |||||
| public function getHelpText($padding = 25) | |||||
| { | |||||
| $helpText = sprintf($this->getBanner(), $this->scriptName); | |||||
| $helpText .= "Options:\n"; | |||||
| foreach ($this->optionList as $option) { | |||||
| $mode = ''; | |||||
| switch ($option->mode()) { | |||||
| case self::NO_ARGUMENT: | |||||
| $mode = ''; | |||||
| break; | |||||
| case self::REQUIRED_ARGUMENT: | |||||
| $mode = "<".$option->getArgument()->getName().">"; | |||||
| break; | |||||
| case self::OPTIONAL_ARGUMENT: | |||||
| $mode = "[<".$option->getArgument()->getName().">]"; | |||||
| break; | |||||
| } | |||||
| $short = ($option->short()) ? '-'.$option->short() : ''; | |||||
| $long = ($option->long()) ? '--'.$option->long() : ''; | |||||
| if ($short && $long) { | |||||
| $options = $short.', '.$long; | |||||
| } else { | |||||
| $options = $short ? : $long; | |||||
| } | |||||
| $padded = str_pad(sprintf(" %s %s", $options, $mode), $padding); | |||||
| $helpText .= sprintf("%s %s\n", $padded, $option->getDescription()); | |||||
| } | |||||
| return $helpText; | |||||
| } | |||||
| /* | |||||
| * Interface support functions | |||||
| */ | |||||
| public function count() | |||||
| { | |||||
| return count($this->options); | |||||
| } | |||||
| public function offsetExists($offset) | |||||
| { | |||||
| return isset($this->options[$offset]); | |||||
| } | |||||
| public function offsetGet($offset) | |||||
| { | |||||
| return $this->getOption($offset); | |||||
| } | |||||
| public function offsetSet($offset, $value) | |||||
| { | |||||
| throw new \LogicException('Getopt is read-only'); | |||||
| } | |||||
| public function offsetUnset($offset) | |||||
| { | |||||
| throw new \LogicException('Getopt is read-only'); | |||||
| } | |||||
| public function getIterator() | |||||
| { | |||||
| // For options that have both short and long names, $this->options has two entries. | |||||
| // We don't want this when iterating, so we have to filter the duplicates out. | |||||
| $filteredOptions = array(); | |||||
| foreach ($this->options as $name => $value) { | |||||
| $keep = true; | |||||
| foreach ($this->optionList as $option) { | |||||
| if ($option->long() == $name && !is_null($option->short())) { | |||||
| $keep = false; | |||||
| } | |||||
| } | |||||
| if ($keep) { | |||||
| $filteredOptions[$name] = $value; | |||||
| } | |||||
| } | |||||
| return new \ArrayIterator($filteredOptions); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,162 @@ | |||||
| <?php | |||||
| namespace Ulrichsg\Getopt; | |||||
| /** | |||||
| * Represents an option that Getopt accepts. | |||||
| */ | |||||
| class Option | |||||
| { | |||||
| private $short; | |||||
| private $long; | |||||
| private $mode; | |||||
| private $description = ''; | |||||
| private $argument; | |||||
| /** | |||||
| * Creates a new option. | |||||
| * | |||||
| * @param string $short the option's short name (a single letter or digit) or null for long-only options | |||||
| * @param string $long the option's long name (a string of 2+ letter/digit/_/- characters, starting with a letter | |||||
| * or digit) or null for short-only options | |||||
| * @param int $mode whether the option can/must have an argument (one of the constants defined in the Getopt class) | |||||
| * (optional, defaults to no argument) | |||||
| * @throws \InvalidArgumentException if both short and long name are null | |||||
| */ | |||||
| public function __construct($short, $long, $mode = Getopt::NO_ARGUMENT) | |||||
| { | |||||
| if (!$short && !$long) { | |||||
| throw new \InvalidArgumentException("The short and long name may not both be empty"); | |||||
| } | |||||
| $this->setShort($short); | |||||
| $this->setLong($long); | |||||
| $this->setMode($mode); | |||||
| $this->argument = new Argument(); | |||||
| } | |||||
| /** | |||||
| * Defines a description for the option. This is only used for generating usage information. | |||||
| * | |||||
| * @param string $description | |||||
| * @return Option this object (for chaining calls) | |||||
| */ | |||||
| public function setDescription($description) | |||||
| { | |||||
| $this->description = $description; | |||||
| return $this; | |||||
| } | |||||
| /** | |||||
| * Defines a default value for the option. | |||||
| * | |||||
| * @param mixed $value | |||||
| * @return Option this object (for chaining calls) | |||||
| */ | |||||
| public function setDefaultValue($value) | |||||
| { | |||||
| $this->argument->setDefaultValue($value); | |||||
| return $this; | |||||
| } | |||||
| /** | |||||
| * Defines a validation function for the option. | |||||
| * | |||||
| * @param callable $function | |||||
| * @return Option this object (for chaining calls) | |||||
| */ | |||||
| public function setValidation($function) | |||||
| { | |||||
| $this->argument->setValidation($function); | |||||
| return $this; | |||||
| } | |||||
| /** | |||||
| * Sets the argument object directly. | |||||
| * | |||||
| * @param Argument $arg | |||||
| * @return Option this object (for chaining calls) | |||||
| */ | |||||
| public function setArgument(Argument $arg) | |||||
| { | |||||
| if ($this->mode == Getopt::NO_ARGUMENT) { | |||||
| throw new \InvalidArgumentException("Option should not have any argument"); | |||||
| } | |||||
| $this->argument = $arg; | |||||
| return $this; | |||||
| } | |||||
| /** | |||||
| * Returns true if the given string is equal to either the short or the long name. | |||||
| * | |||||
| * @param string $string | |||||
| * @return bool | |||||
| */ | |||||
| public function matches($string) | |||||
| { | |||||
| return ($string === $this->short) || ($string === $this->long); | |||||
| } | |||||
| public function short() | |||||
| { | |||||
| return $this->short; | |||||
| } | |||||
| public function long() | |||||
| { | |||||
| return $this->long; | |||||
| } | |||||
| public function mode() | |||||
| { | |||||
| return $this->mode; | |||||
| } | |||||
| public function getDescription() | |||||
| { | |||||
| return $this->description; | |||||
| } | |||||
| /** | |||||
| * Retrieve the argument object | |||||
| * | |||||
| * @return Argument | |||||
| */ | |||||
| public function getArgument() | |||||
| { | |||||
| return $this->argument; | |||||
| } | |||||
| /** | |||||
| * Fluent interface for constructor so options can be added during construction | |||||
| * @see Options::__construct() | |||||
| */ | |||||
| public static function create($short, $long, $mode = Getopt::NO_ARGUMENT) | |||||
| { | |||||
| return new self($short, $long, $mode); | |||||
| } | |||||
| private function setShort($short) | |||||
| { | |||||
| if (!(is_null($short) || preg_match("/^[a-zA-Z0-9]$/", $short))) { | |||||
| throw new \InvalidArgumentException("Short option must be null or a letter/digit, found '$short'"); | |||||
| } | |||||
| $this->short = $short; | |||||
| } | |||||
| private function setLong($long) | |||||
| { | |||||
| if (!(is_null($long) || preg_match("/^[a-zA-Z0-9][a-zA-Z0-9_-]{1,}$/", $long))) { | |||||
| throw new \InvalidArgumentException("Long option must be null or an alphanumeric string, found '$long'"); | |||||
| } | |||||
| $this->long = $long; | |||||
| } | |||||
| private function setMode($mode) | |||||
| { | |||||
| if (!in_array($mode, array(Getopt::NO_ARGUMENT, Getopt::OPTIONAL_ARGUMENT, Getopt::REQUIRED_ARGUMENT), true)) { | |||||
| throw new \InvalidArgumentException("Option mode must be one of " | |||||
| ."Getopt::NO_ARGUMENT, Getopt::OPTIONAL_ARGUMENT and Getopt::REQUIRED_ARGUMENT"); | |||||
| } | |||||
| $this->mode = $mode; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,137 @@ | |||||
| <?php | |||||
| namespace Ulrichsg\Getopt; | |||||
| /** | |||||
| * Converts user-given option specifications into Option objects. | |||||
| */ | |||||
| class OptionParser | |||||
| { | |||||
| private $defaultMode; | |||||
| /** | |||||
| * Creates a new instance. | |||||
| * | |||||
| * @param int $defaultMode will be assigned to options when no mode is given for them. | |||||
| */ | |||||
| public function __construct($defaultMode) { | |||||
| $this->defaultMode = $defaultMode; | |||||
| } | |||||
| /** | |||||
| * Parse a GNU-style option string. | |||||
| * | |||||
| * @param string $string the option string | |||||
| * @return Option[] | |||||
| * @throws \InvalidArgumentException | |||||
| */ | |||||
| public function parseString($string) | |||||
| { | |||||
| if (!mb_strlen($string)) { | |||||
| throw new \InvalidArgumentException('Option string must not be empty'); | |||||
| } | |||||
| $options = array(); | |||||
| $eol = mb_strlen($string) - 1; | |||||
| $nextCanBeColon = false; | |||||
| for ($i = 0; $i <= $eol; ++$i) { | |||||
| $ch = $string[$i]; | |||||
| if (!preg_match('/^[A-Za-z0-9]$/', $ch)) { | |||||
| $colon = $nextCanBeColon ? " or ':'" : ''; | |||||
| throw new \InvalidArgumentException("Option string is not well formed: " | |||||
| ."expected a letter$colon, found '$ch' at position ".($i + 1)); | |||||
| } | |||||
| if ($i == $eol || $string[$i + 1] != ':') { | |||||
| $options[] = new Option($ch, null, Getopt::NO_ARGUMENT); | |||||
| $nextCanBeColon = true; | |||||
| } elseif ($i < $eol - 1 && $string[$i + 2] == ':') { | |||||
| $options[] = new Option($ch, null, Getopt::OPTIONAL_ARGUMENT); | |||||
| $i += 2; | |||||
| $nextCanBeColon = false; | |||||
| } else { | |||||
| $options[] = new Option($ch, null, Getopt::REQUIRED_ARGUMENT); | |||||
| ++$i; | |||||
| $nextCanBeColon = true; | |||||
| } | |||||
| } | |||||
| return $options; | |||||
| } | |||||
| /** | |||||
| * Processes an option array. The array elements can either be Option objects or arrays conforming to the format | |||||
| * (short, long, mode [, description [, default]]). See documentation for details. | |||||
| * | |||||
| * Developer note: Please don't add any further elements to the array. Future features should be configured only | |||||
| * through the Option class's methods. | |||||
| * | |||||
| * @param array $array | |||||
| * @return Option[] | |||||
| * @throws \InvalidArgumentException | |||||
| */ | |||||
| public function parseArray(array $array) | |||||
| { | |||||
| if (empty($array)) { | |||||
| throw new \InvalidArgumentException('No options given'); | |||||
| } | |||||
| $options = array(); | |||||
| foreach ($array as $row) { | |||||
| if ($row instanceof Option) { | |||||
| $options[] = $row; | |||||
| } elseif (is_array($row)) { | |||||
| $options[] = $this->createOption($row); | |||||
| } else { | |||||
| throw new \InvalidArgumentException("Invalid option type, must be Option or array"); | |||||
| } | |||||
| } | |||||
| return $options; | |||||
| } | |||||
| /** | |||||
| * @param array $row | |||||
| * @return Option | |||||
| */ | |||||
| private function createOption(array $row) | |||||
| { | |||||
| $rowSize = count($row); | |||||
| if ($rowSize < 3) { | |||||
| $row = $this->completeOptionArray($row); | |||||
| } | |||||
| $option = new Option($row[0], $row[1], $row[2]); | |||||
| if ($rowSize >= 4) { | |||||
| $option->setDescription($row[3]); | |||||
| } | |||||
| if ($rowSize >= 5 && $row[2] != Getopt::NO_ARGUMENT) { | |||||
| $option->setArgument(new Argument($row[4])); | |||||
| } | |||||
| return $option; | |||||
| } | |||||
| /** | |||||
| * When using arrays, instead of a full option spec ([short, long, type]) users can leave out one or more of | |||||
| * these parts and have Getopt fill them in intelligently: | |||||
| * - If either the short or the long option string is left out, the first element of the given array is interpreted | |||||
| * as either short (if it has length 1) or long, and the other one is set to null. | |||||
| * - If the type is left out, it is set to NO_ARGUMENT. | |||||
| * | |||||
| * @param array $row | |||||
| * @return array | |||||
| */ | |||||
| private function completeOptionArray(array $row) | |||||
| { | |||||
| $short = (strlen($row[0]) == 1) ? $row[0] : null; | |||||
| $long = null; | |||||
| if (is_null($short)) { | |||||
| $long = $row[0]; | |||||
| } elseif (count($row) > 1 && !is_int($row[1])) { | |||||
| $long = $row[1]; | |||||
| } | |||||
| $mode = $this->defaultMode; | |||||
| if (count($row) == 2 && is_int($row[1])) { | |||||
| $mode = $row[1]; | |||||
| } | |||||
| return array($short, $long, $mode); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,40 @@ | |||||
| <?php | |||||
| namespace Ulrichsg\Getopt; | |||||
| class ArgumentTest extends \PHPUnit_Framework_TestCase | |||||
| { | |||||
| public function testConstructor() | |||||
| { | |||||
| $argument1 = new Argument(); | |||||
| $argument2 = new Argument(10); | |||||
| $this->assertFalse($argument1->hasDefaultValue()); | |||||
| $this->assertEquals(10, $argument2->getDefaultValue()); | |||||
| } | |||||
| public function testSetDefaultValueNotScalar() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| $argument = new Argument(); | |||||
| $argument->setDefaultValue(array()); | |||||
| } | |||||
| public function testValidates() | |||||
| { | |||||
| $test = $this; | |||||
| $argument = new Argument(); | |||||
| $argument->setValidation(function($arg) use ($test, $argument) { | |||||
| $test->assertEquals('test', $arg); | |||||
| return true; | |||||
| }); | |||||
| $this->assertTrue($argument->hasValidation()); | |||||
| $this->assertTrue($argument->validates('test')); | |||||
| } | |||||
| public function testSetValidationUncallable() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| $argument = new Argument(); | |||||
| $argument->setValidation(''); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,341 @@ | |||||
| <?php | |||||
| namespace Ulrichsg\Getopt; | |||||
| class CommandLineParserTest extends \PHPUnit_Framework_TestCase | |||||
| { | |||||
| public function testParseNoOptions() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null) | |||||
| )); | |||||
| $parser->parse('something'); | |||||
| $this->assertCount(0, $parser->getOptions()); | |||||
| $operands = $parser->getOperands(); | |||||
| $this->assertCount(1, $operands); | |||||
| $this->assertEquals('something', $operands[0]); | |||||
| } | |||||
| public function testParseUnknownOption() | |||||
| { | |||||
| $this->setExpectedException('UnexpectedValueException'); | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null) | |||||
| )); | |||||
| $parser->parse('-b'); | |||||
| } | |||||
| public function testParseRequiredArgumentMissing() | |||||
| { | |||||
| $this->setExpectedException('UnexpectedValueException'); | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null, Getopt::REQUIRED_ARGUMENT) | |||||
| )); | |||||
| $parser->parse('-a'); | |||||
| } | |||||
| public function testParseMultipleOptionsWithOneHyphen() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null), | |||||
| new Option('b', null) | |||||
| )); | |||||
| $parser->parse('-ab'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals(1, $options['a']); | |||||
| $this->assertEquals(1, $options['b']); | |||||
| } | |||||
| public function testParseCumulativeOption() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null), | |||||
| new Option('b', null) | |||||
| )); | |||||
| $parser->parse('-a -b -a -a'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals(3, $options['a']); | |||||
| $this->assertEquals(1, $options['b']); | |||||
| } | |||||
| public function testParseCumulativeOptionShort() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null), | |||||
| new Option('b', null) | |||||
| )); | |||||
| $parser->parse('-abaa'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals(3, $options['a']); | |||||
| $this->assertEquals(1, $options['b']); | |||||
| } | |||||
| public function testParseShortOptionWithArgument() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null, Getopt::REQUIRED_ARGUMENT) | |||||
| )); | |||||
| $parser->parse('-a value'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals('value', $options['a']); | |||||
| } | |||||
| public function testParseZeroArgument() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null, Getopt::REQUIRED_ARGUMENT) | |||||
| )); | |||||
| $parser->parse('-a 0'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals('0', $options['a']); | |||||
| } | |||||
| public function testParseNumericOption() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null, Getopt::REQUIRED_ARGUMENT), | |||||
| new Option('2', null) | |||||
| )); | |||||
| $parser->parse('-a 2 -2'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals('2', $options['a']); | |||||
| $this->assertEquals(1, $options['2']); | |||||
| } | |||||
| public function testParseCollapsedShortOptionsRequiredArgumentMissing() | |||||
| { | |||||
| $this->setExpectedException('UnexpectedValueException'); | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null), | |||||
| new Option('b', null, Getopt::REQUIRED_ARGUMENT) | |||||
| )); | |||||
| $parser->parse('-ab'); | |||||
| } | |||||
| public function testParseCollapsedShortOptionsWithArgument() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null), | |||||
| new Option('b', null, Getopt::REQUIRED_ARGUMENT) | |||||
| )); | |||||
| $parser->parse('-ab value'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals(1, $options['a']); | |||||
| $this->assertEquals('value', $options['b']); | |||||
| } | |||||
| public function testParseNoArgumentOptionAndOperand() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null), | |||||
| )); | |||||
| $parser->parse('-a b'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals(1, $options['a']); | |||||
| $operands = $parser->getOperands(); | |||||
| $this->assertCount(1, $operands); | |||||
| $this->assertEquals('b', $operands[0]); | |||||
| } | |||||
| public function testParseOperandsOnly() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null, Getopt::REQUIRED_ARGUMENT), | |||||
| new Option('b', null) | |||||
| )); | |||||
| $parser->parse('-- -a -b'); | |||||
| $this->assertCount(0, $parser->getOptions()); | |||||
| $operands = $parser->getOperands(); | |||||
| $this->assertCount(2, $operands); | |||||
| $this->assertEquals('-a', $operands[0]); | |||||
| $this->assertEquals('-b', $operands[1]); | |||||
| } | |||||
| public function testParseLongOptionWithoutArgument() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('o', 'option', Getopt::OPTIONAL_ARGUMENT) | |||||
| )); | |||||
| $parser->parse('--option'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals(1, $options['option']); | |||||
| } | |||||
| public function testParseLongOptionWithoutArgumentAndOperand() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('o', 'option', Getopt::NO_ARGUMENT) | |||||
| )); | |||||
| $parser->parse('--option something'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals(1, $options['option']); | |||||
| $operands = $parser->getOperands(); | |||||
| $this->assertCount(1, $operands); | |||||
| $this->assertEquals('something', $operands[0]); | |||||
| } | |||||
| public function testParseLongOptionWithArgument() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('o', 'option', Getopt::OPTIONAL_ARGUMENT) | |||||
| )); | |||||
| $parser->parse('--option value'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals('value', $options['option']); | |||||
| $this->assertEquals('value', $options['o']); | |||||
| } | |||||
| public function testParseLongOptionWithEqualsSignAndArgument() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('o', 'option', Getopt::OPTIONAL_ARGUMENT) | |||||
| )); | |||||
| $parser->parse('--option=value something'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals('value', $options['option']); | |||||
| $operands = $parser->getOperands(); | |||||
| $this->assertCount(1, $operands); | |||||
| $this->assertEquals('something', $operands[0]); | |||||
| } | |||||
| public function testParseLongOptionWithValueStartingWithHyphen() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('o', 'option', Getopt::REQUIRED_ARGUMENT) | |||||
| )); | |||||
| $parser->parse('--option=-value'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals('-value', $options['option']); | |||||
| } | |||||
| public function testParseNoValueStartingWithHyphenRequired() | |||||
| { | |||||
| $this->setExpectedException('UnexpectedValueException'); | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null, Getopt::REQUIRED_ARGUMENT), | |||||
| new Option('b', null) | |||||
| )); | |||||
| $parser->parse('-a -b'); | |||||
| } | |||||
| public function testParseNoValueStartingWithHyphenOptional() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null, Getopt::OPTIONAL_ARGUMENT), | |||||
| new Option('b', null) | |||||
| )); | |||||
| $parser->parse('-a -b'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals(1, $options['a']); | |||||
| $this->assertEquals(1, $options['b']); | |||||
| } | |||||
| public function testParseOptionWithDefaultValue() | |||||
| { | |||||
| $optionA = new Option('a', null, Getopt::REQUIRED_ARGUMENT); | |||||
| $optionA->setArgument(new Argument(10)); | |||||
| $optionB = new Option('b', 'beta', Getopt::REQUIRED_ARGUMENT); | |||||
| $optionB->setArgument(new Argument(20)); | |||||
| $parser = new CommandLineParser(array($optionA, $optionB)); | |||||
| $parser->parse('-a 12'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals(12, $options['a']); | |||||
| $this->assertEquals(20, $options['b']); | |||||
| $this->assertEquals(20, $options['beta']); | |||||
| } | |||||
| public function testDoubleHyphenNotInOperands() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null, Getopt::REQUIRED_ARGUMENT) | |||||
| )); | |||||
| $parser->parse('-a 0 foo -- bar baz'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals('0', $options['a']); | |||||
| $operands = $parser->getOperands(); | |||||
| $this->assertCount(3, $operands); | |||||
| $this->assertEquals('foo', $operands[0]); | |||||
| $this->assertEquals('bar', $operands[1]); | |||||
| $this->assertEquals('baz', $operands[2]); | |||||
| } | |||||
| public function testSingleHyphenValue() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', 'alpha', Getopt::REQUIRED_ARGUMENT) | |||||
| )); | |||||
| $parser->parse('-a -'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals('-', $options['a']); | |||||
| $operands = $parser->getOperands(); | |||||
| $this->assertCount(0, $operands); | |||||
| $parser->parse('--alpha -'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals('-', $options['a']); | |||||
| $operands = $parser->getOperands(); | |||||
| $this->assertCount(0, $operands); | |||||
| } | |||||
| public function testSingleHyphenOperand() | |||||
| { | |||||
| $parser = new CommandLineParser(array( | |||||
| new Option('a', null, Getopt::REQUIRED_ARGUMENT) | |||||
| )); | |||||
| $parser->parse('-a 0 -'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertEquals('0', $options['a']); | |||||
| $operands = $parser->getOperands(); | |||||
| $this->assertCount(1, $operands); | |||||
| $this->assertEquals('-', $operands[0]); | |||||
| } | |||||
| public function testParseWithArgumentValidation() | |||||
| { | |||||
| $validation = 'is_numeric'; | |||||
| $optionA = new Option('a', null, Getopt::OPTIONAL_ARGUMENT); | |||||
| $optionA->setArgument(new Argument(null, $validation)); | |||||
| $optionB = new Option('b', null, Getopt::REQUIRED_ARGUMENT); | |||||
| $optionB->setArgument(new Argument(null, $validation)); | |||||
| $optionC = new Option('c', null, Getopt::OPTIONAL_ARGUMENT); | |||||
| $optionC->setArgument(new Argument(null, $validation)); | |||||
| $parser = new CommandLineParser(array($optionA, $optionB, $optionC)); | |||||
| $parser->parse('-a 1 -b 2 -c'); | |||||
| $options = $parser->getOptions(); | |||||
| $this->assertSame('1', $options['a']); | |||||
| $this->assertSame('2', $options['b']); | |||||
| $this->assertSame(1, $options['c']); | |||||
| } | |||||
| public function testParseInvalidArgument() | |||||
| { | |||||
| $this->setExpectedException('UnexpectedValueException'); | |||||
| $validation = 'is_numeric'; | |||||
| $option = new Option('a', null, Getopt::OPTIONAL_ARGUMENT); | |||||
| $option->setArgument(new Argument(null, $validation)); | |||||
| $parser = new CommandLineParser(array($option)); | |||||
| $parser->parse('-a nonnumeric'); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,199 @@ | |||||
| <?php | |||||
| namespace Ulrichsg\Getopt; | |||||
| class GetoptTest extends \PHPUnit_Framework_TestCase | |||||
| { | |||||
| public function testAddOptions() | |||||
| { | |||||
| $getopt = new Getopt(); | |||||
| $getopt->addOptions('a:'); | |||||
| $getopt->addOptions( | |||||
| array( | |||||
| array('s', null, Getopt::OPTIONAL_ARGUMENT), | |||||
| array(null, 'long', Getopt::OPTIONAL_ARGUMENT), | |||||
| array('n', 'name', Getopt::OPTIONAL_ARGUMENT) | |||||
| ) | |||||
| ); | |||||
| $getopt->parse('-a aparam -s sparam --long longparam'); | |||||
| $this->assertEquals('aparam', $getopt->getOption('a')); | |||||
| $this->assertEquals('longparam', $getopt->getOption('long')); | |||||
| $this->assertEquals('sparam', $getopt->getOption('s')); | |||||
| } | |||||
| public function testAddOptionsChooseShortOrLongAutomatically() | |||||
| { | |||||
| $getopt = new Getopt(); | |||||
| $getopt->addOptions( | |||||
| array( | |||||
| array('s'), | |||||
| array('long', Getopt::OPTIONAL_ARGUMENT) | |||||
| ) | |||||
| ); | |||||
| $getopt->parse('-s --long longparam'); | |||||
| $this->assertEquals('longparam', $getopt->getOption('long')); | |||||
| $this->assertEquals('1', $getopt->getOption('s')); | |||||
| } | |||||
| public function testAddOptionsUseDefaultArgumentType() | |||||
| { | |||||
| $getopt = new Getopt(null, Getopt::REQUIRED_ARGUMENT); | |||||
| $getopt->addOptions( | |||||
| array( | |||||
| array('l', 'long') | |||||
| ) | |||||
| ); | |||||
| $getopt->parse('-l something'); | |||||
| $this->assertEquals('something', $getopt->getOption('l')); | |||||
| $getopt->parse('--long someOtherThing'); | |||||
| $this->assertEquals('someOtherThing', $getopt->getOption('long')); | |||||
| } | |||||
| public function testAddOptionsFailsOnInvalidArgument() | |||||
| { | |||||
| $this->setExpectedException('\InvalidArgumentException'); | |||||
| $getopt = new Getopt(null); | |||||
| $getopt->addOptions(new Option('a', 'alpha')); | |||||
| } | |||||
| public function testAddOptionsOverwritesExistingOptions() | |||||
| { | |||||
| $getopt = new Getopt(array( | |||||
| array('a', null, Getopt::REQUIRED_ARGUMENT) | |||||
| )); | |||||
| $getopt->addOptions(array( | |||||
| array('a', null, Getopt::NO_ARGUMENT) | |||||
| )); | |||||
| $getopt->parse('-a foo'); | |||||
| $this->assertEquals(1, $getopt->getOption('a')); | |||||
| $this->assertEquals('foo', $getopt->getOperand(0)); | |||||
| } | |||||
| public function testAddOptionsFailsOnConflict() | |||||
| { | |||||
| $this->setExpectedException('\InvalidArgumentException'); | |||||
| $getopt = new Getopt(array( | |||||
| array('v', 'version') | |||||
| )); | |||||
| $getopt->addOptions(array( | |||||
| array('v', 'verbose') | |||||
| )); | |||||
| } | |||||
| public function testParseUsesGlobalArgvWhenNoneGiven() | |||||
| { | |||||
| global $argv; | |||||
| $argv = array('foo.php', '-a'); | |||||
| $getopt = new Getopt('a'); | |||||
| $getopt->parse(); | |||||
| $this->assertEquals(1, $getopt->getOption('a')); | |||||
| } | |||||
| public function testAccessMethods() | |||||
| { | |||||
| $getopt = new Getopt('a'); | |||||
| $getopt->parse('-a foo'); | |||||
| $options = $getopt->getOptions(); | |||||
| $this->assertCount(1, $options); | |||||
| $this->assertEquals(1, $options['a']); | |||||
| $this->assertEquals(1, $getopt->getOption('a')); | |||||
| $operands = $getopt->getOperands(); | |||||
| $this->assertCount(1, $operands); | |||||
| $this->assertEquals('foo', $operands[0]); | |||||
| $this->assertEquals('foo', $getopt->getOperand(0)); | |||||
| } | |||||
| public function testCountable() | |||||
| { | |||||
| $getopt = new Getopt('abc'); | |||||
| $getopt->parse('-abc'); | |||||
| $this->assertEquals(3, count($getopt)); | |||||
| } | |||||
| public function testArrayAccess() | |||||
| { | |||||
| $getopt = new Getopt('q'); | |||||
| $getopt->parse('-q'); | |||||
| $this->assertEquals(1, $getopt['q']); | |||||
| } | |||||
| public function testIterable() | |||||
| { | |||||
| $getopt = new Getopt(array( | |||||
| array(null, 'alpha', Getopt::NO_ARGUMENT), | |||||
| array('b', 'beta', Getopt::REQUIRED_ARGUMENT) | |||||
| )); | |||||
| $getopt->parse('--alpha -b foo'); | |||||
| $expected = array('alpha' => 1, 'b' => 'foo'); // 'beta' should not occur | |||||
| foreach ($getopt as $option => $value) { | |||||
| $this->assertEquals($expected[$option], $value); | |||||
| } | |||||
| } | |||||
| public function testHelpText() | |||||
| { | |||||
| $getopt = new Getopt(array( | |||||
| array('a', 'alpha', Getopt::NO_ARGUMENT, 'Short and long options with no argument'), | |||||
| array(null, 'beta', Getopt::OPTIONAL_ARGUMENT, 'Long option only with an optional argument'), | |||||
| array('c', null, Getopt::REQUIRED_ARGUMENT, 'Short option only with a mandatory argument') | |||||
| )); | |||||
| $getopt->parse(''); | |||||
| $script = $_SERVER['PHP_SELF']; | |||||
| $expected = "Usage: $script [options] [operands]\n"; | |||||
| $expected .= "Options:\n"; | |||||
| $expected .= " -a, --alpha Short and long options with no argument\n"; | |||||
| $expected .= " --beta [<arg>] Long option only with an optional argument\n"; | |||||
| $expected .= " -c <arg> Short option only with a mandatory argument\n"; | |||||
| $this->assertEquals($expected, $getopt->getHelpText()); | |||||
| } | |||||
| public function testHelpTextWithoutDescriptions() | |||||
| { | |||||
| $getopt = new Getopt(array( | |||||
| array('a', 'alpha', Getopt::NO_ARGUMENT), | |||||
| array(null, 'beta', Getopt::OPTIONAL_ARGUMENT), | |||||
| array('c', null, Getopt::REQUIRED_ARGUMENT) | |||||
| )); | |||||
| $getopt->parse(''); | |||||
| $script = $_SERVER['PHP_SELF']; | |||||
| $expected = "Usage: $script [options] [operands]\n"; | |||||
| $expected .= "Options:\n"; | |||||
| $expected .= " -a, --alpha \n"; | |||||
| $expected .= " --beta [<arg>] \n"; | |||||
| $expected .= " -c <arg> \n"; | |||||
| $this->assertEquals($expected, $getopt->getHelpText()); | |||||
| } | |||||
| public function testHelpTextNoParse() | |||||
| { | |||||
| $getopt = new Getopt(); | |||||
| $expected = "Usage: [options] [operands]\nOptions:\n"; | |||||
| $this->assertSame($expected, $getopt->getHelpText()); | |||||
| } | |||||
| public function testHelpTextWithCustomBanner() | |||||
| { | |||||
| $script = $_SERVER['PHP_SELF']; | |||||
| $getopt = new Getopt(); | |||||
| $getopt->setBanner("My custom Banner %s\n"); | |||||
| $this->assertSame("My custom Banner \nOptions:\n", $getopt->getHelpText()); | |||||
| $getopt->parse(''); | |||||
| $this->assertSame("My custom Banner $script\nOptions:\n", $getopt->getHelpText()); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,112 @@ | |||||
| <?php | |||||
| namespace Ulrichsg\Getopt; | |||||
| class OptionParserTest extends \PHPUnit_Framework_TestCase | |||||
| { | |||||
| /** @var OptionParser */ | |||||
| private $parser; | |||||
| public function setUp() | |||||
| { | |||||
| $this->parser = new OptionParser(Getopt::REQUIRED_ARGUMENT); | |||||
| } | |||||
| public function testParseString() | |||||
| { | |||||
| $options = $this->parser->parseString('ab:c::3'); | |||||
| $this->assertInternalType('array', $options); | |||||
| $this->assertCount(4, $options); | |||||
| foreach ($options as $option) { | |||||
| $this->assertInstanceOf('Ulrichsg\Getopt\Option', $option); | |||||
| $this->assertNull($option->long()); | |||||
| switch ($option->short()) { | |||||
| case 'a': | |||||
| case '3': | |||||
| $this->assertEquals(Getopt::NO_ARGUMENT, $option->mode()); | |||||
| break; | |||||
| case 'b': | |||||
| $this->assertEquals(Getopt::REQUIRED_ARGUMENT, $option->mode()); | |||||
| break; | |||||
| case 'c': | |||||
| $this->assertEquals(Getopt::OPTIONAL_ARGUMENT, $option->mode()); | |||||
| break; | |||||
| default: | |||||
| $this->fail('Unexpected option: '.$option->short()); | |||||
| } | |||||
| } | |||||
| } | |||||
| public function testParseStringEmpty() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| $this->parser->parseString(''); | |||||
| } | |||||
| public function testParseStringInvalidCharacter() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| $this->parser->parseString('ab:c::dä'); | |||||
| } | |||||
| public function testParseStringStartsWithColon() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| $this->parser->parseString(':ab:c::d'); | |||||
| } | |||||
| public function testParseStringTripleColon() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| $this->parser->parseString('ab:c:::d'); | |||||
| } | |||||
| public function testParseArray() | |||||
| { | |||||
| $options = $this->parser->parseArray( | |||||
| array( | |||||
| array('a', 'alpha', Getopt::OPTIONAL_ARGUMENT, 'Description', 42), | |||||
| new Option('b', 'beta'), | |||||
| array('c') | |||||
| ) | |||||
| ); | |||||
| $this->assertCount(3, $options); | |||||
| foreach ($options as $option) { | |||||
| $this->assertInstanceOf('Ulrichsg\Getopt\Option', $option); | |||||
| switch ($option->short()) { | |||||
| case 'a': | |||||
| $this->assertEquals('alpha', $option->long()); | |||||
| $this->assertEquals(Getopt::OPTIONAL_ARGUMENT, $option->mode()); | |||||
| $this->assertEquals('Description', $option->getDescription()); | |||||
| $this->assertEquals(42, $option->getArgument()->getDefaultValue()); | |||||
| break; | |||||
| case 'b': | |||||
| $this->assertEquals('beta', $option->long()); | |||||
| $this->assertEquals(Getopt::NO_ARGUMENT, $option->mode()); | |||||
| $this->assertEquals('', $option->getDescription()); | |||||
| break; | |||||
| case 'c': | |||||
| $this->assertNull($option->long()); | |||||
| $this->assertEquals(Getopt::REQUIRED_ARGUMENT, $option->mode()); | |||||
| $this->assertEquals('', $option->getDescription()); | |||||
| $this->assertFalse($option->getArgument()->hasDefaultValue()); | |||||
| break; | |||||
| default: | |||||
| $this->fail('Unexpected option: '.$option->short()); | |||||
| } | |||||
| } | |||||
| } | |||||
| public function testParseArrayEmpty() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| $this->parser->parseArray(array()); | |||||
| } | |||||
| public function testParseArrayInvalid() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| $this->parser->parseArray(array('a', 'b')); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,72 @@ | |||||
| <?php | |||||
| namespace Ulrichsg\Getopt; | |||||
| class OptionTest extends \PHPUnit_Framework_TestCase | |||||
| { | |||||
| public function testConstruct() | |||||
| { | |||||
| $option = new Option('a', 'az-AZ09_', Getopt::OPTIONAL_ARGUMENT); | |||||
| $this->assertEquals('a', $option->short()); | |||||
| $this->assertEquals('az-AZ09_', $option->long()); | |||||
| $this->assertEquals(Getopt::OPTIONAL_ARGUMENT, $option->mode()); | |||||
| } | |||||
| public function testConstructEmptyOption() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| new Option(null, null, Getopt::NO_ARGUMENT); | |||||
| } | |||||
| public function testConstructNoLetter() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| new Option('?', null, Getopt::NO_ARGUMENT); | |||||
| } | |||||
| public function testConstructInvalidCharacter() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| new Option(null, 'öption', Getopt::NO_ARGUMENT); | |||||
| } | |||||
| public function testConstructInvalidArgumentType() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| new Option('a', null, 'no_argument'); | |||||
| } | |||||
| public function testConstructLongOptionTooShort() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| new Option(null, 'a', Getopt::REQUIRED_ARGUMENT); | |||||
| } | |||||
| public function testSetArgument() | |||||
| { | |||||
| $option = new Option('a', null, Getopt::OPTIONAL_ARGUMENT); | |||||
| $this->assertEquals($option, $option->setArgument(new Argument())); | |||||
| $this->assertInstanceof('Ulrichsg\Getopt\Argument', $option->getArgument()); | |||||
| } | |||||
| public function testSetArgumentWrongMode() | |||||
| { | |||||
| $this->setExpectedException('InvalidArgumentException'); | |||||
| $option = new Option('a', null, Getopt::NO_ARGUMENT); | |||||
| $option->setArgument(new Argument()); | |||||
| } | |||||
| public function testSetDefaultValue() | |||||
| { | |||||
| $option = new Option('a', null, Getopt::OPTIONAL_ARGUMENT); | |||||
| $this->assertEquals($option, $option->setDefaultValue(10)); | |||||
| $this->assertEquals(10, $option->getArgument()->getDefaultValue()); | |||||
| } | |||||
| public function testSetValidation() | |||||
| { | |||||
| $option = new Option('a', null, Getopt::OPTIONAL_ARGUMENT); | |||||
| $this->assertEquals($option, $option->setValidation('is_numeric')); | |||||
| $this->assertTrue($option->getArgument()->hasValidation()); | |||||
| } | |||||
| } | |||||