From 7d4a9baa6d9fc397b1b7e40aeeae75438503cf66 Mon Sep 17 00:00:00 2001 From: wangzeyan <258785420@qq.com> Date: Fri, 23 May 2025 10:59:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=BF=BD=E7=95=A5=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/core/base/BaseAdminController.php | 29 - niucloud/core/core/base/BaseAdminService.php | 31 - niucloud/core/core/base/BaseApiController.php | 29 - niucloud/core/core/base/BaseApiService.php | 31 - niucloud/core/core/base/BaseController.php | 96 - niucloud/core/core/base/BaseCoreService.php | 27 - niucloud/core/core/base/BaseJob.php | 61 - niucloud/core/core/base/BaseModel.php | 48 - niucloud/core/core/base/BaseService.php | 135 - niucloud/core/core/base/BaseValidate.php | 46 - niucloud/core/core/dict/AdvPosition.php | 38 - niucloud/core/core/dict/BaseDict.php | 162 - niucloud/core/core/dict/Config.php | 41 - niucloud/core/core/dict/Console.php | 45 - niucloud/core/core/dict/DictLoader.php | 41 - niucloud/core/core/dict/DiyFormComponent.php | 38 - niucloud/core/core/dict/DiyFormTemplate.php | 38 - niucloud/core/core/dict/DiyFormType.php | 38 - niucloud/core/core/dict/Event.php | 42 - niucloud/core/core/dict/GrowthRule.php | 45 - niucloud/core/core/dict/Icon.php | 50 - niucloud/core/core/dict/Lang.php | 56 - .../core/dict/MemberAccountChangeType.php | 46 - niucloud/core/core/dict/MemberBenefits.php | 45 - niucloud/core/core/dict/MemberGift.php | 45 - niucloud/core/core/dict/Menu.php | 29 - niucloud/core/core/dict/Notice.php | 43 - niucloud/core/core/dict/PackageGift.php | 1 - niucloud/core/core/dict/PointRule.php | 45 - niucloud/core/core/dict/Poster.php | 95 - niucloud/core/core/dict/Printer.php | 40 - niucloud/core/core/dict/RechargeGift.php | 43 - niucloud/core/core/dict/Route.php | 33 - niucloud/core/core/dict/Schedule.php | 60 - niucloud/core/core/dict/UniappComponent.php | 38 - niucloud/core/core/dict/UniappLink.php | 75 - niucloud/core/core/dict/UniappPages.php | 52 - niucloud/core/core/dict/UniappTemplate.php | 95 - niucloud/core/core/dict/WebLink.php | 75 - .../core/core/exception/AddonException.php | 17 - .../core/core/exception/AdminException.php | 17 - niucloud/core/core/exception/ApiException.php | 18 - .../core/core/exception/AuthException.php | 18 - .../core/core/exception/CaptchaException.php | 18 - .../core/core/exception/CommonException.php | 18 - .../core/core/exception/NiucloudException.php | 18 - .../core/core/exception/NoticeException.php | 18 - niucloud/core/core/exception/PayException.php | 18 - .../core/core/exception/ServerException.php | 18 - .../core/exception/UploadFileException.php | 18 - .../core/core/exception/WechatException.php | 18 - niucloud/core/core/job/Dispatch.php | 57 - niucloud/core/core/loader/Loader.php | 118 - niucloud/core/core/loader/Storage.php | 69 - niucloud/core/core/oauth/BaseOauth.php | 42 - niucloud/core/core/oauth/OauthLoader.php | 38 - niucloud/core/core/oauth/Weapp.php | 32 - niucloud/core/core/oauth/Wechat.php | 40 - niucloud/core/core/pay/Alipay.php | 389 -- niucloud/core/core/pay/BasePay.php | 203 - niucloud/core/core/pay/PayLoader.php | 42 - niucloud/core/core/pay/Wechatpay.php | 538 --- niucloud/core/core/poster/BasePoster.php | 41 - niucloud/core/core/poster/Poster.php | 205 - niucloud/core/core/poster/PosterLoader.php | 42 - niucloud/core/core/printer/BasePrinter.php | 39 - niucloud/core/core/printer/KdniaoPrinter.php | 37 - niucloud/core/core/printer/PrinterLoader.php | 39 - .../core/printer/sdk/yilianyun/Autoloader.php | 32 - .../sdk/yilianyun/api/ExpressPrintService.php | 36 - .../sdk/yilianyun/api/OauthService.php | 22 - .../sdk/yilianyun/api/PicturePrintService.php | 22 - .../sdk/yilianyun/api/PrintMenuService.php | 19 - .../sdk/yilianyun/api/PrintService.php | 20 - .../sdk/yilianyun/api/PrinterService.php | 313 -- .../printer/sdk/yilianyun/api/RpcService.php | 19 - .../sdk/yilianyun/config/YlyConfig.php | 68 - .../demo/authorization_code_mode/callback.php | 141 - .../yilianyun/demo/client_mode/callback.php | 136 - .../core/printer/sdk/yilianyun/demo/index.php | 11 - .../core/printer/sdk/yilianyun/demo/init.php | 15 - .../sdk/yilianyun/oauth/YlyOauthClient.php | 152 - .../sdk/yilianyun/protocol/YlyRpcClient.php | 104 - niucloud/core/core/sms/Aliyun.php | 98 - niucloud/core/core/sms/BaseSms.php | 83 - niucloud/core/core/sms/SmsLoader.php | 44 - niucloud/core/core/sms/Tencent.php | 106 - niucloud/core/core/template/BaseTemplate.php | 60 - .../core/core/template/TemplateLoader.php | 47 - niucloud/core/core/template/Weapp.php | 93 - niucloud/core/core/template/Wechat.php | 111 - niucloud/core/core/upload/Aliyun.php | 133 - niucloud/core/core/upload/BaseUpload.php | 240 -- niucloud/core/core/upload/Local.php | 253 -- niucloud/core/core/upload/Qiniu.php | 180 - niucloud/core/core/upload/Tencent.php | 195 - niucloud/core/core/upload/UploadLoader.php | 44 - niucloud/core/core/util/Barcode.php | 74 - niucloud/core/core/util/DbBackup.php | 532 --- niucloud/core/core/util/QRcode.php | 3312 ----------------- niucloud/core/core/util/Queue.php | 251 -- niucloud/core/core/util/Snowflake.php | 91 - niucloud/core/core/util/Terminal.php | 56 - niucloud/core/core/util/TokenAuth.php | 109 - .../barcode/class/BCGArgumentException.php | 25 - .../core/util/barcode/class/BCGBarcode.php | 436 --- .../core/util/barcode/class/BCGBarcode1D.php | 259 -- .../core/core/util/barcode/class/BCGColor.php | 154 - .../util/barcode/class/BCGDrawException.php | 21 - .../core/util/barcode/class/BCGDrawing.php | 248 -- .../core/core/util/barcode/class/BCGFont.php | 23 - .../core/util/barcode/class/BCGFontFile.php | 209 -- .../core/util/barcode/class/BCGFontPhp.php | 153 - .../core/core/util/barcode/class/BCGLabel.php | 320 -- .../util/barcode/class/BCGParseException.php | 25 - .../util/barcode/class/BCGcodabar.barcode.php | 122 - .../util/barcode/class/BCGcode11.barcode.php | 185 - .../util/barcode/class/BCGcode128.barcode.php | 885 ----- .../util/barcode/class/BCGcode39.barcode.php | 193 - .../class/BCGcode39extended.barcode.php | 208 -- .../util/barcode/class/BCGcode93.barcode.php | 301 -- .../util/barcode/class/BCGean13.barcode.php | 322 -- .../util/barcode/class/BCGean8.barcode.php | 244 -- .../util/barcode/class/BCGgs1128.barcode.php | 679 ---- .../util/barcode/class/BCGi25.barcode.php | 203 - .../class/BCGintelligentmail.barcode.php | 649 ---- .../util/barcode/class/BCGisbn.barcode.php | 164 - .../util/barcode/class/BCGmsi.barcode.php | 184 - .../barcode/class/BCGothercode.barcode.php | 88 - .../util/barcode/class/BCGpostnet.barcode.php | 138 - .../util/barcode/class/BCGs25.barcode.php | 170 - .../util/barcode/class/BCGupca.barcode.php | 146 - .../util/barcode/class/BCGupce.barcode.php | 336 -- .../util/barcode/class/BCGupcext2.barcode.php | 138 - .../util/barcode/class/BCGupcext5.barcode.php | 200 - .../core/core/util/barcode/class/JoinDraw.php | 194 - .../util/barcode/class/drawer/BCGDraw.php | 38 - .../util/barcode/class/drawer/BCGDrawJPG.php | 102 - .../util/barcode/class/drawer/BCGDrawPNG.php | 202 - .../core/core/util/barcode/font/Arial.ttf | Bin 311636 -> 0 bytes .../core/util/niucloud/BaseNiucloudClient.php | 309 -- .../core/core/util/niucloud/CloudService.php | 37 - .../core/util/niucloud/http/AccessToken.php | 73 - .../util/niucloud/http/HasHttpRequests.php | 183 - .../core/core/util/niucloud/http/Response.php | 95 - .../core/core/util/niucloud/http/Token.php | 81 - .../core/core/util/niucloud/support/XML.php | 155 - 147 files changed, 20331 deletions(-) delete mode 100644 niucloud/core/core/base/BaseAdminController.php delete mode 100644 niucloud/core/core/base/BaseAdminService.php delete mode 100644 niucloud/core/core/base/BaseApiController.php delete mode 100644 niucloud/core/core/base/BaseApiService.php delete mode 100644 niucloud/core/core/base/BaseController.php delete mode 100644 niucloud/core/core/base/BaseCoreService.php delete mode 100644 niucloud/core/core/base/BaseJob.php delete mode 100644 niucloud/core/core/base/BaseModel.php delete mode 100644 niucloud/core/core/base/BaseService.php delete mode 100644 niucloud/core/core/base/BaseValidate.php delete mode 100644 niucloud/core/core/dict/AdvPosition.php delete mode 100644 niucloud/core/core/dict/BaseDict.php delete mode 100644 niucloud/core/core/dict/Config.php delete mode 100644 niucloud/core/core/dict/Console.php delete mode 100644 niucloud/core/core/dict/DictLoader.php delete mode 100644 niucloud/core/core/dict/DiyFormComponent.php delete mode 100644 niucloud/core/core/dict/DiyFormTemplate.php delete mode 100644 niucloud/core/core/dict/DiyFormType.php delete mode 100644 niucloud/core/core/dict/Event.php delete mode 100644 niucloud/core/core/dict/GrowthRule.php delete mode 100644 niucloud/core/core/dict/Icon.php delete mode 100644 niucloud/core/core/dict/Lang.php delete mode 100644 niucloud/core/core/dict/MemberAccountChangeType.php delete mode 100644 niucloud/core/core/dict/MemberBenefits.php delete mode 100644 niucloud/core/core/dict/MemberGift.php delete mode 100644 niucloud/core/core/dict/Menu.php delete mode 100644 niucloud/core/core/dict/Notice.php delete mode 100644 niucloud/core/core/dict/PackageGift.php delete mode 100644 niucloud/core/core/dict/PointRule.php delete mode 100644 niucloud/core/core/dict/Poster.php delete mode 100644 niucloud/core/core/dict/Printer.php delete mode 100644 niucloud/core/core/dict/RechargeGift.php delete mode 100644 niucloud/core/core/dict/Route.php delete mode 100644 niucloud/core/core/dict/Schedule.php delete mode 100644 niucloud/core/core/dict/UniappComponent.php delete mode 100644 niucloud/core/core/dict/UniappLink.php delete mode 100644 niucloud/core/core/dict/UniappPages.php delete mode 100644 niucloud/core/core/dict/UniappTemplate.php delete mode 100644 niucloud/core/core/dict/WebLink.php delete mode 100644 niucloud/core/core/exception/AddonException.php delete mode 100644 niucloud/core/core/exception/AdminException.php delete mode 100644 niucloud/core/core/exception/ApiException.php delete mode 100644 niucloud/core/core/exception/AuthException.php delete mode 100644 niucloud/core/core/exception/CaptchaException.php delete mode 100644 niucloud/core/core/exception/CommonException.php delete mode 100644 niucloud/core/core/exception/NiucloudException.php delete mode 100644 niucloud/core/core/exception/NoticeException.php delete mode 100644 niucloud/core/core/exception/PayException.php delete mode 100644 niucloud/core/core/exception/ServerException.php delete mode 100644 niucloud/core/core/exception/UploadFileException.php delete mode 100644 niucloud/core/core/exception/WechatException.php delete mode 100644 niucloud/core/core/job/Dispatch.php delete mode 100644 niucloud/core/core/loader/Loader.php delete mode 100644 niucloud/core/core/loader/Storage.php delete mode 100644 niucloud/core/core/oauth/BaseOauth.php delete mode 100644 niucloud/core/core/oauth/OauthLoader.php delete mode 100644 niucloud/core/core/oauth/Weapp.php delete mode 100644 niucloud/core/core/oauth/Wechat.php delete mode 100644 niucloud/core/core/pay/Alipay.php delete mode 100644 niucloud/core/core/pay/BasePay.php delete mode 100644 niucloud/core/core/pay/PayLoader.php delete mode 100644 niucloud/core/core/pay/Wechatpay.php delete mode 100644 niucloud/core/core/poster/BasePoster.php delete mode 100644 niucloud/core/core/poster/Poster.php delete mode 100644 niucloud/core/core/poster/PosterLoader.php delete mode 100644 niucloud/core/core/printer/BasePrinter.php delete mode 100644 niucloud/core/core/printer/KdniaoPrinter.php delete mode 100644 niucloud/core/core/printer/PrinterLoader.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/Autoloader.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/api/ExpressPrintService.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/api/OauthService.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/api/PicturePrintService.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/api/PrintMenuService.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/api/PrintService.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/api/PrinterService.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/api/RpcService.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/config/YlyConfig.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/demo/authorization_code_mode/callback.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/demo/client_mode/callback.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/demo/index.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/demo/init.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/oauth/YlyOauthClient.php delete mode 100644 niucloud/core/core/printer/sdk/yilianyun/protocol/YlyRpcClient.php delete mode 100644 niucloud/core/core/sms/Aliyun.php delete mode 100644 niucloud/core/core/sms/BaseSms.php delete mode 100644 niucloud/core/core/sms/SmsLoader.php delete mode 100644 niucloud/core/core/sms/Tencent.php delete mode 100644 niucloud/core/core/template/BaseTemplate.php delete mode 100644 niucloud/core/core/template/TemplateLoader.php delete mode 100644 niucloud/core/core/template/Weapp.php delete mode 100644 niucloud/core/core/template/Wechat.php delete mode 100644 niucloud/core/core/upload/Aliyun.php delete mode 100644 niucloud/core/core/upload/BaseUpload.php delete mode 100644 niucloud/core/core/upload/Local.php delete mode 100644 niucloud/core/core/upload/Qiniu.php delete mode 100644 niucloud/core/core/upload/Tencent.php delete mode 100644 niucloud/core/core/upload/UploadLoader.php delete mode 100644 niucloud/core/core/util/Barcode.php delete mode 100644 niucloud/core/core/util/DbBackup.php delete mode 100644 niucloud/core/core/util/QRcode.php delete mode 100644 niucloud/core/core/util/Queue.php delete mode 100644 niucloud/core/core/util/Snowflake.php delete mode 100644 niucloud/core/core/util/Terminal.php delete mode 100644 niucloud/core/core/util/TokenAuth.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGArgumentException.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGBarcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGBarcode1D.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGColor.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGDrawException.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGDrawing.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGFont.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGFontFile.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGFontPhp.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGLabel.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGParseException.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGcodabar.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGcode11.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGcode128.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGcode39.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGcode39extended.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGcode93.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGean13.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGean8.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGgs1128.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGi25.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGintelligentmail.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGisbn.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGmsi.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGothercode.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGpostnet.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGs25.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGupca.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGupce.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGupcext2.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/BCGupcext5.barcode.php delete mode 100644 niucloud/core/core/util/barcode/class/JoinDraw.php delete mode 100644 niucloud/core/core/util/barcode/class/drawer/BCGDraw.php delete mode 100644 niucloud/core/core/util/barcode/class/drawer/BCGDrawJPG.php delete mode 100644 niucloud/core/core/util/barcode/class/drawer/BCGDrawPNG.php delete mode 100644 niucloud/core/core/util/barcode/font/Arial.ttf delete mode 100644 niucloud/core/core/util/niucloud/BaseNiucloudClient.php delete mode 100644 niucloud/core/core/util/niucloud/CloudService.php delete mode 100644 niucloud/core/core/util/niucloud/http/AccessToken.php delete mode 100644 niucloud/core/core/util/niucloud/http/HasHttpRequests.php delete mode 100644 niucloud/core/core/util/niucloud/http/Response.php delete mode 100644 niucloud/core/core/util/niucloud/http/Token.php delete mode 100644 niucloud/core/core/util/niucloud/support/XML.php diff --git a/niucloud/core/core/base/BaseAdminController.php b/niucloud/core/core/base/BaseAdminController.php deleted file mode 100644 index e9ec2b7c..00000000 --- a/niucloud/core/core/base/BaseAdminController.php +++ /dev/null @@ -1,29 +0,0 @@ -username = $this->request->username(); - $this->uid = $this->request->uid(); - } -} diff --git a/niucloud/core/core/base/BaseApiController.php b/niucloud/core/core/base/BaseApiController.php deleted file mode 100644 index 6fac93f0..00000000 --- a/niucloud/core/core/base/BaseApiController.php +++ /dev/null @@ -1,29 +0,0 @@ -member_id = $this->request->memberId(); - $this->channel = $this->request->getChannel(); - } -} \ No newline at end of file diff --git a/niucloud/core/core/base/BaseController.php b/niucloud/core/core/base/BaseController.php deleted file mode 100644 index 793b992b..00000000 --- a/niucloud/core/core/base/BaseController.php +++ /dev/null @@ -1,96 +0,0 @@ -app = $app; - $this->request = $this->app->request; - // 控制器初始化 - $this->initialize(); - } - - // 初始化 - protected function initialize() - { - } - - /** - * 验证数据 - * @access protected - * @param array $data 数据 - * @param string|array $validate 验证器名或者验证规则数组 - * @param array $message 提示信息 - * @param bool $batch 是否批量验证 - * @return array|string|true - * @throws ValidateException - */ - protected function validate(array $data, $validate, array $message = [], bool $batch = false) - { - if (is_array($validate)) { - $v = new Validate(); - $v->rule($validate); - } else { - if (strpos($validate, '.')) { - // 支持场景 - [$validate, $scene] = explode('.', $validate); - } - $class = str_contains($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate); - $v = new $class(); - if (!empty($scene)) { - $v->scene($scene); - } - } - - $v->message($message); - - // 是否批量验证 - if ($batch || $this->batchValidate) { - $v->batch(); - } - - return $v->failException()->check($data); - } - - -} diff --git a/niucloud/core/core/base/BaseCoreService.php b/niucloud/core/core/base/BaseCoreService.php deleted file mode 100644 index 8f152c27..00000000 --- a/niucloud/core/core/base/BaseCoreService.php +++ /dev/null @@ -1,27 +0,0 @@ -runJob($method, $data); - } - - - /** - * 执行任务 - * @param string $method - * @param array $data - * @param int $error_count - */ - protected function runJob(string $method, array $data) - { - try { - $method = method_exists($this, $method) ? $method : 'handle'; - if (!method_exists($this, $method)) { - throw new CommonException('Job "'.static::class.'" not found!'); - } - $this->{$method}(...$data); - return true; - } catch (\Throwable $e) { - Log::write('队列错误:'.static::class.$method.'_'.'_'.$e->getMessage().'_'.$e->getFile().'_'.$e->getLine()); - throw new CommonException('Job "'.static::class.'" has error!'); - } - - } - -} diff --git a/niucloud/core/core/base/BaseModel.php b/niucloud/core/core/base/BaseModel.php deleted file mode 100644 index dbf71c86..00000000 --- a/niucloud/core/core/base/BaseModel.php +++ /dev/null @@ -1,48 +0,0 @@ -getTable(); - $sql = 'SHOW TABLE STATUS WHERE 1=1 '; - $tablePrefix = config('database.connections.mysql.prefix'); - if (!empty($table_name)) { - $sql .= "AND name='" .$table_name."'"; - } - $tables = Db::query($sql); - $table_info = $tables[0] ?? []; - $table_name = preg_replace("/^{$tablePrefix}/", '', $table_info['Name'], 1); - return Db::name($table_name)->getFields(); - } - - /** - * 处理搜索条件特殊字符(%、_) - * @param $value - */ - public function handelSpecialCharacter($value) - { - $value = str_replace('%', '\%', str_replace('_', '\_', $value)); - return $value; - } -} diff --git a/niucloud/core/core/base/BaseService.php b/niucloud/core/core/base/BaseService.php deleted file mode 100644 index d3f1ecb7..00000000 --- a/niucloud/core/core/base/BaseService.php +++ /dev/null @@ -1,135 +0,0 @@ -request = request(); - } - - /** - * 分页列表参数(页码和每页多少条) - * @return mixed - */ - public function getPageParam() - { - - $page = request()->params([ - ['page', 1], - ['limit', 15] - ]); - validate(Page::class) - ->check($page); - return $page; - } - - /** - * 分页列表 - * @param Model $model - * @param array $where - * @param string $field - * @param string $order - * @param array $append - * @return array - * @throws DbException - */ - public function getPageList(Model $model, array $where, string $field = '*', string $order = '', array $append = [], $with = null, $each = null) - { - $page_params = $this->getPageParam(); - $page = $page_params['page']; - $limit = $page_params['limit']; - - $list = $model->where($where)->when($append, function ($query) use ($append) { - $query->append($append); - })->when($with, function ($query) use ($with) { - $query->with($with); - })->field($field)->order($order)->paginate([ - 'list_rows' => $limit, - 'page' => $page, - ]); - if (!empty($each)) { - $list = $list->each($each); - } - return $list->toArray(); - } - - /** - * 分页数据查询,传入model(查询后结果) - * @param $model BaseModel - * @return array - * @throws DbException - */ - public function pageQuery($model, $each = null) - { - $page_params = $this->getPageParam(); - $page = $page_params['page']; - $limit = $page_params['limit']; - $list = $model->paginate([ - 'list_rows' => $limit, - 'page' => $page, - ]); - if (!empty($each)) { - $list = $list->each($each); - } - return $list->toArray(); - } - - /** - * 分页视图列表查询 - * @param Model $model - * @param array $where - * @param string $field - * @param string $order - * @param array $append - * @return array - * @throws DbException - */ - public function getPageViewList(Model $model, array $where, string $field = '*', string $order = '', array $append = [], $with = null, $each = null) - { - $page_params = $this->getPageParam(); - $page = $page_params['page']; - $limit = $page_params['limit']; - - $list = $model->where($where)->when($append, function ($query) use ($append) { - $query->append($append); - })->when($with, function ($query) use ($with) { - $query->withJoin($with); - })->field($field)->order($order)->paginate([ - 'list_rows' => $limit, - 'page' => $page, - ]); - if (!empty($each)) { - $list = $list->each($each); - } - return $list->toArray(); - } - -} \ No newline at end of file diff --git a/niucloud/core/core/base/BaseValidate.php b/niucloud/core/core/base/BaseValidate.php deleted file mode 100644 index 34a2b0a5..00000000 --- a/niucloud/core/core/base/BaseValidate.php +++ /dev/null @@ -1,46 +0,0 @@ -parseMsg(); - } - - public function parseMsg(){ - if(!empty($this->message)) - { - foreach ($this->message as $key => $value) - { - if(is_array($value)) - { - $this->message[$key] = get_lang($value[0], $value[1]); - } - } - } - - } - -} diff --git a/niucloud/core/core/dict/AdvPosition.php b/niucloud/core/core/dict/AdvPosition.php deleted file mode 100644 index 188726bb..00000000 --- a/niucloud/core/core/dict/AdvPosition.php +++ /dev/null @@ -1,38 +0,0 @@ -getLocalAddons(); - $adv_position_files = []; - foreach ($addons as $v) { - $adv_position_path = $this->getAddonDictPath($v) . "web" . DIRECTORY_SEPARATOR . "adv_position.php"; - if (is_file($adv_position_path)) { - $adv_position_files[] = $adv_position_path; - } - } - $adv_position_file_data = $this->loadFiles($adv_position_files); - $adv_position = $data; - foreach ($adv_position_file_data as $file_data) { - $adv_position = empty($adv_position) ? $file_data : array_merge($adv_position, $file_data); - } - return $adv_position; - } -} diff --git a/niucloud/core/core/dict/BaseDict.php b/niucloud/core/core/dict/BaseDict.php deleted file mode 100644 index 75cdc603..00000000 --- a/niucloud/core/core/dict/BaseDict.php +++ /dev/null @@ -1,162 +0,0 @@ -column("key"); - Cache::tag(CoreAddonBaseService::$cache_tag_name)->set("local_install_addons", $addons); - - return $addons; - } - - /** - * 获取所有本地插件(包括未安装,用于系统指令执行) - * @return array|false - */ - public function getAllLocalAddons() - { - $addon_dir = root_path() . 'addon'; - $addons = array_diff(scandir($addon_dir), ['.', '..']); - return $addons; - } - - /** - * 获取插件目录 - * @param string $addon - * @return string - */ - protected function getAddonPath(string $addon) - { - return root_path() . 'addon' . DIRECTORY_SEPARATOR . $addon . DIRECTORY_SEPARATOR; - - } - - /** - * 获取系统整体app目录 - * @return string - */ - protected function getAppPath() - { - return root_path() . "app" . DIRECTORY_SEPARATOR; - } - - /** - * 获取插件对应app目录 - * @param string $addon - * @return string - */ - protected function getAddonAppPath(string $addon) - { - return $this->getAddonPath($addon) . "app" . DIRECTORY_SEPARATOR; - } - - /** - *获取系统dict path - */ - protected function getDictPath() - { - return root_path() . 'app' . DIRECTORY_SEPARATOR . 'dict' . DIRECTORY_SEPARATOR; - } - - /** - *获取插件对应的dict目录 - * @param string $addon - * @return string - */ - protected function getAddonDictPath(string $addon) - { - return $this->getAddonPath($addon) . 'app' . DIRECTORY_SEPARATOR . 'dict' . DIRECTORY_SEPARATOR; - } - - /** - *获取插件对应的config目录 - * @param string $addon - * @return string - */ - protected function getAddonConfigPath(string $addon) - { - return $this->getAddonPath($addon) . 'config' . DIRECTORY_SEPARATOR; - } - - /** - * 加载文件数据 - * @param $files - * @return array - */ - protected function loadFiles($files) - { - $default_sort = 100000; - $files_data = []; - if (!empty($files)) { - foreach ($files as $file) { - $config = include $file; - if (!empty($config)) { - if (isset($config['file_sort'])) { - $sort = $config['file_sort']; - unset($config['file_sort']); - $sort = $sort * 10; - while (array_key_exists($sort, $files_data)) { - $sort++; - } - $files_data[$sort] = $config; - } else { - $files_data[$default_sort] = $config; - $default_sort++; - } - } - } - } - ksort($files_data); - return $files_data; - } - - /** - * 加载 - * @return mixed - */ - abstract public function load(array $data); -} diff --git a/niucloud/core/core/dict/Config.php b/niucloud/core/core/dict/Config.php deleted file mode 100644 index d7f404fd..00000000 --- a/niucloud/core/core/dict/Config.php +++ /dev/null @@ -1,41 +0,0 @@ -getAllLocalAddons(); - $config_files = []; - - foreach ($addons as $v) { - $config_path = $this->getAddonAppPath($v) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . $config . '.php'; - if (is_file($config_path)) { - $config_files[] = $config_path; - } - } - $files_data = $this->loadFiles($config_files); - - foreach ($files_data as $file_data) { - if(!empty($file_data)) - { - $system_config = empty($system_config) ? $file_data : array_merge2($system_config, $file_data); - } - - } - return $system_config; - } -} diff --git a/niucloud/core/core/dict/Console.php b/niucloud/core/core/dict/Console.php deleted file mode 100644 index 3fed813d..00000000 --- a/niucloud/core/core/dict/Console.php +++ /dev/null @@ -1,45 +0,0 @@ -getAllLocalAddons(); - $console_files = []; - - foreach ($addons as $v) { - $console_path = $this->getAddonAppPath($v) . "/config/console.php"; - if (is_file($console_path)) { - $console_files[] = $console_path; - } - } - $files_data = $this->loadFiles($console_files); - - - $console = $data; - foreach ($files_data as $file_data) { - if(!empty($file_data)) - { - $console = empty($console) ? $file_data : array_merge2($console, $file_data); - } - - } - return $console; - } -} diff --git a/niucloud/core/core/dict/DictLoader.php b/niucloud/core/core/dict/DictLoader.php deleted file mode 100644 index 8e3e5232..00000000 --- a/niucloud/core/core/dict/DictLoader.php +++ /dev/null @@ -1,41 +0,0 @@ -getLocalAddons(); - $components_files = []; - - foreach ($addons as $v) { - $components_path = $this->getAddonDictPath($v) . "diy_form" . DIRECTORY_SEPARATOR . "components.php"; - if (is_file($components_path)) { - $components_files[] = $components_path; - } - } - $components_files_data = $this->loadFiles($components_files); - $components = $data; - foreach ($components_files_data as $file_data) { - $components = empty($components) ? $file_data : array_merge2($components, $file_data); - } - return $components; - } -} diff --git a/niucloud/core/core/dict/DiyFormTemplate.php b/niucloud/core/core/dict/DiyFormTemplate.php deleted file mode 100644 index 5ac2e130..00000000 --- a/niucloud/core/core/dict/DiyFormTemplate.php +++ /dev/null @@ -1,38 +0,0 @@ -getLocalAddons(); - $components_files = []; - - foreach ($addons as $v) { - $components_path = $this->getAddonDictPath($v) . "diy_form" . DIRECTORY_SEPARATOR . "template.php"; - if (is_file($components_path)) { - $components_files[] = $components_path; - } - } - $components_files_data = $this->loadFiles($components_files); - $components = $data; - foreach ($components_files_data as $file_data) { - $components = empty($components) ? $file_data : array_merge2($components, $file_data); - } - return $components; - } -} diff --git a/niucloud/core/core/dict/DiyFormType.php b/niucloud/core/core/dict/DiyFormType.php deleted file mode 100644 index 7b0caab5..00000000 --- a/niucloud/core/core/dict/DiyFormType.php +++ /dev/null @@ -1,38 +0,0 @@ -getLocalAddons(); - $components_files = []; - - foreach ($addons as $v) { - $components_path = $this->getAddonDictPath($v) . "diy_form" . DIRECTORY_SEPARATOR . "type.php"; - if (is_file($components_path)) { - $components_files[] = $components_path; - } - } - $components_files_data = $this->loadFiles($components_files); - $components = $data; - foreach ($components_files_data as $file_data) { - $components = empty($components) ? $file_data : array_merge2($components, $file_data); - } - return $components; - } -} diff --git a/niucloud/core/core/dict/Event.php b/niucloud/core/core/dict/Event.php deleted file mode 100644 index e9eb7d07..00000000 --- a/niucloud/core/core/dict/Event.php +++ /dev/null @@ -1,42 +0,0 @@ -getLocalAddons(); - $event_files = []; - - foreach ($addons as $v) { - $event_path = $this->getAddonAppPath($v) . "event.php"; - if (is_file($event_path)) { - $event_files[] = $event_path; - } - } - $files_data = $this->loadFiles($event_files); - - $files_data[1] = $data; - - $events = []; - foreach ($files_data as $file_data) { - $events = empty($events) ? $file_data : array_merge2($events, $file_data); - } - return $events; - } -} diff --git a/niucloud/core/core/dict/GrowthRule.php b/niucloud/core/core/dict/GrowthRule.php deleted file mode 100644 index 44faa3b3..00000000 --- a/niucloud/core/core/dict/GrowthRule.php +++ /dev/null @@ -1,45 +0,0 @@ -getLocalAddons(); - $account_change_type_files = []; - $system_change_type_file = $this->getDictPath() . "member" . DIRECTORY_SEPARATOR . "growth_rule.php"; - - - if (is_file($system_change_type_file)) { - $account_change_type_files[] = $system_change_type_file; - } - foreach ($addons as $v) { - $addon_change_type_file = $this->getAddonDictPath($v) . "member" . DIRECTORY_SEPARATOR . "growth_rule.php"; - if (is_file($addon_change_type_file)) { - $account_change_type_files[] = $addon_change_type_file; - } - } - - $account_change_type_datas = $this->loadFiles($account_change_type_files); - - $account_change_type_array = []; - foreach ($account_change_type_datas as $account_change_type_data) { - $account_change_type_array = empty($account_change_type_array) ? $account_change_type_data : array_merge2($account_change_type_array, $account_change_type_data); - } - return $account_change_type_array; - } -} diff --git a/niucloud/core/core/dict/Icon.php b/niucloud/core/core/dict/Icon.php deleted file mode 100644 index 499d14f2..00000000 --- a/niucloud/core/core/dict/Icon.php +++ /dev/null @@ -1,50 +0,0 @@ -getRootPath()) . str_replace('/', DIRECTORY_SEPARATOR, '/admin/src/styles/icon'); - $file_arr = getFileMap($sys_path); - $icon_arr = []; - if (!empty($file_arr)) { - foreach ($file_arr as $ck => $cv) { - if (str_contains($cv, '.json')) { - $json_string = file_get_contents($ck); - $icon = json_decode($json_string, true, 512, JSON_THROW_ON_ERROR); - $icon_arr[] = $icon; - } - } - } - - if (count($icon_arr) > 1) { - $last_icon = array_pop($icon_arr); // 最后一个 - $first_icon = array_shift($icon_arr); // 第一个 - - array_unshift($icon_arr, $last_icon); // 将系统图标放到第一位置 - $icon_arr[] = $first_icon; // 交换位置 - } - - return $icon_arr; - } -} diff --git a/niucloud/core/core/dict/Lang.php b/niucloud/core/core/dict/Lang.php deleted file mode 100644 index 40a4a0fc..00000000 --- a/niucloud/core/core/dict/Lang.php +++ /dev/null @@ -1,56 +0,0 @@ -getLocalAddons(); - $system_lang_path = $this->getAppPath() . "lang" . DIRECTORY_SEPARATOR . $data['lang_type'] . DIRECTORY_SEPARATOR; - $lang_files = [ - $system_lang_path . "api.php", - $system_lang_path . "dict.php", - $system_lang_path . "validate.php", - ]; - - - foreach ($addons as $v) { - $lang_path = $this->getAddonAppPath($v) . "lang" . DIRECTORY_SEPARATOR . $data['lang_type'] . DIRECTORY_SEPARATOR; - - $api_path = $lang_path . "api.php"; - $dict_path = $lang_path . "dict.php"; - $validate_path = $lang_path . "validate.php"; - if (is_file($api_path)) { - $lang_files[] = $api_path; - - } - if (is_file($dict_path)) { - $lang_files[] = $dict_path; - } - if (is_file($validate_path)) { - $lang_files[] = $validate_path; - } - } - $files_data = $this->loadFiles($lang_files); - $lang = []; - foreach ($files_data as $file_data) { - $lang = empty($lang) ? $file_data : array_merge2($lang, $file_data); - } - return $lang; - } -} diff --git a/niucloud/core/core/dict/MemberAccountChangeType.php b/niucloud/core/core/dict/MemberAccountChangeType.php deleted file mode 100644 index c7cf0ce8..00000000 --- a/niucloud/core/core/dict/MemberAccountChangeType.php +++ /dev/null @@ -1,46 +0,0 @@ -getLocalAddons(); - $account_change_type_files = []; - $system_change_type_file = $this->getDictPath() . "member" . DIRECTORY_SEPARATOR . "account_change_type.php"; - - - if (is_file($system_change_type_file)) { - $account_change_type_files[] = $system_change_type_file; - } - foreach ($addons as $v) { - $addon_change_type_file = $this->getAddonDictPath($v) . "member" . DIRECTORY_SEPARATOR . "account_change_type.php"; - if (is_file($addon_change_type_file)) { - $account_change_type_files[] = $addon_change_type_file; - } - } - - $account_change_type_datas = $this->loadFiles($account_change_type_files); - - $account_change_type_array = []; - foreach ($account_change_type_datas as $account_change_type_data) { - $account_change_type_array = empty($account_change_type_array) ? $account_change_type_data : array_merge2($account_change_type_array, $account_change_type_data); - } - return $account_change_type_array; - } -} diff --git a/niucloud/core/core/dict/MemberBenefits.php b/niucloud/core/core/dict/MemberBenefits.php deleted file mode 100644 index c22581fc..00000000 --- a/niucloud/core/core/dict/MemberBenefits.php +++ /dev/null @@ -1,45 +0,0 @@ -getLocalAddons(); - $account_change_type_files = []; - $system_change_type_file = $this->getDictPath() . "member" . DIRECTORY_SEPARATOR . "benefits.php"; - - - if (is_file($system_change_type_file)) { - $account_change_type_files[] = $system_change_type_file; - } - foreach ($addons as $v) { - $addon_change_type_file = $this->getAddonDictPath($v) . "member" . DIRECTORY_SEPARATOR . "benefits.php"; - if (is_file($addon_change_type_file)) { - $account_change_type_files[] = $addon_change_type_file; - } - } - - $account_change_type_datas = $this->loadFiles($account_change_type_files); - - $account_change_type_array = []; - foreach ($account_change_type_datas as $account_change_type_data) { - $account_change_type_array = empty($account_change_type_array) ? $account_change_type_data : array_merge2($account_change_type_array, $account_change_type_data); - } - return $account_change_type_array; - } -} diff --git a/niucloud/core/core/dict/MemberGift.php b/niucloud/core/core/dict/MemberGift.php deleted file mode 100644 index 1c8284fe..00000000 --- a/niucloud/core/core/dict/MemberGift.php +++ /dev/null @@ -1,45 +0,0 @@ -getLocalAddons(); - $account_change_type_files = []; - $system_change_type_file = $this->getDictPath() . "member" . DIRECTORY_SEPARATOR . "gift.php"; - - - if (is_file($system_change_type_file)) { - $account_change_type_files[] = $system_change_type_file; - } - foreach ($addons as $v) { - $addon_change_type_file = $this->getAddonDictPath($v) . "member" . DIRECTORY_SEPARATOR . "gift.php"; - if (is_file($addon_change_type_file)) { - $account_change_type_files[] = $addon_change_type_file; - } - } - - $account_change_type_datas = $this->loadFiles($account_change_type_files); - - $account_change_type_array = []; - foreach ($account_change_type_datas as $account_change_type_data) { - $account_change_type_array = empty($account_change_type_array) ? $account_change_type_data : array_merge2($account_change_type_array, $account_change_type_data); - } - return $account_change_type_array; - } -} diff --git a/niucloud/core/core/dict/Menu.php b/niucloud/core/core/dict/Menu.php deleted file mode 100644 index 519ccf2b..00000000 --- a/niucloud/core/core/dict/Menu.php +++ /dev/null @@ -1,29 +0,0 @@ -getAddonDictPath($data['addon']) . "menu" . DIRECTORY_SEPARATOR . $data['app_type'] . ".php"; - if (is_file($menu_path)) { - return include $menu_path; - } - return []; - } -} diff --git a/niucloud/core/core/dict/Notice.php b/niucloud/core/core/dict/Notice.php deleted file mode 100644 index 64f5a14e..00000000 --- a/niucloud/core/core/dict/Notice.php +++ /dev/null @@ -1,43 +0,0 @@ -getDictPath() . "notice" . DIRECTORY_SEPARATOR . $data[ 'type' ] . ".php"; - if (is_file($system_path)) { - $template_files[] = $system_path; - } - $addons = $this->getLocalAddons(); - foreach ($addons as $v) { - $template_path = $this->getAddonDictPath($v) . "notice" . DIRECTORY_SEPARATOR . $data[ 'type' ] . ".php"; - if (is_file($template_path)) { - $template_files[] = $template_path; - } - } - $template_files_data = $this->loadFiles($template_files); - - $template_data_array = []; - foreach ($template_files_data as $file_data) { - $template_data_array = empty($template_data_array) ? $file_data : array_merge($template_data_array, $file_data); - } - return $template_data_array; - } -} diff --git a/niucloud/core/core/dict/PackageGift.php b/niucloud/core/core/dict/PackageGift.php deleted file mode 100644 index f790da46..00000000 --- a/niucloud/core/core/dict/PackageGift.php +++ /dev/null @@ -1 +0,0 @@ -// | 官方网址:https://www.niucloud.com diff --git a/niucloud/core/core/dict/PointRule.php b/niucloud/core/core/dict/PointRule.php deleted file mode 100644 index cdfad3ef..00000000 --- a/niucloud/core/core/dict/PointRule.php +++ /dev/null @@ -1,45 +0,0 @@ -getLocalAddons(); - $account_change_type_files = []; - $system_change_type_file = $this->getDictPath() . "member" . DIRECTORY_SEPARATOR . "point_rule.php"; - - - if (is_file($system_change_type_file)) { - $account_change_type_files[] = $system_change_type_file; - } - foreach ($addons as $v) { - $addon_change_type_file = $this->getAddonDictPath($v) . "member" . DIRECTORY_SEPARATOR . "point_rule.php"; - if (is_file($addon_change_type_file)) { - $account_change_type_files[] = $addon_change_type_file; - } - } - - $account_change_type_datas = $this->loadFiles($account_change_type_files); - - $account_change_type_array = []; - foreach ($account_change_type_datas as $account_change_type_data) { - $account_change_type_array = empty($account_change_type_array) ? $account_change_type_data : array_merge2($account_change_type_array, $account_change_type_data); - } - return $account_change_type_array; - } -} diff --git a/niucloud/core/core/dict/Poster.php b/niucloud/core/core/dict/Poster.php deleted file mode 100644 index 1e6177af..00000000 --- a/niucloud/core/core/dict/Poster.php +++ /dev/null @@ -1,95 +0,0 @@ -getDictPath() . 'poster' . DIRECTORY_SEPARATOR . 'template.php'; - if (is_file($system_path)) { - $schedule_files[] = $system_path; - } - $addons = $this->getLocalAddons(); - foreach ($addons as $v) { - $addon_path = $this->getAddonDictPath($v) . 'poster' . DIRECTORY_SEPARATOR . 'template.php'; - if (is_file($addon_path)) { - $schedule_files[] = $addon_path; - } - } - } else { - $schedule_files = []; - if ($addon == 'system') { - $system_path = $this->getDictPath() . 'poster' . DIRECTORY_SEPARATOR . 'template.php'; - if (is_file($system_path)) { - $schedule_files[] = $system_path; - } - } else { - $addon_path = $this->getAddonDictPath($addon) . 'poster' . DIRECTORY_SEPARATOR . 'template.php'; - if (is_file($addon_path)) { - $schedule_files[] = $addon_path; - } - } - - } - - $schedule_files_data = $this->loadFiles($schedule_files); - $schedule_data_array = []; - foreach ($schedule_files_data as $file_data) { - $schedule_data_array = empty($schedule_data_array) ? $file_data : array_merge($schedule_data_array, $file_data); - } - - if (!empty($type)) { - foreach ($schedule_data_array as $k => $v) { - if ($v[ 'type' ] != $type) { - unset($schedule_data_array[ $k ]); - } - } - $schedule_data_array = array_values($schedule_data_array); - } - return $schedule_data_array; - - } - - /** - * 获取海报组件 - * @param array $data - * @return array|mixed - */ - public function loadComponents(array $data = []) - { - $addons = $this->getLocalAddons(); - $components_files = []; - foreach ($addons as $v) { - $components_path = $this->getAddonDictPath($v) . "poster" . DIRECTORY_SEPARATOR . "components.php"; - if (is_file($components_path)) { - $components_files[] = $components_path; - } - } - $components_files_data = $this->loadFiles($components_files); - $components = $data; - foreach ($components_files_data as $file_data) { - $components = empty($components) ? $file_data : array_merge2($components, $file_data); - } - return $components; - - } -} diff --git a/niucloud/core/core/dict/Printer.php b/niucloud/core/core/dict/Printer.php deleted file mode 100644 index 6e209edc..00000000 --- a/niucloud/core/core/dict/Printer.php +++ /dev/null @@ -1,40 +0,0 @@ -getLocalAddons(); - $types_files = []; - - foreach ($addons as $v) { - $types_path = $this->getAddonDictPath($v) . "printer" . DIRECTORY_SEPARATOR . "type.php"; - if (is_file($types_path)) { - $types_files[] = $types_path; - } - } - $types_files_data = $this->loadFiles($types_files); - $types = $data; - foreach ($types_files_data as $file_data) { - $types = empty($types) ? $file_data : array_merge2($types, $file_data); - } - return $types; - } -} diff --git a/niucloud/core/core/dict/RechargeGift.php b/niucloud/core/core/dict/RechargeGift.php deleted file mode 100644 index f3f1a78b..00000000 --- a/niucloud/core/core/dict/RechargeGift.php +++ /dev/null @@ -1,43 +0,0 @@ -getLocalAddons(); - foreach ($addons as $v) { - $addon_change_type_file = $this->getAddonDictPath($v) . "recharge" . DIRECTORY_SEPARATOR . "package_gift.php"; - if (is_file($addon_change_type_file)) { - $account_change_type_files[] = $addon_change_type_file; - } - } - $account_change_type_datas = $this->loadFiles($account_change_type_files); - $account_change_type_array = []; - foreach ($account_change_type_datas as $account_change_type_data) { - $account_change_type_array = empty($account_change_type_array) ? $account_change_type_data : array_merge2($account_change_type_array, $account_change_type_data); - } - foreach ($account_change_type_array as $key => &$value) { - $value[ 'key' ] = $key; - } - usort($account_change_type_array, function($list_one, $list_two) { - return $list_one[ 'sort' ] <=> $list_two[ 'sort' ]; - }); - return $account_change_type_array; - - } -} diff --git a/niucloud/core/core/dict/Route.php b/niucloud/core/core/dict/Route.php deleted file mode 100644 index b74d8941..00000000 --- a/niucloud/core/core/dict/Route.php +++ /dev/null @@ -1,33 +0,0 @@ -getLocalAddons(); - - foreach ($addons as $k => $v) { - $route_path = $this->getAddonAppPath($v) . DIRECTORY_SEPARATOR . $data['app_type'] . DIRECTORY_SEPARATOR . "route" . DIRECTORY_SEPARATOR . "route.php"; - if (is_file($route_path)) { - include $route_path; - } - } - return true; - } -} diff --git a/niucloud/core/core/dict/Schedule.php b/niucloud/core/core/dict/Schedule.php deleted file mode 100644 index eb824c58..00000000 --- a/niucloud/core/core/dict/Schedule.php +++ /dev/null @@ -1,60 +0,0 @@ -getDictPath() . 'schedule' . DIRECTORY_SEPARATOR . 'schedule.php'; - if (is_file($system_path)) { - $schedule_files[] = $system_path; - } - $addons = $this->getLocalAddons(); - foreach ($addons as $v) { - $addon_path = $this->getAddonDictPath($v) . 'schedule' . DIRECTORY_SEPARATOR . 'schedule.php'; - if (is_file($addon_path)) { - $schedule_files[] = $addon_path; - } - } - } else { - $schedule_files = []; - if ($addon == 'system') { - $system_path = $this->getDictPath() . 'schedule' . DIRECTORY_SEPARATOR . 'schedule.php'; - if (is_file($system_path)) { - $schedule_files[] = $system_path; - } - } else { - $addon_path = $this->getAddonDictPath($addon) . 'schedule' . DIRECTORY_SEPARATOR . 'schedule.php'; - if (is_file($addon_path)) { - $schedule_files[] = $addon_path; - } - } - - } - $schedule_files_data = $this->loadFiles($schedule_files); - $schedule_data_array = []; - foreach ($schedule_files_data as $file_data) { - $schedule_data_array = empty($schedule_data_array) ? $file_data : array_merge($schedule_data_array, $file_data); - } - return $schedule_data_array; - - } -} diff --git a/niucloud/core/core/dict/UniappComponent.php b/niucloud/core/core/dict/UniappComponent.php deleted file mode 100644 index 669b6c91..00000000 --- a/niucloud/core/core/dict/UniappComponent.php +++ /dev/null @@ -1,38 +0,0 @@ -getLocalAddons(); - $components_files = []; - foreach ($addons as $v) { - $components_path = $this->getAddonDictPath($v) . "diy" . DIRECTORY_SEPARATOR . "components.php"; - if (is_file($components_path)) { - $components_files[] = $components_path; - } - } - $components_files_data = $this->loadFiles($components_files); - $components = $data; - foreach ($components_files_data as $file_data) { - $components = empty($components) ? $file_data : array_merge2($components, $file_data); - } - return $components; - } -} diff --git a/niucloud/core/core/dict/UniappLink.php b/niucloud/core/core/dict/UniappLink.php deleted file mode 100644 index e2aca6a7..00000000 --- a/niucloud/core/core/dict/UniappLink.php +++ /dev/null @@ -1,75 +0,0 @@ -getLocalAddons(); - } - - $link_files = []; - - foreach ($addons as $v) { - $link_path = $this->getAddonDictPath($v) . "diy" . DIRECTORY_SEPARATOR . "links.php"; - if (is_file($link_path)) { - $link_files[ $v ] = $link_path; - } - } - - $addon_service = new AddonService(); - $addon_info_list = $addon_service->getAddonListByKeys(array_keys($link_files)); - - if (!empty($params[ 'params' ][ 'query' ]) && $params[ 'params' ][ 'query' ] == 'addon') { - $list_key = array_column($addon_info_list, 'key'); - $addon_info_list = array_combine($list_key, $addon_info_list); - return $addon_info_list; - } else { - - $links = $params[ 'data' ]; - - foreach ($link_files as $k => $v) { - $addon_link = include $v; - if (!empty($addon_link)) { - $addon_info = []; - foreach ($addon_info_list as $ck => $cv) { - if ($cv[ 'key' ] == $k) { - $addon_info = $cv; - break; - } - } - - foreach ($addon_link as $ck => $cv) { - $addon_link[ $ck ][ 'addon_info' ] = $addon_info; - } - $links = array_merge($links, $addon_link); - } - } - - return $links; - } - } -} diff --git a/niucloud/core/core/dict/UniappPages.php b/niucloud/core/core/dict/UniappPages.php deleted file mode 100644 index bb154cb3..00000000 --- a/niucloud/core/core/dict/UniappPages.php +++ /dev/null @@ -1,52 +0,0 @@ -getLocalAddons(); - } - - $page_files = []; - foreach ($addons as $v) { - $page_path = $this->getAddonDictPath($v) . "diy" . DIRECTORY_SEPARATOR . "pages.php"; - if (is_file($page_path)) { - $page_files[] = $page_path; - } - } - $page_files_data = $this->loadFiles($page_files); - if (!empty($data[ 'addon' ])) { - $pages = []; - } else { - $pages = $data; - } - foreach ($page_files_data as $file_data) { - if (empty($pages)) { - $pages = $file_data; - } else { - $pages = array_merge2($pages, $file_data); - } - } - return $pages; - } -} diff --git a/niucloud/core/core/dict/UniappTemplate.php b/niucloud/core/core/dict/UniappTemplate.php deleted file mode 100644 index 6dab6e05..00000000 --- a/niucloud/core/core/dict/UniappTemplate.php +++ /dev/null @@ -1,95 +0,0 @@ -getLocalAddons(); - } - - $app_keys = []; // 应用插件key集合 - $apps = []; // 应用插件集合 - $page_files = []; // 模板页面文件集合 - - // 筛选插件 - if (!empty($params[ 'params' ]) && !empty($params[ 'params' ][ 'addon' ])) { - $is_pass = true; - foreach ($addons as $k => $v) { - if ($params[ 'params' ][ 'addon' ] == $v) { - $addons = [ $v ]; - $is_pass = false; - break; - } - } - - // 如果没有匹配到,则返回系统的 - if ($is_pass) { - return $params[ 'data' ]; - } - } - - foreach ($addons as $v) { - $page_path = $this->getAddonDictPath($v) . "diy" . DIRECTORY_SEPARATOR . "template.php"; - if (is_file($page_path)) { - if (!empty($params[ 'params' ][ 'query' ]) && $params[ 'params' ][ 'query' ] == 'addon') { - $file = include $page_path; - if (!empty($file)) { - $app_keys[] = $v; - $apps[ $v ] = $file; - } - } else { - $page_files[] = $page_path; - } - } - } - - // 查询存在模板页面的应用插件列表 - if (!empty($params[ 'params' ][ 'query' ]) && $params[ 'params' ][ 'query' ] == 'addon') { - $addon_service = new AddonService(); - $list = $addon_service->getAddonListByKeys($app_keys); - $list_key = array_column($list, 'key'); - $list = array_combine($list_key, $list); - foreach ($list as $k => $v) { - $list[ $k ][ 'list' ] = $apps[ $k ]; - } - return $list; - } else { - // 查询应用插件下的模板页面数据 - $page_files_data = $this->loadFiles($page_files); - if (!empty($params[ 'params' ]) && !empty($params[ 'params' ][ 'addon' ])) { - $pages = []; - } else { - $pages = $params[ 'data' ]; - } - foreach ($page_files_data as $file_data) { - if (empty($pages)) { - $pages = $file_data; - } else { - $pages = array_merge($pages, $file_data); - } - } - return $pages; - } - } -} diff --git a/niucloud/core/core/dict/WebLink.php b/niucloud/core/core/dict/WebLink.php deleted file mode 100644 index da09ff00..00000000 --- a/niucloud/core/core/dict/WebLink.php +++ /dev/null @@ -1,75 +0,0 @@ -getLocalAddons(); - } - - $link_files = []; - - foreach ($addons as $v) { - $link_path = $this->getAddonDictPath($v) . "web" . DIRECTORY_SEPARATOR . "web_links.php"; - if (is_file($link_path)) { - $link_files[ $v ] = $link_path; - } - } - - $addon_service = new AddonService(); - $addon_info_list = $addon_service->getAddonListByKeys(array_keys($link_files)); - - if (!empty($params[ 'params' ][ 'query' ]) && $params[ 'params' ][ 'query' ] == 'addon') { - $list_key = array_column($addon_info_list, 'key'); - $addon_info_list = array_combine($list_key, $addon_info_list); - return $addon_info_list; - } else { - - $links = $params[ 'data' ]; - - foreach ($link_files as $k => $v) { - $addon_link = include $v; - if (!empty($addon_link)) { - $addon_info = []; - foreach ($addon_info_list as $ck => $cv) { - if ($cv[ 'key' ] == $k) { - $addon_info = $cv; - break; - } - } - - foreach ($addon_link as $ck => $cv) { - $addon_link[ $ck ][ 'addon_info' ] = $addon_info; - } - $links = array_merge($links, $addon_link); - } - } - - return $links; - } - } -} diff --git a/niucloud/core/core/exception/AddonException.php b/niucloud/core/core/exception/AddonException.php deleted file mode 100644 index 34a08521..00000000 --- a/niucloud/core/core/exception/AddonException.php +++ /dev/null @@ -1,17 +0,0 @@ -job($class)->secs($secs); - if (is_array($action)) { - $queue->data(...$action); - } else if (is_string($action)) { - $queue->method($action)->data(...$data); - } - if ($queue_name) { - $queue->setQueueName($queue_name); - } - return $queue->push(); - } else { - if($secs == 0){ - $class_name = '\\' . $class; - $res = new $class_name(); - if (is_array($action)) { - return $res->doJob(...$action); - } else { - return $res->$action(...$data); - } - } - } - } -} diff --git a/niucloud/core/core/loader/Loader.php b/niucloud/core/core/loader/Loader.php deleted file mode 100644 index e3403f6b..00000000 --- a/niucloud/core/core/loader/Loader.php +++ /dev/null @@ -1,118 +0,0 @@ -name = $name; - } - $this->config = $config; - } - - /** - * 获取默认驱动 - * @return mixed - */ - abstract protected function getDefault(); - - /** - * 创建实例对象 - * @param string $type - * @return object|DbManager - * @throws Exception - */ - public function create(string $type) - { - $class = $this->getClass($type); - return self::createFacade($class, [ - $this->name, - $this->config, - $this->config_file - ], true); - } - - /** - * 获取类 - * @param string $type - * @return mixed|string - * @throws Exception - */ - public function getClass(string $type) - { - $class = config($this->config_name . '.drivers.' . $type . '.driver'); - if (!empty($class) && class_exists($class)) { - return $class; - } else { - if ($this->namespace || str_contains($type, '\\')) { - $class = str_contains($type, '\\') ? $type : $this->namespace . $type; - if (class_exists($class)) { - return $class; - } else { - $class = str_contains($type, '\\') ? $type : $this->namespace . Str::studly($type); - if (class_exists($class)) { - return $class; - } - } - } - } - throw new Exception("Driver [$type] not supported."); - } - - /** - * 通过装载器获取实例 - * @return object|DbManager - * @throws Exception - */ - public function getLoader() - { - - if (empty($this->class)) { - $this->name = $this->name ?: $this->getDefault(); - if (!$this->name) { - throw new Exception(sprintf( - 'could not find driver [%s].', static::class - )); - } - $this->class = $this->create($this->name); - } - return $this->class; - } - - /** - * 动态调用 - * @param $method - * @param $arguments - * @return mixed - * @throws Exception - */ - public function __call($method, $arguments) - { - return $this->getLoader()->{$method}(...$arguments); - } - -} \ No newline at end of file diff --git a/niucloud/core/core/loader/Storage.php b/niucloud/core/core/loader/Storage.php deleted file mode 100644 index 50aea02b..00000000 --- a/niucloud/core/core/loader/Storage.php +++ /dev/null @@ -1,69 +0,0 @@ -name = $name; - $this->config_file = $config_file; - $this->initialize($config); - } - - /** - * 设置错误信息 - * @param string|null $error - * @return bool - */ - protected function setError(?string $error = null) - { - $this->error = $error; - return false; - } - - /** - * 获取错误信息 - * @return string - */ - public function getError() - { - $error = $this->error; - $this->error = null; - return $error; - } - - /** - * 初始化 - * @param array $config - * @return mixed - */ - abstract protected function initialize(array $config); - -} diff --git a/niucloud/core/core/oauth/BaseOauth.php b/niucloud/core/core/oauth/BaseOauth.php deleted file mode 100644 index 8c536023..00000000 --- a/niucloud/core/core/oauth/BaseOauth.php +++ /dev/null @@ -1,42 +0,0 @@ -oauth; - } - - public function oauth(string $code = null, array $options = []) - { -// $this->instance()-> - // TODO: Implement oauth() method. - } -} diff --git a/niucloud/core/core/pay/Alipay.php b/niucloud/core/core/pay/Alipay.php deleted file mode 100644 index 0368a330..00000000 --- a/niucloud/core/core/pay/Alipay.php +++ /dev/null @@ -1,389 +0,0 @@ -config = $this->payConfig($config, 'alipay'); - Pay::config($this->config); - } - - public function mp(array $params) - { - - } - - /** - * 网页支付 - * @param array $params - * @return array - */ - public function web(array $params) - { - return $this->returnFormat(Pay::alipay()->web([ - 'out_trade_no' => $params['out_trade_no'], - 'total_amount' => $params['money'], - 'subject' => $params['body'], - '_method' => 'get', - ])); - } - - /** - * 手机网页支付 - * @param array $params - * @return array - */ - public function wap(array $params) - { - $response = Pay::alipay()->h5([ - 'out_trade_no' => $params['out_trade_no'], - 'total_amount' => $params['money'], - 'subject' => $params['body'], - 'quit_url' => $params['quit_url'] ?? '',//用户付款中途退出返回商户网站的地址, 一般是商品详情页或购物车页 - '_method' => 'get', - ]); - - $redirects = $response->getHeader('Location'); - $effective_url = end($redirects); - return ['url' => $effective_url]; - } - - /** - * app支付 - * @param array $params - * @return array - */ - public function app(array $params) - - { - return $this->returnFormat(Pay::alipay()->app([ - 'out_trade_no' => $params['out_trade_no'], - 'total_amount' => $params['money'], - 'subject' => $params['body'],//用户付款中途退出返回商户网站的地址, 一般是商品详情页或购物车页 - ])); - } - - /** - * 小程序支付 - * @param array $params - * @return Collection - */ - public function mini(array $params) - { - return Pay::alipay()->mini([ - 'out_trade_no' => $params['out_trade_no'], - 'total_amount' => $params['money'], - 'subject' => $params['body'], - 'buyer_id' => $params['buyer_id'],//买家支付宝用户ID 注:交易的买家与卖家不能相同。 - ]); - } - - /** - * 付款码支付 - * @param array $params - * @return Collection - */ - public function pos(array $params) - { - return Pay::alipay()->pos([ - 'out_trade_no' => $params['out_trade_no'], - 'auth_code' => $params['auth_code'],//付授权码。 当面付场景传买家的付款码(25~30开头的长度为16~24位的数字,实际字符串长度以开发者获取的付款码长度为准)或者刷脸标识串(fp开头的35位字符串)。 - 'total_amount' => $params['money'], - 'subject' => $params['body'], - ]); - } - - /** - * 扫码支付 - * @param array $params - * @return Collection - */ - public function scan(array $params) - { - return Pay::alipay()->scan([ - 'out_trade_no' => $params['out_trade_no'], - 'total_amount' => $params['money'], - 'subject' => $params['body'], - ]); - } - - /** - * 转账 - * @param array $params - * @return array - */ - public function transfer(array $params) - { - - $result = $this->returnFormat(Pay::alipay()->transfer([ - 'out_biz_no' => $params['transfer_no'], - 'trans_amount' => $params['money'], - 'product_code' => $params['product_code'] ?: 'TRANS_ACCOUNT_NO_PWD',//业务产品码,单笔无密转账到支付宝账户固定为 : TRANS_ACCOUNT_NO_PWD; 收发现金红包固定为 : STD_RED_PACKET; - 'biz_scene' => $params['scene'] ?: 'DIRECT_TRANSFER',//描述特定的业务场景,可传的参数如下:DIRECT_TRANSFER:单笔无密转账到支付宝,B2C现金红包;PERSONAL_COLLECTION:C2C现金红包-领红包 - 'payee_info' => [//收款方信息 - 'identity' => $params['to_no'],//参与方的唯一标识 - 'identity_type' => $params['to_type'] ?: 'ALIPAY_LOGON_ID',//参与方的标识类型,目前支持如下类型:1、ALIPAY_USER_ID 支付宝的会员ID2、ALIPAY_LOGON_ID:支付宝登录号,支持邮箱和手机号格式3、ALIPAY_OPEN_ID:支付宝openid - 'name' => $params['to_name'],//参与方真实姓名,如果非空,将校验收款支付宝账号姓名一致性。当identity_type=ALIPAY_LOGON_ID时,本字段必填。 - ], - ])); - if (!empty($result['msg']) && $result['msg'] != 'Success') { - throw new PayException($result['sub_msg']); - } else { - $status = $result['status']; - $status_array = [ - 'SUCCESS' => TransferDict::SUCCESS, - 'WAIT_PAY' => TransferDict::WAIT, - 'CLOSED' => TransferDict::FAIL, - 'FAIL' => TransferDict::FAIL - ]; - $res = [ - 'status' => $status_array[$status], - ]; - if ($status == 'FAIL') { - $res['fail_reason'] = $result['fail_reason']; - } - } - return $res; - } - - /** - * 支付关闭 - * @param string $out_trade_no - * @return bool - * @throws ContainerException - * @throws InvalidParamsException - * @throws ServiceNotFoundException - */ - public function close(string $out_trade_no) - { - $result = $this->returnFormat(Pay::alipay()->close([ - 'out_trade_no' => $out_trade_no, - ])); - //todo 支付宝关闭异步回调 - if (isset($result['sub_code']) && in_array($result['sub_code'], ['ACQ.REASON_ILLEGAL_STATUS', 'ACQ.REASON_TRADE_STATUS_INVALID', 'ACQ.TRADE_NOT_EXIST', 'ACQ.TRADE_STATUS_ERROR'])) { - return true; - } - if (!empty($result['msg']) && $result['msg'] == 'Success') { - return true; - } else { - return false; - } - } - - /** - * 退款 - * @param array $params - * @return array|false - * @throws ContainerException - * @throws InvalidParamsException - * @throws ServiceNotFoundException - */ - public function refund(array $params) - { - $out_trade_no = $params['out_trade_no']; - $money = $params['money']; -// $total = $params['total']; - $refund_no = $params['refund_no']; - $result = $this->returnFormat(Pay::alipay()->refund([ - 'out_trade_no' => $out_trade_no, - 'refund_amount' => $money, - 'out_request_no' => $refund_no - ])); - if (!empty($result['msg']) && $result['msg'] == 'Success') { - $fund_change = $result['fund_change'];//退款是否成功可以根据同步响应的 fund_change 参数来判断,fund_change 表示本次退款是否发生了资金变化,返回 Y 表示退款成功,返回 N 则表示本次退款未发生资金变动 。 - if ($fund_change == 'Y') { - $status = RefundDict::SUCCESS; - } else { - $status = RefundDict::DEALING; - } - return [ - 'status' => $status, - 'refund_no' => $refund_no, - 'out_trade_no' => $out_trade_no - ]; - } else { - //todo 这儿可以抛出错误 - return false; - } - } - - - /** - * 支部异步回调 - * @param string $action - * @param callable $callback - * @return ResponseInterface|string - */ - public function notify(string $action, callable $callback) - { - try { - $result = Pay::alipay()->callback(); - //通过返回的值 - if (!empty($result)) {//成功 - if ($action == 'pay') { - //todo 这儿需要具体设计 - $temp_data = array( - 'mchid' => $result['seller_id'], - 'trade_no' => $result['trade_no'], - 'result' => $result, - 'status' => OnlinePayDict::getAliPayStatus($result['trade_status']) - ); - $callback_result = $callback($result['out_trade_no'], $temp_data); - if (is_bool($callback_result) && $callback_result) { - return Pay::alipay()->success(); - } - } - - } - return $this->fail(); - } catch ( Throwable $e ) { - return $this->fail(); - } - - - } - - /** - * 查询普通支付订单 - * @param array $params - * @return array - * @throws ContainerException - * @throws InvalidParamsException - * @throws ServiceNotFoundException - */ - public function getOrder(array $params = []) - { - $out_trade_no = $params['out_trade_no']; - $order = [ - 'out_trade_no' => $out_trade_no, - ]; - $result = $this->returnFormat(Pay::alipay()->query($order)); - if (!empty($result['msg']) && $result['msg'] == 'Success') { - return [ - 'status' => OnlinePayDict::getAliPayStatus($result['trade_status']) - ]; - } else { - if (!empty($result['sub_code']) && $result['sub_code'] == 'ACQ.ACQ.SYSTEM_ERROR') { - throw new PayException($result['msg']); - } else { - return []; - } - } - } - - /** - * 查询退款单据 - * @param string $out_trade_no - * @param string|null $refund_no - * @return array - * @throws ContainerException - * @throws InvalidParamsException - * @throws ServiceNotFoundException - */ - public function getRefund(string $out_trade_no, ?string $refund_no) - { - $order = [ - 'out_trade_no' => $out_trade_no, - 'out_request_no' => $refund_no, - '_action' => 'refund', // 默认值,查询退款网页订单 - ]; - - $result = $this->returnFormat(Pay::alipay()->query($order)); - if (!empty($result['msg']) && $result['msg'] == 'Success') { - $refund_status = $result['refund_status'] ?? ''; - if ($refund_status == 'REFUND_SUCCESS') { - $status = RefundDict::SUCCESS; - } else { - $status = RefundDict::DEALING; - } - return [ - 'status' => $status, - 'refund_no' => $refund_no, - 'out_trade_no' => $out_trade_no - ]; - } else { - if (!empty($result['sub_code']) && $result['sub_code'] == 'ACQ.ACQ.SYSTEM_ERROR') { - throw new PayException($result['msg']); - } else { - return []; - } - } - } - - /** - * 获取转账订单 - * @param string $transfer_no - * @return array - * @throws ContainerException - * @throws InvalidParamsException - * @throws ServiceNotFoundException - */ - public function getTransfer(string $transfer_no, $out_transfer_no = '') - { - $order = [ - 'out_biz_no' => $transfer_no, - '_action' => 'transfer' - ]; - $result = $this->returnFormat(Pay::alipay()->query($order)); - if (!empty($result['msg']) && $result['msg'] == 'Success') { - $status = $result['SUCCESS'] ?? ''; - $status_array = array( - 'SUCCESS' => TransferDict::SUCCESS, - 'WAIT_PAY' => TransferDict::WAIT, - 'CLOSED' => TransferDict::FAIL, - 'FAIL' => TransferDict::FAIL - ); - return [ - 'status' => $status_array[$status], - 'transfer_no' => $transfer_no - ]; - } else { - if (!empty($result['sub_code']) && $result['sub_code'] == 'ACQ.ACQ.SYSTEM_ERROR') { - throw new PayException($result['msg']); - } else { - return []; - } - } - } - - public function fail() - { - return 'fail'; - } - - public function returnUrl($params) - { - return ['url' => $params->getHeader('Location')[0] ?? '']; - } -} diff --git a/niucloud/core/core/pay/BasePay.php b/niucloud/core/core/pay/BasePay.php deleted file mode 100644 index 439d083f..00000000 --- a/niucloud/core/core/pay/BasePay.php +++ /dev/null @@ -1,203 +0,0 @@ - [ - 'enable' => true, - 'file' => root_path('runtime') . 'paylog' . DIRECTORY_SEPARATOR . date('Ym') . DIRECTORY_SEPARATOR . date('d') . '.log', - 'level' => env('app_debug') ? 'debug' : 'info', // 建议生产环境等级调整为 info,开发环境为 debug - 'type' => 'single', // optional, 可选 daily. - 'max_file' => 30, // optional, 当 type 为 daily 时有效,默认 30 天 - ], - 'http' => [ // optional - 'timeout' => 5.0, - ] - ], - [ - $type => [ - 'default' => $config - ] - ], - ['_force' => true] - ); - } - - public function returnFormat($param) - { - if ($param instanceof MessageInterface || $param instanceof Response) { - $return_value = $param->getBody()->getContents(); - } else if ($param instanceof Collection) { - $return_value = $param->toArray(); - } else { - $return_value = $param; - } - return $return_value; - } - - /** - * 解析退款返回数据并解析 - * @param $our_trade_no - * @param $refund_no - * @param $status - * @param int $success_time - * @param string $reason - * @return array - */ - public function getRefundData($our_trade_no, $refund_no, $status, $success_time = 0, $reason = '') - { - return [ - 'our_trade_no' => $our_trade_no, - 'refund_no' => $refund_no, - 'status' => $status, - 'success_time' => $success_time, - 'reason' => $reason - ]; - } - - /** - * 获取转账数据并解析 - * @param $transfer_no - * @param $status - * @param $reason - * @return void - */ - public function getTransferData($transfer_no, $status, $reason) - { - - } - - -} diff --git a/niucloud/core/core/pay/PayLoader.php b/niucloud/core/core/pay/PayLoader.php deleted file mode 100644 index b0c34ab6..00000000 --- a/niucloud/core/core/pay/PayLoader.php +++ /dev/null @@ -1,42 +0,0 @@ -config = $config; - $config['mch_secret_cert'] = url_to_path($config['mch_secret_cert'] ?? ''); - $config['mch_public_cert_path'] = url_to_path($config['mch_public_cert_path'] ?? ''); - // 选填-默认为正常模式。可选为: MODE_NORMAL, MODE_SERVICE - $config['mode'] = Pay::MODE_NORMAL; - if (!empty($config['wechat_public_cert_path']) && !empty($config['wechat_public_cert_id'])) { - $config['wechat_public_cert_path'] = [ - $config['wechat_public_cert_id'] => url_to_path($config['wechat_public_cert_path']) - ]; - } else { - unset($config['wechat_public_cert_path']); - unset($config['wechat_public_cert_id']); - } - Pay::config($this->payConfig($config, 'wechat')); - } - - - /** - * 公众号支付 - * @param array $params - * @return mixed|Collection - */ - public function mp(array $params) - { - try { - $result = $this->returnFormat(Pay::wechat()->mp([ - 'out_trade_no' => $params['out_trade_no'], - 'description' => $params['body'], - 'amount' => [ - 'total' => $params['money'], - ], - 'payer' => [ - 'openid' => $params['openid'], - ], - ])); - $code = $result['code'] ?? 0; - if ($code == 0) return $result; - //支付错误抛出 - throw new PayException($result['message']); - } catch (\Exception $e) { - if ($e instanceof InvalidResponseException) { - throw new PayException($e->response->all()['message'] ?? ''); - } - throw new PayException($e->getMessage()); - } - } - - /** - * 手机网页支付 - * @param array $params - * @return mixed - */ - public function wap(array $params) - { - try { - $order = [ - 'out_trade_no' => $params['out_trade_no'], - 'description' => $params['body'], - 'amount' => [ - 'total' => $params['money'], - ], - 'scene_info' => [ - 'payer_client_ip' => request()->ip(), - 'h5_info' => [ - 'type' => 'Wap', - ] - ], - ]; - //这儿有些特殊, 默认情况下,H5 支付所使用的 appid 是微信公众号的 appid,即配置文件中的 mp_app_id 参数,如果想使用关联的小程序的 appid,则只需要在调用参数中增加 ['_type' => 'mini'] 即可 - if (!empty($order['type'])) { - $order['_type'] = 'mini'; // 注意这一行 - } - return $this->returnFormat(Pay::wechat()->h5($order)); - } catch (\Exception $e) { - if ($e instanceof InvalidResponseException) { - throw new PayException($e->response->all()['message'] ?? ''); - } - throw new PayException($e->getMessage()); - } - } - - public function web(array $params) - { - - } - - /** - * app支付 - * @param array $params - * @return mixed|ResponseInterface - */ - public function app(array $params) - { - try { - return $this->returnFormat(Pay::wechat()->app([ - 'out_trade_no' => $params['out_trade_no'], - 'description' => $params['body'], - 'amount' => [ - 'total' => $params['money'], - ], - ])); - } catch (\Exception $e) { - if ($e instanceof InvalidResponseException) { - throw new PayException($e->response->all()['message'] ?? ''); - } - throw new PayException($e->getMessage()); - } - } - - /** - * 小程序支付 - * @param array $params - * @return mixed|ResponseInterface - */ - public function mini(array $params) - { - try { - return $this->returnFormat(Pay::wechat()->mini([ - 'out_trade_no' => $params['out_trade_no'], - 'description' => $params['body'], - 'amount' => [ - 'total' => $params['money'], - 'currency' => 'CNY',//一般是人民币 - ], - 'payer' => [ - 'openid' => $params['openid'], - ] - ])); - } catch (\Exception $e) { - if ($e instanceof InvalidResponseException) { - throw new PayException($e->response->all()['message'] ?? ''); - } - throw new PayException($e->getMessage()); - } - } - - /** - * 付款码支付 - * @param array $params - * @return mixed|Collection - */ - public function pos(array $params) - { - try { - $order = [ - 'out_trade_no' => $params['out_trade_no'], - 'body' => $params['body'], - 'total_fee' => $params['money'], - 'spbill_create_ip' => request()->ip(), - 'auth_code' => $params["auth_code"], - ]; - $result = Pay::wechat()->pos($order); - return $this->returnFormat($result); - } catch (\Exception $e) { - if ($e instanceof InvalidResponseException) { - throw new PayException($e->response->all()['message'] ?? ''); - } - throw new PayException($e->getMessage()); - } - } - - /** - * 扫码支付 - * @param array $params - * @return mixed|Collection - */ - public function scan(array $params) - { - try { - return $this->returnFormat(Pay::wechat()->scan([ - 'out_trade_no' => $params['out_trade_no'], - 'description' => $params['body'], - 'amount' => [ - 'total' => $params['money'], - ], - ])); - } catch (\Exception $e) { - if ($e instanceof InvalidResponseException) { - throw new PayException($e->response->all()['message'] ?? ''); - } - throw new PayException($e->getMessage()); - } - } - - /** - * 转账(微信的转账是很多笔的) - * @param array $params - * @return array - */ - public function transfer(array $params) - { - - $to_data = $params['to_no'];//收款人数据 - $channel = $to_data['channel'] ?? '';//渠道 - $open_id = $to_data['open_id'] ?? '';//openid - - if(empty($this->config['mch_id']) || empty($this->config['mch_secret_key']) || empty($this->config['mch_secret_cert']) || empty($this->config['mch_public_cert_path'])){ - throw new PayException('WECHAT_TRANSFER_CONFIG_NOT_EXIST'); - } - //这儿的批次信息可能是这儿生成的,但依然需要记录 - $order = [ - 'out_batch_no' => ($to_data['out_batch_no'] ?? '') . '',// - 'batch_name' => $params['remark'] ?? '', - 'batch_remark' => $params['remark'] ?? '', - ]; - if($channel == ChannelDict::WEAPP){ - $order['_type'] = 'mini'; - } - $transfer_list = $params['transfer_list']; - //单笔转账 - if (empty($transfer_list)) { - $transfer_list = [ - [ - 'transfer_no' => $params['transfer_no'], - 'money' => (int)$params['money'], - 'remark' => $params['remark'], - 'openid' => $open_id - ] - ]; - } - $total_amount = 0; - $total_num = 0; - - foreach ($transfer_list as $k => $v) { - $item_transfer = [ - 'out_detail_no' => $params['transfer_no'], - 'transfer_amount' => (int)$v['money'], - 'transfer_remark' => $v['remark'], - 'openid' => $v['openid'], - ]; - $total_amount += (int)$v['money']; - $total_num++; - if (!empty($v['user_name'])) { - $item_transfer['user_name'] = $v['user_name'];// 明文传参即可,sdk 会自动加密 - } - $order['transfer_detail_list'][] = $item_transfer; - } - $order['total_amount'] = $total_amount; - $order['total_num'] = $total_num; - $tran_status_list = [ - 'PROCESSING' => TransferDict::DEALING, - 'ACCEPTED' => TransferDict::DEALING, - 'CLOSED' => TransferDict::FAIL, - 'FINISHED' => TransferDict::SUCCESS, - ]; - try { - $result = $this->returnFormat(Pay::wechat()->transfer($order)); - if (!empty($result['code'])) { -// if($result['code'] == 'PARAM_ERROR'){ -// throw new PayException(); -// }else if($result['code'] == 'INVALID_REQUEST'){ -// throw new PayException(); -// } - if ($result['code'] == 'INVALID_REQUEST') { - throw new PayException(700010); - } - throw new PayException($result['message']); - } - - - return ['batch_id' => $result['batch_id'], 'out_batch_no' => $result['out_batch_no'], 'status' => $tran_status_list[$result['batch_status']]]; - } catch (\Exception $e) { - if($e->getCode() == 9402){ - return ['batch_id' => '', 'out_batch_no' => $order['out_batch_no'], 'status' => TransferDict::DEALING]; - } - if ($e instanceof InvalidResponseException) { - throw new PayException($e->response->all()['message'] ?? ''); - } - throw new PayException($e->getMessage()); - } - - } - - /** - * 支付关闭 - * @param string $out_trade_no - * @return void - * @throws ContainerException - * @throws InvalidParamsException - * @throws ServiceNotFoundException - */ - public function close(string $out_trade_no) - { - try { - $result = Pay::wechat()->close([ - 'out_trade_no' => $out_trade_no, - ]); - return $this->returnFormat($result); - }catch(Throwable $e){ - return false; - } - return true; - } - - /** - * 退款 - * @param array $params - * @return array - * @throws ContainerException - * @throws InvalidParamsException - * @throws ServiceNotFoundException - */ - public function refund(array $params) - { - $out_trade_no = $params['out_trade_no']; - $money = $params['money']; - $total = $params['total']; - $refund_no = $params['refund_no']; - $result = Pay::wechat()->refund([ - 'out_trade_no' => $out_trade_no, - 'out_refund_no' => $refund_no, - 'amount' => [ - 'refund' => $money, - 'total' => $total, - 'currency' => 'CNY', - ], - ]); - $result = $this->returnFormat($result); - - $refund_status_array = [ - 'SUCCESS' => RefundDict::SUCCESS, - 'CLOSED' => RefundDict::FAIL, - 'PROCESSING' => RefundDict::DEALING, - 'ABNORMAL' => RefundDict::FAIL, - ]; - return [ - 'status' => $refund_status_array[$result['status']], - 'refund_no' => $refund_no, - 'out_trade_no' => $out_trade_no, - 'pay_refund_no' => $result['refund_id'] - ]; - } - - - /** - * 异步回调 - * @param string $action - * @param callable $callback - * @return ResponseInterface|Response - */ - public function notify(string $action, callable $callback) - { - try { - $result = $this->returnFormat(Pay::wechat()->callback()); - if ($action == 'pay') {//支付 - if ($result['event_type'] == 'TRANSACTION.SUCCESS') { - $pay_trade_data = $result['resource']['ciphertext']; - - $temp_params = [ - 'trade_no' => $pay_trade_data['transaction_id'], - 'mch_id' => $pay_trade_data['mchid'], - 'status' => OnlinePayDict::getWechatPayStatus($pay_trade_data['trade_state']) - ]; - - $callback_result = $callback($pay_trade_data['out_trade_no'], $temp_params); - if (is_bool($callback_result) && $callback_result) { - return Pay::wechat()->success(); - } - } - } else if ($action == 'refund') {//退款 - if ($result['event_type'] == 'REFUND.SUCCESS') { - $refund_trade_data = $result['resource']['ciphertext']; - $refund_status_array = [ - 'SUCCESS' => RefundDict::SUCCESS, - 'CLOSED' => RefundDict::FAIL, - 'PROCESSING' => RefundDict::DEALING, - 'ABNORMAL' => RefundDict::FAIL, - ]; - $temp_params = [ - 'trade_no' => $refund_trade_data['transaction_id'], - 'mch_id' => $refund_trade_data['mchid'], - 'refund_no' => $refund_trade_data['out_refund_no'], - 'status' => $refund_status_array[$refund_trade_data['refund_status']], - ]; - - $callback_result = $callback($refund_trade_data['out_trade_no'], $temp_params); - if (is_bool($callback_result) && $callback_result) { - return Pay::wechat()->success(); - } - } - } - return $this->fail(); - - } catch ( Throwable $e ) { -// throw new PayException($e->getMessage()); - return $this->fail($e->getMessage()); - } - } - - /** - * 查询普通支付订单 - * @param array $params - * @return array|MessageInterface|Collection|null - * @throws ContainerException - * @throws InvalidParamsException - * @throws ServiceNotFoundException - */ - public function getOrder(array $params = []) - { - - $out_trade_no = $params['out_trade_no']; - $transaction_id = $params['transaction_id'] ?? ''; - $order = [ - - ]; - if (!empty($out_trade_no)) { - $order['out_trade_no'] = $out_trade_no; - } - if (!empty($transaction_id)) { - $order['transaction_id'] = $transaction_id; - } - $result = Pay::wechat()->query($order); - if (empty($result)) - return $result; - $result = $this->returnFormat($result); - return [ - 'status' => OnlinePayDict::getWechatPayStatus($result['trade_state']), - ]; - } - - /** - * 查询退款单据 - * @param string|null $out_trade_no - * @param string|null $refund_no - * @return array|Collection|MessageInterface|null - * @throws ContainerException - * @throws InvalidParamsException - * @throws ServiceNotFoundException - */ - public function getRefund(?string $out_trade_no, ?string $refund_no = '') - { - $order = [ - '_action' => 'refund', - 'transaction_id' => $out_trade_no, - 'out_refund_no' => $refund_no, - '' - ]; - $result = Pay::wechat()->query($order); - if (empty($result)) - return $result; - $result = $this->returnFormat($result); - $refund_status_array = [ - 'SUCCESS' => RefundDict::SUCCESS, - 'CLOSED' => RefundDict::FAIL, - 'PROCESSING' => RefundDict::DEALING, - 'ABNORMAL' => RefundDict::FAIL, - ]; - return [ - 'status' => $refund_status_array[$result['status']], - 'refund_no' => $refund_no, - 'out_trade_no' => $out_trade_no - ]; - } - - /** - * 获取转账订单(todo 切勿调用) - * @param string $transfer_no - * @return array - * @throws ContainerException - * @throws InvalidParamsException - */ - public function getTransfer(string $transfer_no, $out_batch_no = '') - { - $order = [ - 'out_batch_no' => $out_batch_no, - 'out_detail_no' => $transfer_no, - '_action' => 'transfer', - ]; - - try { - $result = Pay::wechat()->query($order); - $result = $this->returnFormat($result); - //微信转账状态 - $transfer_status_array = [ - 'INIT' => TransferDict::DEALING,//初始态。 系统转账校验中 - 'WAIT_PAY' => TransferDict::DEALING, - 'PROCESSING' => TransferDict::DEALING, - 'FAIL' => TransferDict::FAIL, - 'SUCCESS' => TransferDict::SUCCESS, - ]; - return [ - 'status' => $transfer_status_array[$result['detail_status']], - 'transfer_no' => $transfer_no - ]; - }catch(Throwable $e){ - return [ - 'status' => TransferDict::DEALING, - 'transfer_no' => $transfer_no - ]; - } - } - - - public function fail($message = '') - { - $response = [ - 'code' => 'FAIL', - 'message' => $message ?: '失败', - ]; - return response($response, 400, [], 'json'); - } -} diff --git a/niucloud/core/core/poster/BasePoster.php b/niucloud/core/core/poster/BasePoster.php deleted file mode 100644 index 2822d065..00000000 --- a/niucloud/core/core/poster/BasePoster.php +++ /dev/null @@ -1,41 +0,0 @@ -config([ 'path' => realpath($dir) . DIRECTORY_SEPARATOR . $file_path ]); - $bg_width = $poster_data[ 'global' ][ 'width' ]; - $bg_height = $poster_data[ 'global' ][ 'height' ]; - if ($bg_type == 'url' && !empty($poster_data[ 'global' ][ 'bgUrl' ]) && is_file($poster_data[ 'global' ][ 'bgUrl' ])) { - $im = $instance->buildIm($bg_width, $bg_height)->buildImage([ - 'src' => $poster_data[ 'global' ][ 'bgUrl' ], -// 'angle' => 80 - ], 0, 0, 0, 0, $bg_width, $bg_height); - } else { - $im = $instance->buildIm($bg_width, $bg_height, $this->getRgbColor($poster_data[ 'global' ][ 'bgColor' ])); - } - $align_array = [ - 'center', 'left', 'right', 'top', 'bottom' - ]; - foreach ($poster_data[ 'value' ] as $k => $v) { - $type = $v[ 'type' ]; - switch ($type) { - case 'text': - $font_size = ceil($v[ 'fontSize' ]); - $default_font = 'static' . DIRECTORY_SEPARATOR . 'font' . DIRECTORY_SEPARATOR . 'SourceHanSansCN-Regular.ttf'; - $font = $v[ 'fontFamily' ] ? : $default_font; - $content_list = $this->getText($v[ 'value' ], $font_size, $font, $v[ 'space' ] ?? 0, $v[ 'width' ], $v[ 'height' ], $v[ 'lineHeight' ] + $font_size); - $base_y = $this->getX($v[ 'y' ]); - if (is_array($base_y)) { - $diff_height = count($content_list) * ( $v[ 'lineHeight' ] + $font_size ); - $again_y = $base_y[ 0 ]; - if ($again_y == 'center') { - $base_y_num = ( $bg_height - $diff_height ) > 0 ? ( $bg_height - $diff_height ) / 2 : 0; - } else if ($again_y == 'top') { - $base_y_num = 0; - } else { - $base_y_num = $bg_height - $v[ 'height' ]; - } - - } else { - $base_y_num = $base_y; - } -// if(in_array($base_y, $align_array)){ -// $diff_height = count($content_list)*($v[ 'lineHeight' ]+$font_size); -// $base_y_num = ($bg_height-$diff_height) > 0 ? ($bg_height-$diff_height)/2 : 0; -// }else{ -// $base_y_num = $base_y[0]; -// } - foreach ($content_list as $ck => $content) { - if ($ck == 0) { - if ($v[ 'lineHeight' ] > 0) { - $item_line = $v[ 'lineHeight' ] / 2; - } else { - $item_line = 0; - } - } else { - $item_line = $v[ 'lineHeight' ] + $font_size; - } - $base_y_num += $item_line; - //计算文本框宽度 - $im = $im->buildText($content, $this->getX($v[ 'x' ]), $base_y_num, $font_size, $this->getRgbColor($v[ 'fontColor' ]), $v[ 'width' ], $font, $v[ 'weight' ] ? 10 : null); # 合成文字 - } - break; - case 'image': - if (is_file($v[ 'value' ])) { - $im = $im->buildImage($v[ 'value' ], $this->getX($v[ 'x' ]), $this->getY($v[ 'y' ]), 0, 0, $v[ 'width' ], $v[ 'height' ], false, $v[ 'shape' ] ?? 'normal'); # 合成图片 - } - break; - case 'draw': - if (!empty($v[ 'draw_type' ]) && $v[ 'draw_type' ] == 'Polygon') { - $points = $v[ 'points' ]; - $im = $im->buildLine($points[ 0 ][ 0 ], $points[ 0 ][ 1 ], $points[ 2 ][ 0 ], $points[ 2 ][ 1 ], $this->getRgbColor($v[ 'bgColor' ]), 'filled_rectangle'); - } - break; - } - } - - $path = $im->getPoster(); - - return str_replace(DIRECTORY_SEPARATOR, '/', str_replace(realpath(''), '', $path[ 'url' ])); - } - - - public function getX($dst_x) - { - if (is_int($dst_x)) { - return $dst_x; - } else { - return [ $dst_x, 0 ]; - } - } - - public function getY($dst_y) - { - if (is_int($dst_y)) { - return $dst_y; - } else { - return [ $dst_y, 0 ]; - } - } - - public function getRgbColor($color) - { - $color = $color ? : '#FFFFFF'; - if (!str_contains($color, '#')) { - $color = str_replace('rgba(', '', $color); - $color = str_replace(')', '', $color); - list($r, $g, $b) = explode(',', $color); - list($r, $g, $b) = array_map(function($v) { return (int) $v; }, [ $r, $g, $b ]); - } else { - list($r, $g, $b) = sscanf($color, "#%02x%02x%02x"); - } - return [ $r, $g, $b, 1 ]; - } - - /** - * 获取高度限制过后的文本 - * @param $content - * @param $fontSize - * @param $font - * @param $space - * @param $max_ws - * @param $max_hs - * @param $line_height - * @return mixed - */ - public function getText($content, $fontSize, $font, $space, $max_ws, $max_hs, $line_height) - { - $calcSpace = $space > $fontSize ? ( $space - $fontSize ) : 0; // 获取间距计算值 - - $fontSize = ( $fontSize * 3 ) / 4; // px 转化为 pt - - mb_internal_encoding('UTF-8'); // 设置编码 - // 这几个变量分别是 字体大小, 角度, 字体名称, 字符串, 预设宽度 - $contents = ''; - $contentsArr = []; - $letter = []; - $line = 1; - $calcSpaceRes = 0; - // 将字符串拆分成一个个单字 保存到数组 letter 中 - for ($i = 0; $i < mb_strlen($content); $i++) { - $letter[] = mb_substr($content, $i, 1); - } - $textWidthArr = []; - $contentStr = ''; - $line_num = 1; - $total_width = 0; - $content_list = []; - foreach ($letter as $l) { - $textStr = $contentStr . $l; - $fontBox = imagettfbbox($fontSize, 0, $font, $textStr); - $textWidth = abs($fontBox[ 2 ]) + $calcSpaceRes; - $textWidthArr[ $line ] = $textWidth; - // 判断拼接后的字符串是否超过预设的宽度 - if (( $textWidth > $max_ws ) && ( $contents !== '' )) { - $line_num++; - if (( $line_num * $line_height ) > $max_hs) { - break; - } - $contents .= "\n"; - $contentStr = ""; - $line++; - } - if (empty($content_list[ $line_num - 1 ])) $content_list[ $line_num - 1 ] = ''; - $content_list[ $line_num - 1 ] .= $l; - $contents .= $l; - $contentStr .= $l; - $line === 1 && $calcSpaceRes += $calcSpace; - $text_width = max(array_values($textWidthArr)); - } - return $content_list; - } -} \ No newline at end of file diff --git a/niucloud/core/core/poster/PosterLoader.php b/niucloud/core/core/poster/PosterLoader.php deleted file mode 100644 index 82265b01..00000000 --- a/niucloud/core/core/poster/PosterLoader.php +++ /dev/null @@ -1,42 +0,0 @@ -config = $config; - } - - /** - * 打印小票 - * @param array $data - * @return mixed|void - */ - public function printTicket(array $data) - { - } -} \ No newline at end of file diff --git a/niucloud/core/core/printer/PrinterLoader.php b/niucloud/core/core/printer/PrinterLoader.php deleted file mode 100644 index 28c2f9c8..00000000 --- a/niucloud/core/core/printer/PrinterLoader.php +++ /dev/null @@ -1,39 +0,0 @@ -client->call('expressprint/index', array('machine_code' => $machineCode, 'content' => $content, 'origin_id' => $originId, 'sandbox' => $sandbox)); - } - - /** - * 面单取消接口 - * - * @param $machineCode - * @param $content - * @return mixed - * @throws \Exception - */ - public function cancel($machineCode, $content) - { - return $this->client->call('expressprint/cancel', array('machine_code' => $machineCode, 'content' => $content)); - } - -} diff --git a/niucloud/core/core/printer/sdk/yilianyun/api/OauthService.php b/niucloud/core/core/printer/sdk/yilianyun/api/OauthService.php deleted file mode 100644 index c712be22..00000000 --- a/niucloud/core/core/printer/sdk/yilianyun/api/OauthService.php +++ /dev/null @@ -1,22 +0,0 @@ -client->call('oauth/setpushurl', array('cmd' => $cmd, 'url' => $url, 'status' => $status)); - } -} - - diff --git a/niucloud/core/core/printer/sdk/yilianyun/api/PicturePrintService.php b/niucloud/core/core/printer/sdk/yilianyun/api/PicturePrintService.php deleted file mode 100644 index dfb4b4c4..00000000 --- a/niucloud/core/core/printer/sdk/yilianyun/api/PicturePrintService.php +++ /dev/null @@ -1,22 +0,0 @@ -client->call('pictureprint/index', array('machine_code' => $machineCode, 'picture_url' => $pictureUrl, 'origin_id' => $originId, $idempotence => $idempotence)); - } -} diff --git a/niucloud/core/core/printer/sdk/yilianyun/api/PrintMenuService.php b/niucloud/core/core/printer/sdk/yilianyun/api/PrintMenuService.php deleted file mode 100644 index 6f4a5ede..00000000 --- a/niucloud/core/core/printer/sdk/yilianyun/api/PrintMenuService.php +++ /dev/null @@ -1,19 +0,0 @@ -client->call('printmenu/addprintmenu', array('machine_code' => $machineCode, 'content' => $content)); - } - -} \ No newline at end of file diff --git a/niucloud/core/core/printer/sdk/yilianyun/api/PrintService.php b/niucloud/core/core/printer/sdk/yilianyun/api/PrintService.php deleted file mode 100644 index 7ff2309e..00000000 --- a/niucloud/core/core/printer/sdk/yilianyun/api/PrintService.php +++ /dev/null @@ -1,20 +0,0 @@ -client->call('print/index', array('machine_code' => $machineCode, 'content' => $content, 'origin_id' => $originId, 'idempotence' => $idempotence)); - } -} diff --git a/niucloud/core/core/printer/sdk/yilianyun/api/PrinterService.php b/niucloud/core/core/printer/sdk/yilianyun/api/PrinterService.php deleted file mode 100644 index d7b6bd66..00000000 --- a/niucloud/core/core/printer/sdk/yilianyun/api/PrinterService.php +++ /dev/null @@ -1,313 +0,0 @@ - $machineCode, - 'msign' => $mSign, - ); - if (!empty($phone)) { - $params['phone'] = $phone; - } - if (!empty($printName)) { - $params['print_name'] = $printName; - } - return $this->client->call('printer/addprinter', $params); - } - - - /** - * 设置内置语音接口 - * 注意: 仅支持K4-WA、K4-GAD、K4-WGEAD型号 - * - * @param $machineCode string 机器码 - * @param $content string 在线语音地址链接 or 自定义语音内容 - * @param bool $isFile true or false - * @param string $aid int 0~9 , 定义需设置的语音编号,若不提交,默认升序 - * @return mixed - */ - public function setVoice($machineCode, $content, $isFile = false, $aid = '') - { - $params = array( - 'machine_code' => $machineCode, - 'content' => $content, - 'is_file' => $isFile, - ); - if (!empty($aid)){ - $params ['aid'] = $aid; - } - return $this->client->call('printer/setvoice', $params); - } - - - /** - * 删除内置语音接口 - * 注意: 仅支持K4-WA、K4-GAD、K4-WGEAD型号 - * - * @param $machineCode string 机器码 - * @param $aid int 0 ~ 9 编号 - * @return mixed - */ - public function deleteVoice($machineCode, $aid) - { - return $this->client->call('printer/deletevoice', array('machine_code' => $machineCode, 'aid' => $aid)); - } - - - /** - * 删除终端授权接口 - * - * @param $machineCode string 机器码 - * @return mixed - */ - public function deletePrinter($machineCode) - { - return $this->client->call('printer/deleteprinter', array('machine_code' => $machineCode)); - } - - - /** - * 关机重启接口 - * - * @param $machineCode string 机器码 - * @param $responseType string restart or shutdown - * @return mixed - */ - public function shutdownRestart($machineCode, $responseType) - { - return $this->client->call('printer/shutdownrestart', array('machine_code' => $machineCode, 'response_type' => $responseType)); - } - - - /** - * 声音调节接口 - * - * @param $machineCode string 机器码 - * @param $voice string 音量 0 or 1 or 2 or 3 - * @param $responseType string buzzer (蜂鸣器) or horn (喇叭) - * @return mixed - */ - public function setsound($machineCode, $voice, $responseType) - { - return $this->client->call('printer/setsound', array('machine_code' => $machineCode, 'voice' => $voice, 'response_type' => $responseType)); - } - - - /** - * 获取机型打印宽度接口 - * - * @param $machineCode string 机器码 - * @return mixed - */ - public function printInfo($machineCode) - { - return $this->client->call('printer/printinfo', array('machine_code' => $machineCode)); - } - - - /** - * 获取机型软硬件版本接口 - * - * @param $machineCode string 机器码 - * @return mixed - */ - public function getVersion($machineCode) - { - return $this->client->call('printer/getversion', array('machine_code' => $machineCode)); - } - - - /** - * 取消所有未打印订单接口 - * - * @param $machineCode string 机器码 - * @return mixed - */ - public function cancelAll($machineCode) - { - return $this->client->call('printer/cancelall', array('machine_code' => $machineCode)); - } - - - /** - * 取消单条未打印订单接口 - * - * @param $machineCode string 机器码 - * @param $orderId string 未打印的易联云ID - * @return mixed - */ - public function cancelOne($machineCode, $orderId) - { - return $this->client->call('printer/cancelone', array('machine_code' => $machineCode, 'order_id' => $orderId)); - } - - - /** - * 设置logo接口 - * - * @param $machineCode string 机器码 - * @param $imgUrl string logo链接地址 - * @return mixed - */ - public function setIcon($machineCode, $imgUrl) - { - return $this->client->call('printer/seticon', array('machine_code' => $machineCode, 'img_url' => $imgUrl)); - } - - - /** - * 取消logo接口 - * - * @param $machineCode string 机器码 - * @return mixed - */ - public function deleteIcon($machineCode) - { - return $this->client->call('printer/deleteicon', array('machine_code' => $machineCode)); - } - - - /** - * 打印方式接口 - * - * @param $machineCode string 机器码 - * @param $responseType string btnopen or btnclose - * @return mixed - */ - public function btnPrint($machineCode, $responseType) - { - return $this->client->call('printer/btnprint', array('machine_code' => $machineCode, 'response_type' => $responseType)); - } - - - /** - * 接单拒单设置接口 - * - * @param $machineCode string 机器码 - * @param $responseType string open or close - * @return mixed - */ - public function getOrder($machineCode, $responseType) - { - return $this->client->call('printer/getorder', array('machine_code' => $machineCode, 'response_type' => $responseType)); - } - - - /** - * 获取订单状态接口 - * - * @param $machineCode string 机器码 - * @param $orderId string 易联云订单id - * @return mixed - */ - public function getOrderStatus($machineCode, $orderId) - { - return $this->client->call('printer/getorderstatus', array('machine_code' => $machineCode, 'order_id' => $orderId)); - } - - - /** - * 获取订单列表接口 - * - * @param $machineCode string 机器码 - * @param $pageIndex int 第几页 - * @param $pageSize int 查询条数 - * @return mixed - */ - public function getOrderPagingList($machineCode, $pageIndex = 1 , $pageSize = 10) - { - return $this->client->call('printer/getorderpaginglist', array('machine_code' => $machineCode, 'page_index' => $pageIndex, 'page_size' => $pageSize)); - } - - /** - * 获取终端状态接口 - * - * @param $machineCode string 机器码 - * @return mixed - */ - public function getPrintStatus($machineCode) - { - return $this->client->call('printer/getprintstatus', array('machine_code' => $machineCode)); - } - - /** - * 订单重打(单订单) - * - * @param $machineCode - * @param $orderId - * @return mixed - * @throws \Exception - */ - public function reprintOrder($machineCode, $orderId) - { - return $this->client->call('printer/reprintorder', array('machine_code' => $machineCode, 'order_id' => $orderId)); - } - - /** - * K8 推送开关设置 - * - * @param $machineCode - * @param $status - * @param $mode - * @return mixed - * @throws \Exception - */ - public function pushSwitch($machineCode, $status, $mode = 1) - { - return $this->client->call('printer/pushswitch', array('machine_code' => $machineCode, 'status' => $status, $mode)); - } - - /** - * K8 关键词设置接口 - * - * @param $machineCode - * @param $keys - * @param $type - * @param $content - * @return mixed - * @throws \Exception - */ - public function setKeyWords($machineCode, $keys, $type, $content) - { - return $this->client->call('printer/setkeywords', array('machine_code' => $machineCode, 'keys' => $keys, 'type' => $type, 'content' => $content)); - } - - /** - * K8 高级设置接口 - * - * @param $machineCode - * @param null $usbPrintMode - * @param null $usbInputMode - * @param null $cameraDecodeTxMode - * @return mixed - * @throws \Exception - */ - public function setting($machineCode, $usbPrintMode = null, $usbInputMode = null, $cameraDecodeTxMode = null) - { - $params = array('machine_code' => $machineCode); - if (!is_null($usbPrintMode) && in_array($usbPrintMode, [0, 1])) { - $params['usb_print_mode'] = (int)$usbInputMode; - } - if (!is_null($usbInputMode) && in_array($usbInputMode, [0, 1])) { - $params['usb_input_mode'] = (int)$usbInputMode; - } - if (!is_null($cameraDecodeTxMode) && in_array($cameraDecodeTxMode, [0, 1])) { - $params['camera_decode_tx_mode'] = (int)$cameraDecodeTxMode; - } - return $this->client->call('printer/setting', $params); - } - -} diff --git a/niucloud/core/core/printer/sdk/yilianyun/api/RpcService.php b/niucloud/core/core/printer/sdk/yilianyun/api/RpcService.php deleted file mode 100644 index 22596e68..00000000 --- a/niucloud/core/core/printer/sdk/yilianyun/api/RpcService.php +++ /dev/null @@ -1,19 +0,0 @@ -client = new YlyRpcClient($token, $config); - } - -} \ No newline at end of file diff --git a/niucloud/core/core/printer/sdk/yilianyun/config/YlyConfig.php b/niucloud/core/core/printer/sdk/yilianyun/config/YlyConfig.php deleted file mode 100644 index cdf00b9e..00000000 --- a/niucloud/core/core/printer/sdk/yilianyun/config/YlyConfig.php +++ /dev/null @@ -1,68 +0,0 @@ -clientId = $clientId; - $this->clientSecret = $clientSecret; - } - - public function getClientId() - { - return $this->clientId; - } - - - public function getClientSecret() - { - return $this->clientSecret; - } - - public function getRequestUrl() - { - return $this->requestUrl; - } - - public function setRequestUrl($requestUrl) - { - $this->requestUrl = $requestUrl; - } - - public function getLog() - { - return $this->log; - } - - public function setLog($log) - { - if (!method_exists($log, "info")) { - throw new InvalidArgumentException("logger need have method 'info(\$message)'"); - } - if (!method_exists($log, "error")) { - throw new InvalidArgumentException("logger need have method 'error(\$message)'"); - } - $this->log = $log; - } - -} diff --git a/niucloud/core/core/printer/sdk/yilianyun/demo/authorization_code_mode/callback.php b/niucloud/core/core/printer/sdk/yilianyun/demo/authorization_code_mode/callback.php deleted file mode 100644 index aa8786c3..00000000 --- a/niucloud/core/core/printer/sdk/yilianyun/demo/authorization_code_mode/callback.php +++ /dev/null @@ -1,141 +0,0 @@ -getToken($code); -} catch (Exception $e) { - echo $e->getMessage() . "\n"; - print_r(json_decode($e->getMessage(), true)); - return; -} - -$access_token = $token->access_token; //调用API凭证AccessToken -$refresh_token = $token->refresh_token; //刷新AccessToken凭证 失效时间35天 -$machine_code = $token->machine_code; //商户授权机器码 -$expires_in = $token->expires_in; //AccessToken失效时间30天 -$refresh_expires_in = $token->refresh_expires_in; //RefreshToken失效时间35天 -$origin_id = ''; //内部订单号(32位以内) - - -if (empty($machine_code)) { - echo 'The machine_code cannot be empty'; - return; -} - -if (empty($origin_id)) { - echo 'The origin_id cannot be empty'; - return; -} - -/**文本接口开始**/ -$print = new PrintService($access_token, $config); -//58mm排版 排版指令详情请看 http://doc2.10ss.net/332006 -$content = "
**#1 美团**
"; -$content .= str_repeat('.', 32); -$content .= "
--在线支付--
"; -$content .= "
张周兄弟烧烤
"; -$content .= "订单时间:" . date("Y-m-d H:i") . "\n"; -$content .= "订单编号:40807050607030\n"; -$content .= str_repeat('*', 14) . "商品" . str_repeat("*", 14); -$content .= ""; -$content .= ""; -$content .= ""; -$content .= ""; -$content .= ""; -$content .= ""; -$content .= "
烤土豆(超级辣)x35.96
烤豆干(超级辣)x23.88
烤鸡翅(超级辣)x317.96
烤排骨(香辣)x312.44
烤韭菜(超级辣)x38.96
"; -$content .= str_repeat('.', 32); -$content .= "这是二维码内容"; -$content .= "小计:¥82\n"; -$content .= "折扣:¥4 \n"; -$content .= str_repeat('*', 32); -$content .= "订单总价:¥78 \n"; -$content .= "
**#1 完**
"; - -try { - var_dump($print->index($machine_code, $content, $origin_id)); -} catch (Exception $e) { - echo $e->getMessage(); -} -/**文本接口结束**/ - - -///**图形接口开始**/ -//$picturePrint = new PicturePrintService($access_token, $config); -//$content = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1497000905083&di=7c3cffef1dd40edffbd0a37c4eabb277&imgtype=0&src=http://img1.touxiang.cn/uploads/20131114/14-054929_462.jpg"; -//try{ -// var_dump($picturePrint->index($machine_code, $content, $origin_id)); -//}catch (Exception $e) { -// echo $e->getMessage(); -//} -///**图形接口结束**/ - - -///**面单接口开始**/ //打印机型必须为k5; -//$expressPrint = new ExpressPrintService($access_token, $config); -//$content = array( -// "OrderCode"=> "0126578665784971", -// "ShipperCode"=> "SF", //SF YZPY HTKY YD -// "PayType"=> 1, -// "ExpType"=> 1, -// "Cost"=>6.0, -// "OtherCost"=> 7.0, -// "CustomerName" => '1264546', -// "CustomerPwd" => '4545454', -// "MonthCode" => '', -// "Sender"=> array( -// "Company" => "5645645", -// "Name" => "Taylor", -// "Mobile" => "15018442396", -// "ProvinceName" => "上海", -// "CityName" => "上海", -// "PostCode" => '61000', -// "ExpAreaName" => "青浦区", -// "Address" => "明珠路73号" -// ), -// "Receiver"=> array( -// "Company"=> "789789", -// "Name"=> "Yann", -// "Mobile"=> "15018442396", -// "ProvinceName"=> "北京", -// "CityName"=> "北京", -// "PostCode" => '61000', -// "ExpAreaName"=> "朝阳区", -// "Address"=> "三里屯街道雅秀大厦" -// ), -// "Commodity" => array( -// array( -// "GoodsName"=> "鞋子", -// ) -// ), -// "AddService"=> array( -// array( -// "Name"=> "COD", -// "Value"=> "1020", -// "CustomerID" => "44564" -// ) -// ), -// "StartDate" => date("y-M-d H:i:s",time() + 7200), -// "Weight"=> 1.0, -// "Quantity"=> 1, -// "Volume"=> 0.0, -// "Remark"=> "小心轻放", -//); -// -//try{ -// var_dump($expressPrint->index($machine_code, $content, $origin_id)); -//}catch (Exception $e) { -// echo $e->getMessage(); -//} -///**面单接口结束**/ diff --git a/niucloud/core/core/printer/sdk/yilianyun/demo/client_mode/callback.php b/niucloud/core/core/printer/sdk/yilianyun/demo/client_mode/callback.php deleted file mode 100644 index bba4a61e..00000000 --- a/niucloud/core/core/printer/sdk/yilianyun/demo/client_mode/callback.php +++ /dev/null @@ -1,136 +0,0 @@ -getToken(); -} catch (Exception $e) { - echo $e->getMessage() . "\n"; - print_r(json_decode($e->getMessage(), true)); - return; -} - -$access_token = $token->access_token; //调用API凭证AccessToken 永久有效,请妥善保存. -$refresh_token = $token->refresh_token; //刷新AccessToken凭证 失效时间35天 -$expires_in = $token->expires_in; //自有型应用可忽略此回调参数, AccessToken失效时间30天 -$refresh_expires_in = $token->refresh_expires_in; //自有型应用可忽略此回调参数, RefreshToken失效时间35天 -$machine_code = ''; //机器码 -$origin_id = ''; //内部订单号(32位以内) - -if (empty($machine_code)) { - echo 'The machine_code cannot be empty'; - return; -} - -if (empty($origin_id)) { - echo 'The origin_id cannot be empty'; - return; -} - - -/**文本接口开始**/ -$print = new PrintService($access_token, $config); -//58mm排版 排版指令详情请看 http://doc2.10ss.net/332006 -$content = "
**#1 美团**
"; -$content .= str_repeat('.', 32); -$content .= "
--在线支付--
"; -$content .= "
张周兄弟烧烤
"; -$content .= "订单时间:" . date("Y-m-d H:i") . "\n"; -$content .= "订单编号:40807050607030\n"; -$content .= str_repeat('*', 14) . "商品" . str_repeat("*", 14); -$content .= ""; -$content .= ""; -$content .= ""; -$content .= ""; -$content .= ""; -$content .= ""; -$content .= "
烤土豆(超级辣)x35.96
烤豆干(超级辣)x23.88
烤鸡翅(超级辣)x317.96
烤排骨(香辣)x312.44
烤韭菜(超级辣)x38.96
"; -$content .= str_repeat('.', 32); -$content .= "这是二维码内容"; -$content .= "小计:¥82\n"; -$content .= "折扣:¥4 \n"; -$content .= str_repeat('*', 32); -$content .= "订单总价:¥78 \n"; -$content .= "
**#1 完**
"; - -try { - var_dump($print->index($machine_code, $content, $origin_id)); -} catch (Exception $e) { - echo $e->getMessage(); -} -/**文本接口结束**/ - - -///**图形接口开始**/ -//$picturePrint = new PicturePrintService($access_token, $config); -//$content = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1497000905083&di=7c3cffef1dd40edffbd0a37c4eabb277&imgtype=0&src=http://img1.touxiang.cn/uploads/20131114/14-054929_462.jpg"; -//try{ -// var_dump($picturePrint->index($machine_code, $content, $origin_id)); -//}catch (Exception $e) { -// echo $e->getMessage(); -//} -///**图形接口结束**/ - - -///**面单接口开始**/ //打印机型必须为k5; -//$expressPrint = new ExpressPrintService($access_token, $config); -//$content = array( -// "OrderCode"=> "0126578665784971", -// "ShipperCode"=> "SF", //SF YZPY HTKY YD -// "PayType"=> 1, -// "ExpType"=> 1, -// "Cost"=>6.0, -// "OtherCost"=> 7.0, -// "CustomerName" => '1264546', -// "CustomerPwd" => '4545454', -// "MonthCode" => '', -// "Sender"=> array( -// "Company" => "5645645", -// "Name" => "Taylor", -// "Mobile" => "15018442396", -// "ProvinceName" => "上海", -// "CityName" => "上海", -// "PostCode" => '61000', -// "ExpAreaName" => "青浦区", -// "Address" => "明珠路73号" -// ), -// "Receiver"=> array( -// "Company"=> "789789", -// "Name"=> "Yann", -// "Mobile"=> "15018442396", -// "ProvinceName"=> "北京", -// "CityName"=> "北京", -// "PostCode" => '61000', -// "ExpAreaName"=> "朝阳区", -// "Address"=> "三里屯街道雅秀大厦" -// ), -// "Commodity" => array( -// array( -// "GoodsName"=> "鞋子", -// ) -// ), -// "AddService"=> array( -// array( -// "Name"=> "COD", -// "Value"=> "1020", -// "CustomerID" => "44564" -// ) -// ), -// "StartDate" => date("y-M-d H:i:s",time() + 7200), -// "Weight"=> 1.0, -// "Quantity"=> 1, -// "Volume"=> 0.0, -// "Remark"=> "小心轻放", -//); -// -//try{ -// var_dump($expressPrint->index($machine_code, $content, $origin_id)); -//}catch (Exception $e) { -// echo $e->getMessage(); -//} -///**面单接口结束**/ diff --git a/niucloud/core/core/printer/sdk/yilianyun/demo/index.php b/niucloud/core/core/printer/sdk/yilianyun/demo/index.php deleted file mode 100644 index 30cabdd0..00000000 --- a/niucloud/core/core/printer/sdk/yilianyun/demo/index.php +++ /dev/null @@ -1,11 +0,0 @@ -setRequestUrl('https://open-api.10ss.net/v2'); diff --git a/niucloud/core/core/printer/sdk/yilianyun/oauth/YlyOauthClient.php b/niucloud/core/core/printer/sdk/yilianyun/oauth/YlyOauthClient.php deleted file mode 100644 index ffc8510d..00000000 --- a/niucloud/core/core/printer/sdk/yilianyun/oauth/YlyOauthClient.php +++ /dev/null @@ -1,152 +0,0 @@ -clientId = $config->getClientId(); - $this->clientSecret = $config->getClientSecret(); - $this->requestUrl = $config->getRequestUrl(); - $this->log = $config->getLog(); - } - - - public function getToken($code = '') - { - $time = time(); - $params = array( - 'client_id' => $this->clientId, - 'timestamp' => $time, - 'sign' => $this->getSign($time), - 'id' => $this->uuid4(), - 'scope' => 'all' - ); - $params[ 'grant_type' ] = 'client_credentials'; - if (!empty($code)) { - $params[ 'code' ] = $code; - $params[ 'grant_type' ] = 'authorization_code'; - } - - $url = sprintf("%s/%s", $this->requestUrl, 'oauth/oauth'); - return $this->send($params, $url); - } - - - public function getTokenBySecret($machineCode, $secret, $secretType = 0) - { - $time = time(); - $params = array( - 'client_id' => $this->clientId, - 'timestamp' => $time, - 'sign' => $this->getSign($time), - 'id' => $this->uuid4(), - 'machine_code' => $machineCode, - 'scope' => 'all' - ); - if ($secretType == 1) { - $params[ 'qr_key' ] = $secret; - } else { - $params[ 'msign' ] = $secret; - } - - $url = sprintf("%s/%s", $this->requestUrl, 'oauth/scancodemodel'); - return $this->send($params, $url); - } - - public function refreshToken($refreshToken) - { - $time = time(); - $params = array( - 'client_id' => $this->clientId, - 'timestamp' => $time, - 'sign' => $this->getSign($time), - 'id' => $this->uuid4(), - 'scope' => 'all', - 'grant_type' => 'refresh_token', - 'refresh_token' => $refreshToken, - ); - - $url = sprintf("%s/%s", $this->requestUrl, 'oauth/oauth'); - return $this->send($params, $url); - } - - - public function getSign($timestamp) - { - return md5( - $this->clientId . - $timestamp . - $this->clientSecret - ); - } - - - public function uuid4() - { - mt_srand(mt_rand()); - $charid = strtolower(md5(uniqid(rand(), true))); - $hyphen = '-'; - $uuidV4 = - substr($charid, 0, 8) . $hyphen . - substr($charid, 8, 4) . $hyphen . - substr($charid, 12, 4) . $hyphen . - substr($charid, 16, 4) . $hyphen . - substr($charid, 20, 12); - return $uuidV4; - } - - - public function send($data, $url) - { - $requestInfo = http_build_query($data); - $log = $this->log; - if ($log != null) { - $log->info("request data: " . $requestInfo); - } - $curl = curl_init(); // 启动一个CURL会话 - curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址 - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检测 - curl_setopt($curl, CURLOPT_HTTPHEADER, array( 'Expect:' )); // 解决数据包大不能提交 - curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转 - curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer - curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求 - curl_setopt($curl, CURLOPT_POSTFIELDS, $requestInfo); // Post提交的数据包 - curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循 - curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容 - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回 - $requestResponse = curl_exec($curl); // 执行操作 - $response = json_decode($requestResponse); - if (curl_errno($curl)) { - if ($log != null) { - $log->error("error: " . curl_error($curl)); - } - throw new Exception(curl_error($curl)); - } - if (is_null($response)) { - throw new Exception("illegal response :" . $requestResponse); - } - - if ($response->error != 0 && $response->error_description != 'success') { - throw new Exception($response->error_description); - } - if ($this->log != null) { - $this->log->info("response: " . json_encode($response)); - } - curl_close($curl); // 关键CURL会话 - return $response->body; // 返回数据 - } - - -} diff --git a/niucloud/core/core/printer/sdk/yilianyun/protocol/YlyRpcClient.php b/niucloud/core/core/printer/sdk/yilianyun/protocol/YlyRpcClient.php deleted file mode 100644 index 4099af9b..00000000 --- a/niucloud/core/core/printer/sdk/yilianyun/protocol/YlyRpcClient.php +++ /dev/null @@ -1,104 +0,0 @@ -clientId = $config->getClientId(); - $this->clientSecret = $config->getClientSecret(); - $this->requestUrl = $config->getRequestUrl(); - $this->log = $config->getLog(); - $this->token = $token; - } - - - public function call($action, array $params) - { - $time = time(); - $params = array_merge(array( - 'client_id' => $this->clientId, - 'timestamp' => $time, - 'sign' => $this->getSign($time), - 'id' => $this->uuid4(), - 'access_token' => $this->token, - ), $params); - - $result = $this->send($params, $this->requestUrl . '/' . $action); - $response = json_decode($result, false, 512, JSON_BIGINT_AS_STRING); - - return $response; - } - - - public function getSign($timestamp) - { - return md5( - $this->clientId . - $timestamp . - $this->clientSecret - ); - } - - - public function uuid4() - { - mt_srand(mt_rand()); - $charid = strtolower(md5(uniqid(rand(), true))); - $hyphen = '-'; - $uuidV4 = - substr($charid, 0, 8) . $hyphen . - substr($charid, 8, 4) . $hyphen . - substr($charid, 12, 4) . $hyphen . - substr($charid, 16, 4) . $hyphen . - substr($charid, 20, 12); - return $uuidV4; - } - - - public function send($data, $url) - { - $requestInfo = http_build_query($data); - $log = $this->log; - if ($log != null) { - $log->info("request data: " . $requestInfo); - } - $curl = curl_init(); // 启动一个CURL会话 - curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址 - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检测 - curl_setopt($curl, CURLOPT_HTTPHEADER, array( 'Expect:' )); // 解决数据包大不能提交 - curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转 - curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer - curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求 - curl_setopt($curl, CURLOPT_POSTFIELDS, $requestInfo); // Post提交的数据包 - curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循 - curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容 - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回 - $response = curl_exec($curl); // 执行操作 - if (curl_errno($curl)) { - if ($log != null) { - $log->error("error: " . curl_error($curl)); - } - throw new Exception(curl_error($curl)); - } - if ($log != null) { - $log->info("response: " . $response); - } - curl_close($curl); // 关键CURL会话 - return $response; // 返回数据 - } - - -} diff --git a/niucloud/core/core/sms/Aliyun.php b/niucloud/core/core/sms/Aliyun.php deleted file mode 100644 index dc66a8ef..00000000 --- a/niucloud/core/core/sms/Aliyun.php +++ /dev/null @@ -1,98 +0,0 @@ -app_key = $config[ 'app_key' ] ?? ''; - $this->secret_key = $config[ 'secret_key' ] ?? ''; - $this->sign = $config[ 'sign' ] ?? ''; - } - - - /** - * 发送短信 - * @param string $mobile - * @param string $template_id - * @param array $data - * @return array - */ - public function send(string $mobile, string $template_id, array $data = []) - { - try { - AlibabaCloud::accessKeyClient($this->app_key, $this->secret_key) - ->regionId('cn-hangzhou') - ->asDefaultClient(); - $result = AlibabaCloud::rpcRequest() - ->product('Dysmsapi') - ->host('dysmsapi.aliyuncs.com') - ->version('2017-05-25') - ->action('SendSms') - ->method('POST') - ->debug(false) - ->options([ - 'query' => [ - 'PhoneNumbers' => $mobile, - 'SignName' => $this->sign, - 'TemplateCode' => $template_id, - 'TemplateParam' => json_encode($data, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE), - ], - ]) - ->request(); - - $res = $result->toArray(); - if (isset($res[ 'Code' ]) && $res[ 'Code' ] == 'OK') { - return $res; - } - $message = $res[ 'Message' ] ?? $res; - throw new NoticeException($message); - } catch (Exception $e) { - throw new NoticeException($e->getMessage()); - } - } - - public function modify(string $sign, string $mobile, string $code) - { - } - - public function template(int $page = 0, int $limit = 10, int $type = 1) - { - } - - public function apply(string $title, string $content, int $type) - { - } - - public function localTemplate(int $type, int $page, int $limit) - { - } - - public function record($id) - { - } -} \ No newline at end of file diff --git a/niucloud/core/core/sms/BaseSms.php b/niucloud/core/core/sms/BaseSms.php deleted file mode 100644 index 4559cf23..00000000 --- a/niucloud/core/core/sms/BaseSms.php +++ /dev/null @@ -1,83 +0,0 @@ -secret_id = $config[ 'secret_id' ] ?? ''; - $this->secret_key = $config[ 'secret_key' ] ?? ''; - $this->sign = $config[ 'sign' ] ?? ''; - $this->app_id = $config[ 'app_id' ] ?? ''; - } - - - /** - * 发送短信 - * @return bool|mixed - */ - public function send(string $mobile, string $template_id, array $data = []) - { - try { - $cred = new Credential($this->secret_id, $this->secret_key); - $httpProfile = new HttpProfile(); - $httpProfile->setEndpoint("sms.tencentcloudapi.com"); - - $clientProfile = new ClientProfile(); - $clientProfile->setHttpProfile($httpProfile); - - $client = new SmsClient($cred, 'ap-guangzhou', $clientProfile); - $params = [ - 'PhoneNumberSet' => [ '+86' . $mobile ], - 'TemplateID' => $template_id, - 'Sign' => $this->sign, - 'TemplateParamSet' => $data, - 'SmsSdkAppid' => $this->app_id, - ]; - $req = new SendSmsRequest(); - $req->fromJsonString(json_encode($params, JSON_THROW_ON_ERROR)); - $resp = json_decode($client->SendSms($req)->toJsonString(), true, 512, JSON_THROW_ON_ERROR); - if (isset($resp[ 'SendStatusSet' ]) && $resp[ 'SendStatusSet' ][ 0 ][ 'Code' ] == 'Ok') { - return $resp; - } else { - $message = $res[ 'SendStatusSet' ][ 0 ][ 'Message' ] ?? json_encode($resp, JSON_THROW_ON_ERROR); - throw new CommonException($message); - } - } catch (Exception $e) { - throw new NoticeException($e->getMessage()); - } - } - - - public function modify(string $sign, string $mobile, string $code) - { - } - - public function template(int $page = 0, int $limit = 15, int $type = 1) - { - } - - public function apply(string $title, string $content, int $type) - { - } - - public function localTemplate(int $type, int $page, int $limit) - { - } - - public function record($id) - { - } -} \ No newline at end of file diff --git a/niucloud/core/core/template/BaseTemplate.php b/niucloud/core/core/template/BaseTemplate.php deleted file mode 100644 index 73d5a978..00000000 --- a/niucloud/core/core/template/BaseTemplate.php +++ /dev/null @@ -1,60 +0,0 @@ -postJson('cgi-bin/message/subscribe/send', [ - 'template_id' => $data['template_id'], // 所需下发的订阅模板id - 'touser' => $data['openid'], // 接收者(用户)的 openid - 'page' => $data['page'], // 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 - 'data' => $data['data'], - ]); - } - - /** - * 添加模板消息 - * @param array $data - * @return array|Collection|object|ResponseInterface|string - * @throws GuzzleException - * @throws InvalidConfigException - */ - public function addTemplate(array $data) - { - $api = CoreWeappService::appApiClient(); - return $api->postJson('wxaapi/newtmpl/addtemplate', [ - 'tid' => $data['tid'], - 'kidList' => $data['kid_list'], - 'sceneDesc' => $data['scene_desc'], - ]); - } - - /** - * 删除 - * @param array $data - * @return array|Collection|object|ResponseInterface|string - * @throws GuzzleException - * @throws InvalidConfigException - */ - public function delete(array $data) - { - $api = CoreWeappService::appApiClient(); - return $api->postJson('wxaapi/newtmpl/deltemplate', [ - 'priTmplId' => $data['template_id'], - ]); - } - - /** - * 获取 - * @return void - */ - public function get() - { - - } -} diff --git a/niucloud/core/core/template/Wechat.php b/niucloud/core/core/template/Wechat.php deleted file mode 100644 index f9aea6f7..00000000 --- a/niucloud/core/core/template/Wechat.php +++ /dev/null @@ -1,111 +0,0 @@ - $v){ - $temp_data[$k] = ['value' => $v]; - } - - if (!empty($first)) $data[ 'first' ] = $first; - if (!empty($remark)) $data[ 'remark' ] = $remark; - $api = CoreWechatService::appApiClient(); - $param = [ - 'touser' => $openid, - 'template_id' => $template_id, - 'url' => $url, - 'miniprogram' => $miniprogram, - 'data' => $temp_data, - ]; - if(!empty($client_msg_id)){ - $param['client_msg_id'] = $client_msg_id; - } - return $api->postJson('cgi-bin/message/template/send', $param); - } - - /** - * 添加模板消息 - * @param array $data - * @return array|Collection|object|ResponseInterface|string - * @throws GuzzleException - * @throws InvalidConfigException - */ - public function addTemplate(array $data) - { - $api = CoreWechatService::appApiClient(); - return $api->postJson('cgi-bin/template/api_add_template', [ - 'template_id_short' => $data[ 'shortId' ], - 'keyword_name_list' => $data[ 'keyword_name_list' ] - ]); - } - - /** - * 删除 - * @param array $data - * @return array|Collection|object|ResponseInterface|string - * @throws GuzzleException - * @throws InvalidConfigException - */ - public function delete(array $data) - { - $api = CoreWechatService::appApiClient(); - - return $api->postJson('cgi-bin/template/del_private_template', [ - 'template_id' => $data[ 'templateId' ], - ]); - } - - /** - * 获取 - * @return void - */ - public function get() - { - - } -} diff --git a/niucloud/core/core/upload/Aliyun.php b/niucloud/core/core/upload/Aliyun.php deleted file mode 100644 index 238a4c97..00000000 --- a/niucloud/core/core/upload/Aliyun.php +++ /dev/null @@ -1,133 +0,0 @@ -config['access_key']; - $access_key_secret = $this->config['secret_key']; - - $endpoint = $this->config['endpoint'];// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。 - return new OssClient($access_key_id, $access_key_secret, $endpoint); - } - - /** - * 执行上传 - * @param string $dir - * @return true - */ - public function upload(string $dir) - { - $this->validate(); - $bucket = $this->config['bucket']; - try { - $this->client()->uploadFile( - $bucket, - $this->getFullPath($dir), - $this->getRealPath() - ); - return true; - } catch ( OssException $e ) { - throw new UploadFileException($e->getMessage()); - } - - } - - /** - * base64上云 - * @param string $base64_data - * @param string|null $key - * @return true - */ - public function base64(string $base64_data, ?string $key = null) - { - $bucket = $this->config['bucket']; - try { - $base64_file = base64_decode($base64_data); - if (!$base64_file) throw new UploadFileException('FILE_ERROR'); - $this->client()->putObject( - $bucket, - $key, - $base64_file - ); - return true; - } catch ( OssException $e ) { - throw new UploadFileException($e->getMessage()); - } - } - /** - * Notes: 抓取远程资源 - * @param string $url - * @param string|null $key - * @return true - */ - public function fetch(string $url, ?string $key = null) - { - $bucket = $this->config['bucket']; - try { - $content = file_get_contents($url); - $this->client()->putObject( - $bucket, - $key, - $content - ); - return true; - } catch ( OssException $e ) { - throw new UploadFileException($e->getMessage()); - } - - } - - /** - * 删除文件 - * @param string $file_name - * @return true - */ - public function delete(string $file_name) - { - $bucket = $this->config['bucket']; - try { - $this->client()->deleteObject($bucket, $file_name); - return true; - } catch ( OssException $e ) { - throw new UploadFileException($e->getMessage()); - } - - } - - public function thumb($file_path, $thumb_type) - { - $thumb_config = config('upload.thumb.thumb_type'); - $thumb_data = []; - foreach ($thumb_config as $k => $v) { - if ($thumb_type == 'all' || $thumb_type == $k || (is_array($thumb_type) && in_array($k, $thumb_type))) { - $width = $v['width']; - $height = $v['height']; - //拼装缩略路径 - $item_thumb = $file_path . '?x-oss-process=image/resize,h_' . $height . ',w_' . $width; - $thumb_data[$k] = $item_thumb; - } - } - - return $thumb_data; - } - -} diff --git a/niucloud/core/core/upload/BaseUpload.php b/niucloud/core/core/upload/BaseUpload.php deleted file mode 100644 index 6e367e7d..00000000 --- a/niucloud/core/core/upload/BaseUpload.php +++ /dev/null @@ -1,240 +0,0 @@ -config = $config; - $this->storage_type = $config['storage_type']; - } - - /** - * 附件上传 - * @param string $dir - * @return mixed - */ - abstract protected function upload(string $dir); - - /** - * 抓取远程附件 - * @param string $url - * @param string|null $key - * @return mixed - */ - abstract protected function fetch(string $url, ?string $key); - - /** - * base64文件上云 - * @param string $base64_data - * @param string|null $key - * @return mixed - */ - abstract protected function base64(string $base64_data, ?string $key = null); - /** - * 附件删除 - * @param string $file_name - * @return mixed - */ - abstract protected function delete(string $file_name); - - /** - * 缩略图 - * @param string $file_path - * @param $thumb_type - * @return mixed - */ - abstract protected function thumb(string $file_path, $thumb_type); - - /** - * 读取文件 - * @param string $name - * @param bool $is_rename - */ - public function read(string $name, bool $is_rename = true) - { - $this->name = $name; - $this->file = request()->file($name); - if (empty($this->file)) - throw new UploadFileException(100012); - $this->file_info = [ - 'name' => $this->file->getOriginalName(),//文件原始名称 - 'mime' => $this->file->getOriginalMime(),//上传文件类型信息 - 'real_path' => $this->file->getRealPath(),//上传文件真实路径 - 'ext' => $this->file->getOriginalExtension(),//上传文件后缀 - 'size' => $this->file->getSize(),//上传文件大小 - ]; - if ($is_rename) { - $this->file_name = $this->createFileName(); - } else { - $this->file_name = $this->file_info['name']; - } - - } - - /** - * 设置文件类型 - * @param string $type - * @return $this - */ - public function setType(string $type) - { - $this->type = $type; - return $this; - } - - /** - * 校验文件是否合法 - */ - public function check() - { - - } - - /** - * 生成新的文件名 - * @return string - */ - public function createFileName(string $key = '', string $ext = '') - { - //DIRECTORY_SEPARATOR 常量 - $storage_tag = '_' . $this->storage_type; - if (empty($key)) { - return time() . md5($this->file_info['real_path']) . $storage_tag . '.' . $this->file_info['ext']; - } else { - return time() . md5($key) . $storage_tag . '.' . $ext; - } - - } - - /** - * 获取原始附件信息 - * @return mixed - */ - public function getFileInfo() - { - return $this->file_info; - } - - /** - * 获取上传文件的真实完整路径 - * @return mixed - */ - public function getRealPath() - { - return $this->file_info['real_path']; - } - - /** - * 获取生成的文件完整地址 - * @return string - */ - public function getFullPath(string $dir = '') - { - return $this->full_path ?: $this->concatFullPath($dir); - } - - /** - * 合并路径和文件名 - * @param string $dir - * @return string - */ - public function concatFullPath(string $dir = '') - { - $this->full_path = implode('/', array_filter([$dir, $this->getFileName()])); - return $this->full_path; - } - - /** - * 获取文件名 - * @return mixed - */ - public function getFileName() - { - return $this->file_name; - } - - public function getUrl(string $path = '') - { - $path = !empty($path) ? $path : $this->getFullPath(); - $domain = $this->config['domain'] ?? ''; - $domain = empty($domain) ? '' : $domain . '/'; - return $domain . $path; - } - - /** - * 验证 - * @param array $validate - * @return $this - */ - public function setValidate(array $validate = []) - { - $this->validate = $validate ?: config('upload.rules')[$this->type] ?? []; - return $this; - } - - /** - * 根据上传文件的类型来校验文件是否符合配置 - * @return void - */ - public function validate() - { - if (empty($this->file)) - throw new UploadFileException('UPLOAD_FAIL'); - $config['file_ext'] = $this->validate['ext'] ?? []; - $config['file_mime'] = $this->validate['mime'] ?? []; - $config['file_size'] = $this->validate['size'] ?? 0; - $rule = []; - $file_size = $config['file_size'] ?? 0; - if ($file_size > 0) { - $rule[] = 'fileSize:' . $file_size; - } - //验证上传文件类型 - $file_mime = $config['file_mime'] ?? []; - $file_ext = $config['file_ext'] ?? []; - if (!empty($file_ext)) { - $rule[] = 'fileExt:' . implode(',', $file_ext); - } - if (!empty($rule)) { - if (!in_array($this->file->getOriginalMime(), $file_mime)) { - throw new UploadFileException('UPLOAD_TYPE_NOT_SUPPORT'); - } - validate([$this->name => implode('|', $rule)])->check([$this->name => $this->file]); - } - - } -} diff --git a/niucloud/core/core/upload/Local.php b/niucloud/core/core/upload/Local.php deleted file mode 100644 index 872baa30..00000000 --- a/niucloud/core/core/upload/Local.php +++ /dev/null @@ -1,253 +0,0 @@ - 'top-left', - 'top-center' => 'top-center', - 'top-right' => 'top-right', - 'center-left' => 'center-left', - 'center' => 'center', - 'center-right' => 'center-right', - 'bottom-left' => 'bottom-left', - 'bottom-center' => 'bottom-center', - 'bottom-right' => 'bottom-right', - ); - - protected function initialize(array $config = []) - { - parent::initialize($config); - - } - - public function upload(string $dir) - { - $this->validate(); - - mkdirs_or_notexist($dir, 0777); - $this->file->move($dir, $this->file_name); - //错误一般是已经被抛出了 - return true; - } - - - /** - * 远程获取图片 - * @param string $url - * @param string|null $key - * @return true - */ - public function fetch(string $url, ?string $key) - { - try { - mkdirs_or_notexist(dirname($key), 0777); - $ch = curl_init($url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - $content = curl_exec($ch); - curl_close($ch); - // $content = @file_get_contents($url);//file_get_contents下载网络图片慢,更换为curl下载 - if (!empty($content)) { - file_put_contents($key, $content); - - - $image_info = getimagesize($key); - $image_type = $image_info[2]; -// if($image_type == IMAGETYPE_JPEG){ -// // 保存图片为PNG格式 -// $image = imagecreatefromjpeg($key); -// }else if($image_type == IMAGETYPE_PNG){ -// // 保存图片为PNG格式 -// $image = imagecreatefrompng($key); -// } - if($image_type == IMAGETYPE_WEBP){ - // 保存图片为PNG格式 - $image = imagecreatefromwebp($key); - } - // 创建图片资源 - // 检查图片是否创建成功 - if (!empty($image)){ - - // 图片类型常量定义:IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_GIF - if ($image_type == IMAGETYPE_WEBP) { - $temp_arr = explode('.', $key); - $ext = end($temp_arr); - if($ext == 'jpg' || $ext == 'jpeg'){ - // 保存图片为PNG格式 - imagejpeg($image, $key); - }else if($ext = 'png'){ - // 保存图片为PNG格式 - imagepng($image, $key); - } - } - // 释放内存 - imagedestroy($image); - } - - } else { - throw new UploadFileException(203006); - } - return true; - } catch ( Exception $e ) { - throw new UploadFileException($e->getMessage()); - } - } - - /** - * base64转图片 - * @param string $content - * @param string|null $key - * @return true - */ - public function base64(string $content, ?string $key = null) - { - - mkdirs_or_notexist(dirname($key)); - file_put_contents(url_to_path($key), base64_decode($content)); - return true; - } - - /** - * 删除本地附件 - * @param string $file_name - * @return bool - */ - public function delete(string $file_name) - { - $file_path = url_to_path($file_name); - if (file_exists($file_path)) { - $result = unlink($file_path); -// throw new UploadFileException(100013); - }else{ - $result = true; - } - //顺便删除相关的缩略图 - $dirname = dirname($file_name); - $file_list = []; - search_dir($dirname, $file_list); - if(!empty($file_list)){ - $file_arr = explode('/', $file_name); - $only_file_name = end($file_arr); - foreach($file_list as $v){ - if(str_contains($v, $only_file_name) && file_exists($v)){ - unlink($v); - } - } - } - return $result; - } - - /** - * 缩略图 - * @param $file_path - * @param $thumb_type - * @return array - * @throws Exception - */ - public function thumb($file_path, $thumb_type) - { - //todo 判断缩略图是否存在 - $thumb_config = config('upload.thumb.thumb_type'); - // …… - //获取文件原名 获取 - $file_arr = explode('/', $file_path); - $file_name = end($file_arr); - $thumb_list = []; - //获取文件后缀 - foreach ($thumb_config as $k => $v) { - if ($thumb_type == 'all' || $thumb_type == $k || (is_array($thumb_type) && in_array($k, $thumb_type))) { - $new_width = $v['width']; - $new_height = $v['height']; - $new_thumb_path = str_replace($file_name, $new_width . 'x' . $new_height . '_' . $file_name, $file_path); - - if (!file_exists($new_thumb_path)) { - $editor = Grafika::createEditor(); - $editor->open($image, $file_path); - $editor->resizeFit($image, $new_width, $new_height); - //新缩略图文件名称 - $editor->save($image, $new_thumb_path, null, null, false, 0777); - } - $thumb_list[$k] = $new_thumb_path; - } - - } - return $thumb_list; - } - - /** - * 图片水印 - * @param $file_path - * @return mixed - * @throws Exception - */ - public function water($file_path) - { - $water_config = []; - if (!empty($water_config)) { - $status = $water_config['status'];//是否启用 - if ($status) { - $editor = Grafika::createEditor(); - $editor->open($image, $file_path); - if ($water_config['type'] == 'image') { - $water_image = $water_config['image']; - if (!empty($water_image)) { - //判断水印图片是否是本地图片 - if (check_file_is_remote($water_image)) { - $file_arr = explode('.', $water_image); - $ext_name = end($file_arr); - $name = $this->createFileName($water_image, $ext_name); - $watermark_image = 'upload/water/' . $name; - $this->fetch($water_image, $watermark_image); - } - if (file_exists($water_image)) { - - } - $editor->open($image1, $water_config['image']); - $editor->blend($image, $image1, 'normal', $water_config['opacity'], $this->position[$water_config['position']], $water_config['offset_x'], $water_config['offset_y']); - } - } else { - if ($water_config['text']) { - $position = $this->position[$water_config['position']]; - $offset_x = $water_config['offset_x'];//水平偏移值 - $offset_y = $water_config['offset_y'];//垂直偏移值 - $width = $image->getWidth(); - $height = $image->getHeight(); - - //获取文字信息 - $info = imagettfbbox($water_config['size'], $water_config['angle'], $water_config['font'], $water_config['text']); - $minx = min($info[0], $info[2], $info[4], $info[6]); - $maxx = max($info[0], $info[2], $info[4], $info[6]); - $miny = min($info[1], $info[3], $info[5], $info[7]); - $maxy = max($info[1], $info[3], $info[5], $info[7]); - /* 计算文字初始坐标和尺寸 */ - $x = $minx; - $y = abs($miny); - $w = $maxx - $minx; - $h = $maxy - $miny; - //转化坐标 - $position = new Position($position, $offset_x, $offset_y); - // Position is for $image2. $image1 is canvas. - list($offset_x, $offset_y) = $position->getXY($width, $height, $w, $h); - - $editor->text($image, $water_config['text'], $water_config['size'], $offset_x, $offset_y, new Color($water_config['color']), $water_config['font'], $water_config['angle']); - } - $editor->save($image, $file_path); - - - } - } - return $file_path; - } - } -} diff --git a/niucloud/core/core/upload/Qiniu.php b/niucloud/core/core/upload/Qiniu.php deleted file mode 100644 index ea3ecbdf..00000000 --- a/niucloud/core/core/upload/Qiniu.php +++ /dev/null @@ -1,180 +0,0 @@ - 'NorthWest', - 'top-center' => 'North', - 'top-right' => 'NorthEast', - 'center-left' => 'West', - 'center' => 'Center', - 'center-right' => 'East', - 'bottom-left' => 'SouthWest', - 'bottom-center' => 'South', - 'bottom-right' => 'SouthEast', - ); - - protected function initialize(array $config = []) - { - parent::initialize($config); - } - - /** - * 获取一个鉴权对象 - * @return Auth - */ - public function auth() - { - $access_key = $this->config['access_key']; - $secret_key = $this->config['secret_key']; - return new Auth($access_key, $secret_key); - } - - /** - * @throws Exception - */ - public function upload(string $dir) - { - $this->validate(); - $bucket = $this->config['bucket']; - //todo 这儿可以定义凭证的过期时间 - $up_token = $this->auth()->uploadToken($bucket); - // 初始化 UploadManager 对象并进行文件的上传。 - $upload_mgr = new UploadManager(); - [$ret, $err] = $upload_mgr->putFile($up_token, $this->getFullPath($dir), $this->getRealPath()); - if ($err !== null) - throw new UploadFileException($err->message()); - return true; - } - - /** - * 抓取网络资源到空间 - * @param string $url - * @param string|null $key - * @return true - * @throws Exception - */ - public function fetch(string $url, ?string $key = null) - { - $bucket = $this->config['bucket']; - $auth = $this->auth(); - if (!str_contains($url, 'http://') && !str_contains($url, 'https://')) { - $token = $auth->uploadToken($bucket); - $upload_mgr = new UploadManager(); - [$ret, $err] = $upload_mgr->putFile($token, $key, $url); - } else { - //抓取网络资源到空间 - $bucket_manager = new BucketManager($auth); - [$ret, $err] = $bucket_manager->fetch($url, $bucket, $key);//不指定key时,以文件内容的hash作为文件名 - } - - if ($err !== null) - throw new UploadFileException($err->message()); - return true; - } - - /** - * base64资源上传 - * @param string $base64_data - * @param string|null $key - * @return true - */ - public function base64(string $base64_data, ?string $key = null) - { - $bucket = $this->config['bucket']; - $auth = $this->auth(); - $up_token = $this->auth()->uploadToken($bucket); - // 初始化 UploadManager 对象并进行文件的上传。 - $upload_mgr = new UploadManager(); - //将 base64 编码的图片数据解码 - $base64_file = base64_decode($base64_data); - if (!$base64_file) throw new UploadFileException('FILE_ERROR'); - // 初始化 UpLoadManager 对象并进行文件的上传 - list($ret, $err) = $upload_mgr->put($up_token, $key, $base64_file); - if ($err !== null) throw new UploadFileException($err->message); - return true; - } - - /** - * 删除空间中的文件 - * @param string $file_name - * @return true - */ - public function delete(string $file_name) - { - $bucket = $this->config['bucket']; - $auth = $this->auth(); - $config = new Config(); - $bucket_manager = new BucketManager($auth, $config); - [$ret, $err] = $bucket_manager->delete($bucket, $file_name); - if ($err !== null) - throw new UploadFileException($err->message()); - return true; - } - - public function thumb($file_path, $thumb_type) - { -// mageView2/1/w/400/h/600/q/85 - $thumb_config = config('upload.thumb.thumb_type'); - $thumb_data = []; - foreach ($thumb_config as $k => $v) { - if ($thumb_type == 'all' || $thumb_type == $k || (is_array($thumb_type) && in_array($k, $thumb_type))) { -// ?x-oss-process=image/resize,m_fill,w_200,h_600,quality,q_60 - $width = $v['width']; - $height = $v['height']; - //拼装缩略路径 - $item_thumb = $file_path . '?imageView2/2/w/' . $width . '/h/' . $height; - $thumb_data[$k] = $item_thumb; - } - } - - return $thumb_data; - } - - - /** - * 图片水印 - * @param $file_path - * @return mixed - * @throws Exception - */ - public function water($file_path) - { - $water_config = []; - $water_path = $file_path; - if (!empty($water_config)) { - $status = $water_config['status'];//是否启用 - if ($status) { - //判断当前的云图片是否存在?,存在符号的话需要用|连接 - if (str_contains($file_path, '?')) { - $water_path .= '|watermark'; - } else { - $water_path .= '?watermark'; - } - if ($water_config['type'] == 'image') { - $water_image = $water_config['image']; - if (!empty($water_image)) { - $water_path .= '/1/image/' . base64_encode($water_image) . '/gravity/' . $this->position[$water_config['position']] . '/dissolve/' . $water_config['opacity'] . '/dx/' . $water_config['offset_x'] . '/dy/' . $water_config['offset_y']; - } - } else { - $water_path .= '/2/text/' . base64_encode($water_config['text']) . '/font/' . base64_encode($water_config['font']) . '/fill/' . base64_encode($water_config['color']) . '/fontsize/' . $water_config['size'] . '/gravity/' . $this->position[$water_config['position']] . '/dx/' . $water_config['offset_x'] . '/dy/' . $water_config['offset_y']; - } - } - } - return $water_path; - } - -} \ No newline at end of file diff --git a/niucloud/core/core/upload/Tencent.php b/niucloud/core/core/upload/Tencent.php deleted file mode 100644 index a5b03ceb..00000000 --- a/niucloud/core/core/upload/Tencent.php +++ /dev/null @@ -1,195 +0,0 @@ - 'northwest', - 'top-center' => 'north', - 'top-right' => 'northeast', - 'center-left' => 'west', - 'center' => 'center', - 'center-right' => 'east', - 'bottom-left' => 'southwest', - 'bottom-center' => 'south', - 'bottom-right' => 'southeast', - ); - - protected function initialize(array $config = []) - { - parent::initialize($config); - } - - /** - * 获取服务主体 - * @return Client - */ - public function client() - { - $secret_id = $this->config['access_key']; //替换为用户的 secretId,请登录访问管理控制台进行查看和管理,https://console.tencentcloud.com/cam/capi - $secret_key = $this->config['secret_key']; //替换为用户的 secretKey,请登录访问管理控制台进行查看和管理,https://console.tencentcloud.com/cam/capi - $region = $this->config['region']; //替换为用户的 region,已创建桶归属的region可以在控制台查看,https://console.tencentcloud.com/cos5/bucket - - return new Client( - array( - 'region' => $region, -// 'schema' => 'https', //协议头部,默认为http - 'credentials' => array( - 'secretId' => $secret_id, - 'secretKey' => $secret_key) - ) - ); - } - - - /** - * 执行上传 - * @param string $dir - * @return true - */ - public function upload(string $dir) - { - $this->validate(); - $bucket = $this->config['bucket']; - try { - $result = $this->client()->putObject(array( - 'Bucket' => $bucket, //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.tencentcloud.com/cos5/bucket - 'Key' => $this->getFullPath($dir), - 'Body' => fopen($this->getRealPath(), 'rb'), - )); - // 请求成功 - return true; - } catch ( Exception $e ) { - throw new UploadFileException($e->getMessage()); - } - } - - /** - * base文件上云 - * @param string $base64_data - * @param string|null $key - * @return true - */ - public function base64(string $base64_data, ?string $key = null) - { - $bucket = $this->config['bucket']; - try { - $base64_file = base64_decode($base64_data); - if (!$base64_file) throw new UploadFileException('FILE_ERROR'); - $result = $this->client()->putObject(array( - 'Bucket' => $bucket, //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.tencentcloud.com/cos5/bucket - 'Key' => $key, - 'Body' => $base64_file, - )); - // 请求成功 - return true; - } catch ( Exception $e ) { - throw new UploadFileException($e->getMessage()); - } - } - /** - * notes: 抓取远程资源(最大支持上传5G文件) - * @param string $url - * @param string|null $key - * @return true - */ - public function fetch(string $url, ?string $key = null) - { - - $bucket = $this->config['bucket']; - try { - $result = $this->client()->putObject(array( - 'Bucket' => $bucket, //存储桶名称,由BucketName-Appid 组成,可以在COS控制台查看 https://console.tencentcloud.com/cos5/bucket - 'Key' => $key, - 'Body' => fopen($url, 'rb'), - )); - // 请求成功 - return true; - } catch ( Exception $e ) { - throw new UploadFileException($e->getMessage()); - } - } - - /** - * 删除一个简单对象 - * @param string $file_name - * @return true - */ - public function delete(string $file_name) - { - $bucket = $this->config['bucket']; - try { - $this->client()->deleteObject(array( - 'Bucket' => $bucket, - 'Key' => $file_name - )); - return true; - } catch ( Exception $e ) { - throw new UploadFileException($e->getMessage()); - } - } - - public function thumb($file_path, $thumb_type) - { - //腾讯云缩略图地址 - - $thumb_config = config('upload.thumb.thumb_type'); - $thumb_data = []; - foreach ($thumb_config as $k => $v) { - if ($thumb_type == 'all' || $thumb_type == $k || (is_array($thumb_type) && in_array($k, $thumb_type))) { -// ?x-oss-process=image/resize,m_fill,w_200,h_600,quality,q_60 - $width = $v['width']; - $height = $v['height']; - //拼装缩略路径 - $item_thumb = $file_path . '?imageMogr2/thumbnail/' . $width . 'x' . $height; - $thumb_data[$k] = $item_thumb; - } - } - - return $thumb_data; - } - - - /** - * 图片水印 - * @param $file_path - * @return mixed - * @throws Exception - */ - public function water($file_path) - { - $water_config = []; - $water_path = $file_path; - if (!empty($water_config)) { - $status = $water_config['status'];//是否启用 - if($status){ - //判断当前的云图片是否存在?,存在符号的话需要用|连接 - if(str_contains($file_path, '?')){ - $water_path .= '&watermark'; - }else{ - $water_path .= '?watermark'; - } - if ($water_config['type'] == 'image') { - $water_image = $water_config['image']; - if(!empty($water_image)){ - //http://examples-1251000004.cos.ap-shanghai.myqcloud.com/sample.jpeg?watermark/1/image/aHR0cDovL2V4YW1wbGVzLTEyNTEwMDAwMDQucGljc2gubXlxY2xvdWQuY29tL3NodWl5aW4uanBn/gravity/southeast - $water_path .= '/1/image/' . base64_encode($water_image) . '/gravity/' . $this->position[$water_config['position']] . '/blogo/1/dx/' . $water_config['offset_x'] . '/dy/' . $water_config['offset_y'].'/dissolve/'.$water_config['opacity']; - } - } else { - //http://examples-1251000004.cos.ap-shanghai.myqcloud.com/sample.jpeg?q-sign-algorithm=&watermark/2/text/6IW-6K6v5LqRwrfkuIfosaHkvJjlm74/fill/IzNEM0QzRA/fontsize/20/dissolve/50/gravity/northeast/dx/20/dy/20/batch/1/degree/45 - $water_path .= '/2/text/' . base64_encode($water_config['text']) . '/font/' . base64_encode($water_config['font']) . '/fill/' . base64_encode($water_config['color']) . '/fontsize/' . $water_config['size'] . '/gravity/' . $this->position[$water_config['position']] . '/dx/' . $water_config['offset_x'] . '/dy/' . $water_config['offset_y']; - } - } - } - return $water_path; - } -} diff --git a/niucloud/core/core/upload/UploadLoader.php b/niucloud/core/core/upload/UploadLoader.php deleted file mode 100644 index 75175677..00000000 --- a/niucloud/core/core/upload/UploadLoader.php +++ /dev/null @@ -1,44 +0,0 @@ -color_black = new \BCGColor(0, 0, 0); - $this->color_white = new \BCGColor(255, 255, 255); - $this->size = $size; - $this->fontPath = str_replace("\\", "/", root_path() . "core/util/barcode/font/Arial.ttf"); - $this->font = new \BCGFontFile($this->fontPath, $this->size); - $this->content = $content; - } - - //生成条形码 - public function generateBarcode($path = '', $scale = 2) - { - try { - $code = new \BCGcode128(); - $code->setScale($scale); - $code->setThickness(30); // 条形码的厚度 - $code->setForegroundColor($this->color_black); // 条形码颜色 - $code->setBackgroundColor($this->color_white); // 空白间隙颜色 - $code->setFont($this->font); // - $code->parse($this->content); // 条形码需要的数据内容 - } catch (Exception $exception) { - $this->drawException = $exception; - } - - if ($path == '') { - $path = 'upload/barcode';//条形码存放路径 - } - - if (!is_dir($path)) { - $mode = intval('0777', 8); - mkdir($path, $mode, true); - chmod($path, $mode); - } - $path = $path . '/' . $this->content . '.png'; - if (file_exists($path)) { - unlink($path); - } - - //根据以上条件绘制条形码 - $drawing = new \BCGDrawing('', $this->color_white); - if ($this->drawException) { - $drawing->drawException($this->drawException); - } else { - $drawing->setBarcode($code); - $drawing->setFilename($path); - $drawing->draw(); - } - // 生成PNG格式的图片 - $drawing->finish(\BCGDrawing::IMG_FORMAT_PNG); - return $path; - } -} - -?> \ No newline at end of file diff --git a/niucloud/core/core/util/DbBackup.php b/niucloud/core/core/util/DbBackup.php deleted file mode 100644 index 5bad871b..00000000 --- a/niucloud/core/core/util/DbBackup.php +++ /dev/null @@ -1,532 +0,0 @@ - './backup/', - // 数据库备份卷大小 - 'part' => 20971520, - // 数据库备份文件是否启用压缩 0不压缩 1 压缩 - 'compress' => 0, - // 数据库备份文件压缩级别 1普通 4 一般 9最高 - 'level' => 9, - ); - - /** - * 数据库备份构造方法 - * @param array $file 备份或还原的文件信息 - * @param array $config 备份配置信息 - */ - public function __construct($config = []) - { - $this->config = is_array($config) && !empty($config) ? array_merge($this->config, $config) : $this->config; - //初始化文件名 - $this->setFile(); - //初始化数据库连接参数 - $this->setDbConn(); - //检查文件是否可写 - if (!$this->checkPath($this->config['path'])) { - throw new \Exception("The current directory is not writable"); - } - } - - /** - * 设置脚本运行超时时间 - * 0表示不限制,支持连贯操作 - */ - public function setTimeout($time = null) - { - if (!is_null($time)) { - set_time_limit($time) || ini_set("max_execution_time", $time); - } - return $this; - } - - /** - * 设置数据库连接必备参数 - * @param array $dbconfig 数据库连接配置信息 - * @return object - */ - public function setDbConn($dbconfig = []) - { - if (empty($dbconfig)) { - $this->dbconfig = config('database.connections.'.config('database.default')); - } else { - $this->dbconfig = $dbconfig; - } - return $this; - } - - /** - * 设置备份文件名 - * - * @param Array $file 文件名字 - * @return object - */ - public function setFile($file = null) - { - if (is_null($file)) { - $this->file = ['name' => date('Ymd-His'), 'part' => 1]; - } else { - if (!array_key_exists("name", $file) && !array_key_exists("part", $file)) { - $this->file = $file['1']; - } else { - $this->file = $file; - } - } - return $this; - } - - /** - * 数据库表列表 - * - * @param null $table - * @param int $type - * @return array - */ - public function dataList($table = null, $type = 1) - { - if (is_null($table)) { - $list = Db::query("SHOW TABLE STATUS"); - } else { - if ($type) { - $list = Db::query("SHOW FULL COLUMNS FROM {$table}"); - } else { - $list = Db::query("show columns from {$table}"); - } - } - - return array_map('array_change_key_case', $list); - } - - /** - * 数据库备份文件列表 - * - * @return array - */ - public function fileList() - { - if (!is_dir($this->config['path'])) { - mkdir($this->config['path'], 0755, true); - } - $path = realpath($this->config['path']); - $flag = \FilesystemIterator::KEY_AS_FILENAME; - $glob = new \FilesystemIterator($path, $flag); - $list = array(); - foreach ($glob as $name => $file) { - if (preg_match('/^\\d{8,8}-\\d{6,6}-\\d+\\.sql(?:\\.gz)?$/', $name)) { - $name1 = $name; - $name = sscanf($name, '%4s%2s%2s-%2s%2s%2s-%d'); - $date = "{$name[0]}-{$name[1]}-{$name[2]}"; - $time = "{$name[3]}:{$name[4]}:{$name[5]}"; - $part = $name[6]; - if (isset($list["{$date} {$time}"])) { - $info = $list["{$date} {$time}"]; - $info['part'] = max($info['part'], $part); - $info['size'] = $info['size'] + $file->getSize(); - } else { - $info['part'] = $part; - $info['size'] = $file->getSize(); - } - $extension = strtoupper(pathinfo($file->getFilename(), PATHINFO_EXTENSION)); - $info['name'] = $name1; - $info['compress'] = $extension === 'SQL' ? '-' : $extension; - $info['time'] = strtotime("{$date} {$time}"); - $list["{$date} {$time}"] = $info; - } - } - return $list; - } - - /** - * 获取文件名称 - * - * @param string $type - * @param int $time - * @return array|false|mixed|string - * @throws \Exception - */ - public function getFile($type = '', $time = 0) - { - // - if (!is_numeric($time)) { - throw new \Exception("{$time} Illegal data type"); - } - switch ($type) { - case 'time': - $name = date('Ymd-His', $time).'-*.sql*'; - $path = realpath($this->config['path']).DIRECTORY_SEPARATOR.$name; - return glob($path); - break; - case 'timeverif': - $name = date('Ymd-His', $time).'-*.sql*'; - $path = realpath($this->config['path']).DIRECTORY_SEPARATOR.$name; - $files = glob($path); - $list = array(); - foreach ($files as $name) { - $basename = basename($name); - $match = sscanf($basename, '%4s%2s%2s-%2s%2s%2s-%d'); - $gz = preg_match('/^\\d{8,8}-\\d{6,6}-\\d+\\.sql.gz$/', $basename); - $list[$match[6]] = array($match[6], $name, $gz); - } - $last = end($list); - if (count($list) === $last[0]) { - return $list; - } else { - throw new \Exception("File {$files['0']} may be damaged, please check again"); - } - break; - case 'pathname': - return "{$this->config['path']}{$this->file['name']}-{$this->file['part']}.sql"; - break; - case 'filename': - return "{$this->file['name']}-{$this->file['part']}.sql"; - break; - case 'filepath': - return $this->config['path']; - break; - default: - $arr = array( - 'pathname' => "{$this->config['path']}{$this->file['name']}-{$this->file['part']}.sql", - 'filename' => "{$this->file['name']}-{$this->file['part']}.sql", - 'filepath' => $this->config['path'], 'file' => $this->file - ); - return $arr; - } - } - - /** - * 删除备份文件 - * - * @param $time - * @return mixed - * @throws \Exception - */ - public function delFile($time) - { - if ($time) { - $file = $this->getFile('time', $time); - array_map("unlink", $file); - $file = $this->getFile('time', $time); - if (count($file)) { - throw new \Exception("File ".implode('##', $file)." deleted failed"); - } else { - return $time; - } - } else { - throw new \Exception("{$time} Time parameter is incorrect"); - } - } - - /** - * 下载备份 - * - * @param string $time - * @param integer $part - * @return array|mixed|string - */ - public function downloadFile($time, $part = 0) - { - $file = $this->getFile('time', $time); - $fileName = $file[$part]; - if (file_exists($fileName)) { - ob_end_clean(); - header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); - header('Content-Description: File Transfer'); - header('Content-Type: application/octet-stream'); - header('Content-Length: '.filesize($fileName)); - header('Content-Disposition: attachment; filename='.basename($fileName)); - readfile($fileName); - } else { - throw new \Exception("{$time} File is abnormal"); - } - } - - public function setSqlMode() { - Db::query("SET sql_mode = '';"); - return true; - } - - /** - * 导入表 - * - * @param $start - * @param $time - * @return array|false|int - * @throws Exception - */ - public function import($start, $time) - { - //还原数据 - $this->file = $this->getFile('time', $time); - if ($this->config['compress']) { - $gz = gzopen($this->file[0], 'r'); - $size = 0; - } else { - $size = filesize($this->file[0]); - $gz = fopen($this->file[0], 'r'); - } - $sql = ''; - if ($start) { - $this->config['compress'] ? gzseek($gz, $start) : fseek($gz, $start); - } - for ($i = 0; $i < 1000; $i++) { - $sql .= $this->config['compress'] ? gzgets($gz) : fgets($gz); - if (preg_match('/.*;$/', trim($sql))) { - if (false !== Db::query($sql)) { - $start += strlen($sql); - } else { - return false; - } - $sql = ''; - } elseif ($this->config['compress'] ? gzeof($gz) : feof($gz)) { - return 0; - } - } - return array($start, $size); - } - - /** - * 写入初始数据 - * - * @return boolean true - 写入成功,false - 写入失败 - */ - public function backupInit() - { - $sql = "-- -----------------------------\n"; - $sql .= "-- Think MySQL Data Transfer \n"; - $sql .= "-- \n"; - $sql .= "-- Host : ".$this->dbconfig['hostname']."\n"; - $sql .= "-- Port : ".$this->dbconfig['hostport']."\n"; - $sql .= "-- Database : ".$this->dbconfig['database']."\n"; - $sql .= "-- \n"; - $sql .= "-- Part : #{$this->file['part']}\n"; - $sql .= "-- Date : ".date("Y-m-d H:i:s")."\n"; - $sql .= "-- -----------------------------\n\n"; - $sql .= "SET FOREIGN_KEY_CHECKS = 0;\n\n"; - return $this->write($sql); - } - - /** - * 查询单条 - * @param $sql - * @return array|mixed - */ - public function selectOne($sql) { - $result = Db::query($sql); - return $result[0] ?? []; - } - - /** - * 备份表结构 - * - * @param string $table 表名 - * @param integer $start 起始行数 - * @return boolean false - 备份失败 - */ - public function backup($table, $start = 0) - { - // 备份表结构 - if (0 == $start) { - $result = $this->selectOne("SHOW CREATE TABLE `{$table}`"); - $sql = "\n"; - $sql .= "-- -----------------------------\n"; - $sql .= "-- Table structure for `{$table}`\n"; - $sql .= "-- -----------------------------\n"; - $sql .= "DROP TABLE IF EXISTS `{$table}`;\n"; - $sql .= trim($result['Create Table']).";\n\n"; - if (false === $this->write($sql)) { - return false; - } - } - //数据总数 - $result = $this->selectOne("SELECT COUNT(*) AS count FROM `{$table}`"); - $count = $result['count']; - //备份表数据 - if ($count) { - //写入数据注释 - if (0 == $start) { - $sql = "-- -----------------------------\n"; - $sql .= "-- Records of `{$table}`\n"; - $sql .= "-- -----------------------------\n"; - $this->write($sql); - } - //备份数据记录 - $result = Db::query("SELECT * FROM `{$table}` LIMIT {$start}, 1000"); - $sql = "INSERT INTO `{$table}` VALUES\n"; - foreach ($result as $index => $row) { - $row = array_map(function ($item){ - return is_string($item) ? addslashes($item) : $item; - }, $row); - $sql .= "('".str_replace(array("\r", "\n"), array('\\r', '\\n'), - implode("', '", $row))."')"; - $sql .= $index < (count($result) - 1) ? ",\n" : ";\n"; - } - - if (false === $this->write($sql)) { - return false; - } - //还有更多数据 - if ($count > $start + 1000) { - return $this->backup($table, $start + 1000); - } - } - //备份下一表 - return true; - } - - /** - * 优化表 - * - * @param String $tables 表名 - * @return String $tables - */ - public function optimize($tables = null) - { - if ($tables) { - if (is_array($tables)) { - $tables = implode('`,`', $tables); - $list = db ::select("OPTIMIZE TABLE `{$tables}`"); - } else { - $list = Db::query("OPTIMIZE TABLE `{$tables}`"); - } - if ($list) { - return $tables; - } else { - throw new \Exception("data sheet'{$tables}'Repair mistakes please try again!"); - } - } else { - throw new \Exception("Please specify the table to be repaired!"); - } - } - - /** - * 修复表 - * - * @param String $tables 表名 - * @return String $tables - */ - public function repair($tables = null) - { - if ($tables) { - if (is_array($tables)) { - $tables = implode('`,`', $tables); - $list = Db::query("REPAIR TABLE `{$tables}`"); - } else { - $list = Db::query("REPAIR TABLE `{$tables}`"); - } - if ($list) { - - return $list; - } else { - throw new \Exception("data sheet'{$tables}'Repair mistakes please try again!"); - } - } else { - throw new \Exception("Please specify the table to be repaired!"); - } - } - - /** - * 写入SQL语句 - * - * @param string $sql 要写入的SQL语句 - * @return boolean true - 写入成功,false - 写入失败! - */ - private function write($sql) - { - $size = strlen($sql); - //由于压缩原因,无法计算出压缩后的长度,这里假设压缩率为50%, - //一般情况压缩率都会高于50%; - $size = $this->config['compress'] ? $size / 2 : $size; - $this->open($size); - return $this->config['compress'] ? @gzwrite($this->fp, $sql) : @fwrite($this->fp, $sql); - } - - /** - * 打开一个卷,用于写入数据 - * - * @param integer $size 写入数据的大小 - */ - private function open($size) - { - if ($this->fp) { - $this->size += $size; - if ($this->size > $this->config['part']) { - $this->config['compress'] ? @gzclose($this->fp) : @fclose($this->fp); - $this->fp = null; - $this->file['part']++; - session('backup_file', $this->file); - $this->backupInit(); - } - } else { - $backuppath = $this->config['path']; - $filename = "{$backuppath}{$this->file['name']}-{$this->file['part']}.sql"; - if ($this->config['compress']) { - $filename = "{$filename}.gz"; - $this->fp = @gzopen($filename, "a{$this->config['level']}"); - } else { - $this->fp = @fopen($filename, 'a'); - } - $this->size = filesize($filename) + $size; - } - } - - /** - * 检查目录是否可写 - * - * @param string $path 目录 - * @return boolean - */ - protected function checkPath($path) - { - if (is_dir($path)) { - return true; - } - if (mkdir($path, 0755, true)) { - return true; - } else { - return false; - } - } - - /** - * 析构方法,用于关闭文件资源 - */ - public function __destruct() - { - if ($this->fp) { - $this->config['compress'] ? @gzclose($this->fp) : @fclose($this->fp); - } - } - -} diff --git a/niucloud/core/core/util/QRcode.php b/niucloud/core/core/util/QRcode.php deleted file mode 100644 index 52c92ce7..00000000 --- a/niucloud/core/core/util/QRcode.php +++ /dev/null @@ -1,3312 +0,0 @@ - - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - - -/* - * Version: 1.1.4 - * Build: 2010100721 - */ - - - -//---- qrconst.php ----------------------------- - - - - - -/* - * PHP QR Code encoder - * - * Common constants - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - // Encoding modes - - define('QR_MODE_NUL', -1); - define('QR_MODE_NUM', 0); - define('QR_MODE_AN', 1); - define('QR_MODE_8', 2); - define('QR_MODE_KANJI', 3); - define('QR_MODE_STRUCTURE', 4); - - // Levels of error correction. - - define('QR_ECLEVEL_L', 0); - define('QR_ECLEVEL_M', 1); - define('QR_ECLEVEL_Q', 2); - define('QR_ECLEVEL_H', 3); - - // Supported output formats - - define('QR_FORMAT_TEXT', 0); - define('QR_FORMAT_PNG', 1); - - class qrstr { - public static function set(&$srctab, $x, $y, $repl, $replLen = false) { - $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl)); - } - } - - - -//---- merged_config.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Config file, tuned-up for merged verion - */ - - define('QR_CACHEABLE', false); // use cache - more disk reads but less CPU power, masks and format templates are stored there - define('QR_CACHE_DIR', false); // used when QR_CACHEABLE === true - define('QR_LOG_DIR', false); // default error logs dir - - define('QR_FIND_BEST_MASK', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code - define('QR_FIND_FROM_RANDOM', 2); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly - define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false - - define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images - - - - -//---- qrtools.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Toolset, handy and debug utilites. - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - class QRtools { - - //---------------------------------------------------------------------- - public static function binarize($frame) - { - $len = count($frame); - foreach ($frame as &$frameLine) { - - for($i=0; $i<$len; $i++) { - $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0'; - } - } - - return $frame; - } - - //---------------------------------------------------------------------- - public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037') - { - $barcode_array = array(); - - if (!is_array($mode)) - $mode = explode(',', $mode); - - $eccLevel = 'L'; - - if (count($mode) > 1) { - $eccLevel = $mode[1]; - } - - $qrTab = QRcode::text($code, false, $eccLevel); - $size = count($qrTab); - - $barcode_array['num_rows'] = $size; - $barcode_array['num_cols'] = $size; - $barcode_array['bcode'] = array(); - - foreach ($qrTab as $line) { - $arrAdd = array(); - foreach(str_split($line) as $char) - $arrAdd[] = ($char=='1')?1:0; - $barcode_array['bcode'][] = $arrAdd; - } - - return $barcode_array; - } - - //---------------------------------------------------------------------- - public static function clearCache() - { - self::$frames = array(); - } - - //---------------------------------------------------------------------- - public static function buildCache() - { - QRtools::markTime('before_build_cache'); - - $mask = new QRmask(); - for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) { - $frame = QRspec::newFrame($a); - if (QR_IMAGE) { - $fileName = QR_CACHE_DIR.'frame_'.$a.'.png'; - QRimage::png(self::binarize($frame), $fileName, 1, 0); - } - - $width = count($frame); - $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); - for ($maskNo=0; $maskNo<8; $maskNo++) - $mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true); - } - - QRtools::markTime('after_build_cache'); - } - - //---------------------------------------------------------------------- - public static function log($outfile, $err) - { - if (QR_LOG_DIR !== false) { - if ($err != '') { - if ($outfile !== false) { - file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND); - } else { - file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND); - } - } - } - } - - //---------------------------------------------------------------------- - public static function dumpMask($frame) - { - $width = count($frame); - for($y=0;$y<$width;$y++) { - for($x=0;$x<$width;$x++) { - echo ord($frame[$y][$x]).','; - } - } - } - - //---------------------------------------------------------------------- - public static function markTime($markerId) - { - list($usec, $sec) = explode(" ", microtime()); - $time = ((float)$usec + (float)$sec); - - if (!isset($GLOBALS['qr_time_bench'])) - $GLOBALS['qr_time_bench'] = array(); - - $GLOBALS['qr_time_bench'][$markerId] = $time; - } - - //---------------------------------------------------------------------- - public static function timeBenchmark() - { - self::markTime('finish'); - - $lastTime = 0; - $startTime = 0; - $p = 0; - - echo ' - - '; - - foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) { - if ($p > 0) { - echo ''; - } else { - $startTime = $thisTime; - } - - $p++; - $lastTime = $thisTime; - } - - echo ' - - -
BENCHMARK
till '.$markerId.': '.number_format($thisTime-$lastTime, 6).'s
TOTAL: '.number_format($lastTime-$startTime, 6).'s
'; - } - - } - - //########################################################################## - - QRtools::markTime('start'); - - - - -//---- qrspec.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * QR Code specifications - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * The following data / specifications are taken from - * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) - * or - * "Automatic identification and data capture techniques -- - * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - define('QRSPEC_VERSION_MAX', 40); - define('QRSPEC_WIDTH_MAX', 177); - - define('QRCAP_WIDTH', 0); - define('QRCAP_WORDS', 1); - define('QRCAP_REMINDER', 2); - define('QRCAP_EC', 3); - - class QRspec { - - public static $capacity = array( - array( 0, 0, 0, array( 0, 0, 0, 0)), - array( 21, 26, 0, array( 7, 10, 13, 17)), // 1 - array( 25, 44, 7, array( 10, 16, 22, 28)), - array( 29, 70, 7, array( 15, 26, 36, 44)), - array( 33, 100, 7, array( 20, 36, 52, 64)), - array( 37, 134, 7, array( 26, 48, 72, 88)), // 5 - array( 41, 172, 7, array( 36, 64, 96, 112)), - array( 45, 196, 0, array( 40, 72, 108, 130)), - array( 49, 242, 0, array( 48, 88, 132, 156)), - array( 53, 292, 0, array( 60, 110, 160, 192)), - array( 57, 346, 0, array( 72, 130, 192, 224)), //10 - array( 61, 404, 0, array( 80, 150, 224, 264)), - array( 65, 466, 0, array( 96, 176, 260, 308)), - array( 69, 532, 0, array( 104, 198, 288, 352)), - array( 73, 581, 3, array( 120, 216, 320, 384)), - array( 77, 655, 3, array( 132, 240, 360, 432)), //15 - array( 81, 733, 3, array( 144, 280, 408, 480)), - array( 85, 815, 3, array( 168, 308, 448, 532)), - array( 89, 901, 3, array( 180, 338, 504, 588)), - array( 93, 991, 3, array( 196, 364, 546, 650)), - array( 97, 1085, 3, array( 224, 416, 600, 700)), //20 - array(101, 1156, 4, array( 224, 442, 644, 750)), - array(105, 1258, 4, array( 252, 476, 690, 816)), - array(109, 1364, 4, array( 270, 504, 750, 900)), - array(113, 1474, 4, array( 300, 560, 810, 960)), - array(117, 1588, 4, array( 312, 588, 870, 1050)), //25 - array(121, 1706, 4, array( 336, 644, 952, 1110)), - array(125, 1828, 4, array( 360, 700, 1020, 1200)), - array(129, 1921, 3, array( 390, 728, 1050, 1260)), - array(133, 2051, 3, array( 420, 784, 1140, 1350)), - array(137, 2185, 3, array( 450, 812, 1200, 1440)), //30 - array(141, 2323, 3, array( 480, 868, 1290, 1530)), - array(145, 2465, 3, array( 510, 924, 1350, 1620)), - array(149, 2611, 3, array( 540, 980, 1440, 1710)), - array(153, 2761, 3, array( 570, 1036, 1530, 1800)), - array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35 - array(161, 3034, 0, array( 600, 1120, 1680, 1980)), - array(165, 3196, 0, array( 630, 1204, 1770, 2100)), - array(169, 3362, 0, array( 660, 1260, 1860, 2220)), - array(173, 3532, 0, array( 720, 1316, 1950, 2310)), - array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40 - ); - - //---------------------------------------------------------------------- - public static function getDataLength($version, $level) - { - return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level]; - } - - //---------------------------------------------------------------------- - public static function getECCLength($version, $level) - { - return self::$capacity[$version][QRCAP_EC][$level]; - } - - //---------------------------------------------------------------------- - public static function getWidth($version) - { - return self::$capacity[$version][QRCAP_WIDTH]; - } - - //---------------------------------------------------------------------- - public static function getRemainder($version) - { - return self::$capacity[$version][QRCAP_REMINDER]; - } - - //---------------------------------------------------------------------- - public static function getMinimumVersion($size, $level) - { - - for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) { - $words = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level]; - if($words >= $size) - return $i; - } - - return -1; - } - - //###################################################################### - - public static $lengthTableBits = array( - array(10, 12, 14), - array( 9, 11, 13), - array( 8, 16, 16), - array( 8, 10, 12) - ); - - //---------------------------------------------------------------------- - public static function lengthIndicator($mode, $version) - { - if ($mode == QR_MODE_STRUCTURE) - return 0; - - if ($version <= 9) { - $l = 0; - } else if ($version <= 26) { - $l = 1; - } else { - $l = 2; - } - - return self::$lengthTableBits[$mode][$l]; - } - - //---------------------------------------------------------------------- - public static function maximumWords($mode, $version) - { - if($mode == QR_MODE_STRUCTURE) - return 3; - - if($version <= 9) { - $l = 0; - } else if($version <= 26) { - $l = 1; - } else { - $l = 2; - } - - $bits = self::$lengthTableBits[$mode][$l]; - $words = (1 << $bits) - 1; - - if($mode == QR_MODE_KANJI) { - $words *= 2; // the number of bytes is required - } - - return $words; - } - - // Error correction code ----------------------------------------------- - // Table of the error correction code (Reed-Solomon block) - // See Table 12-16 (pp.30-36), JIS X0510:2004. - - public static $eccTable = array( - array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)), - array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1 - array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), - array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)), - array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)), - array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5 - array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)), - array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)), - array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)), - array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)), - array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), //10 - array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)), - array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)), - array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)), - array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)), - array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), //15 - array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)), - array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)), - array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)), - array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)), - array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), //20 - array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)), - array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)), - array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)), - array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)), - array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), //25 - array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)), - array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)), - array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)), - array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)), - array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30 - array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)), - array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)), - array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)), - array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)), - array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), //35 - array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)), - array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)), - array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)), - array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)), - array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)),//40 - ); - - //---------------------------------------------------------------------- - // CACHEABLE!!! - - public static function getEccSpec($version, $level, array &$spec) - { - if (count($spec) < 5) { - $spec = array(0,0,0,0,0); - } - - $b1 = self::$eccTable[$version][$level][0]; - $b2 = self::$eccTable[$version][$level][1]; - $data = self::getDataLength($version, $level); - $ecc = self::getECCLength($version, $level); - - if($b2 == 0) { - $spec[0] = $b1; - $spec[1] = (int)($data / $b1); - $spec[2] = (int)($ecc / $b1); - $spec[3] = 0; - $spec[4] = 0; - } else { - $spec[0] = $b1; - $spec[1] = (int)($data / ($b1 + $b2)); - $spec[2] = (int)($ecc / ($b1 + $b2)); - $spec[3] = $b2; - $spec[4] = $spec[1] + 1; - } - } - - // Alignment pattern --------------------------------------------------- - - // Positions of alignment patterns. - // This array includes only the second and the third position of the - // alignment patterns. Rest of them can be calculated from the distance - // between them. - - // See Table 1 in Appendix E (pp.71) of JIS X0510:2004. - - public static $alignmentPattern = array( - array( 0, 0), - array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5 - array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10 - array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15 - array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20 - array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25 - array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30 - array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35 - array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40 - ); - - - /** -------------------------------------------------------------------- - * Put an alignment marker. - * @param frame - * @param width - * @param ox,oy center coordinate of the pattern - */ - public static function putAlignmentMarker(array &$frame, $ox, $oy) - { - $finder = array( - "\xa1\xa1\xa1\xa1\xa1", - "\xa1\xa0\xa0\xa0\xa1", - "\xa1\xa0\xa1\xa0\xa1", - "\xa1\xa0\xa0\xa0\xa1", - "\xa1\xa1\xa1\xa1\xa1" - ); - - $yStart = $oy-2; - $xStart = $ox-2; - - for($y=0; $y<5; $y++) { - QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]); - } - } - - //---------------------------------------------------------------------- - public static function putAlignmentPattern($version, &$frame, $width) - { - if($version < 2) - return; - - $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0]; - if($d < 0) { - $w = 2; - } else { - $w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2); - } - - if($w * $w - 3 == 1) { - $x = self::$alignmentPattern[$version][0]; - $y = self::$alignmentPattern[$version][0]; - self::putAlignmentMarker($frame, $x, $y); - return; - } - - $cx = self::$alignmentPattern[$version][0]; - for($x=1; $x<$w - 1; $x++) { - self::putAlignmentMarker($frame, 6, $cx); - self::putAlignmentMarker($frame, $cx, 6); - $cx += $d; - } - - $cy = self::$alignmentPattern[$version][0]; - for($y=0; $y<$w-1; $y++) { - $cx = self::$alignmentPattern[$version][0]; - for($x=0; $x<$w-1; $x++) { - self::putAlignmentMarker($frame, $cx, $cy); - $cx += $d; - } - $cy += $d; - } - } - - // Version information pattern ----------------------------------------- - - // Version information pattern (BCH coded). - // See Table 1 in Appendix D (pp.68) of JIS X0510:2004. - - // size: [QRSPEC_VERSION_MAX - 6] - - public static $versionPattern = array( - 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, - 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, - 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, - 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, - 0x27541, 0x28c69 - ); - - //---------------------------------------------------------------------- - public static function getVersionPattern($version) - { - if($version < 7 || $version > QRSPEC_VERSION_MAX) - return 0; - - return self::$versionPattern[$version -7]; - } - - // Format information -------------------------------------------------- - // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib) - - public static $formatInfo = array( - array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976), - array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0), - array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed), - array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b) - ); - - public static function getFormatInfo($mask, $level) - { - if($mask < 0 || $mask > 7) - return 0; - - if($level < 0 || $level > 3) - return 0; - - return self::$formatInfo[$level][$mask]; - } - - // Frame --------------------------------------------------------------- - // Cache of initial frames. - - public static $frames = array(); - - /** -------------------------------------------------------------------- - * Put a finder pattern. - * @param frame - * @param width - * @param ox,oy upper-left coordinate of the pattern - */ - public static function putFinderPattern(&$frame, $ox, $oy) - { - $finder = array( - "\xc1\xc1\xc1\xc1\xc1\xc1\xc1", - "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", - "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", - "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", - "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", - "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", - "\xc1\xc1\xc1\xc1\xc1\xc1\xc1" - ); - - for($y=0; $y<7; $y++) { - QRstr::set($frame, $ox, $oy+$y, $finder[$y]); - } - } - - //---------------------------------------------------------------------- - public static function createFrame($version) - { - $width = self::$capacity[$version][QRCAP_WIDTH]; - $frameLine = str_repeat ("\0", $width); - $frame = array_fill(0, $width, $frameLine); - - // Finder pattern - self::putFinderPattern($frame, 0, 0); - self::putFinderPattern($frame, $width - 7, 0); - self::putFinderPattern($frame, 0, $width - 7); - - // Separator - $yOffset = $width - 7; - - for($y=0; $y<7; $y++) { - $frame[$y][7] = "\xc0"; - $frame[$y][$width - 8] = "\xc0"; - $frame[$yOffset][7] = "\xc0"; - $yOffset++; - } - - $setPattern = str_repeat("\xc0", 8); - - QRstr::set($frame, 0, 7, $setPattern); - QRstr::set($frame, $width-8, 7, $setPattern); - QRstr::set($frame, 0, $width - 8, $setPattern); - - // Format info - $setPattern = str_repeat("\x84", 9); - QRstr::set($frame, 0, 8, $setPattern); - QRstr::set($frame, $width - 8, 8, $setPattern, 8); - - $yOffset = $width - 8; - - for($y=0; $y<8; $y++,$yOffset++) { - $frame[$y][8] = "\x84"; - $frame[$yOffset][8] = "\x84"; - } - - // Timing pattern - - for($i=1; $i<$width-15; $i++) { - $frame[6][7+$i] = chr(0x90 | ($i & 1)); - $frame[7+$i][6] = chr(0x90 | ($i & 1)); - } - - // Alignment pattern - self::putAlignmentPattern($version, $frame, $width); - - // Version information - if($version >= 7) { - $vinf = self::getVersionPattern($version); - - $v = $vinf; - - for($x=0; $x<6; $x++) { - for($y=0; $y<3; $y++) { - $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1)); - $v = $v >> 1; - } - } - - $v = $vinf; - for($y=0; $y<6; $y++) { - for($x=0; $x<3; $x++) { - $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1)); - $v = $v >> 1; - } - } - } - - // and a little bit... - $frame[$width - 8][8] = "\x81"; - - return $frame; - } - - //---------------------------------------------------------------------- - public static function debug($frame, $binary_mode = false) - { - if ($binary_mode) { - - foreach ($frame as &$frameLine) { - $frameLine = join('  ', explode('0', $frameLine)); - $frameLine = join('██', explode('1', $frameLine)); - } - - ?> - -


        '; - echo join("
        ", $frame); - echo '






'; - - } else { - - foreach ($frame as &$frameLine) { - $frameLine = join(' ', explode("\xc0", $frameLine)); - $frameLine = join('', explode("\xc1", $frameLine)); - $frameLine = join(' ', explode("\xa0", $frameLine)); - $frameLine = join('', explode("\xa1", $frameLine)); - $frameLine = join('', explode("\x84", $frameLine)); //format 0 - $frameLine = join('', explode("\x85", $frameLine)); //format 1 - $frameLine = join('', explode("\x81", $frameLine)); //special bit - $frameLine = join(' ', explode("\x90", $frameLine)); //clock 0 - $frameLine = join('', explode("\x91", $frameLine)); //clock 1 - $frameLine = join(' ', explode("\x88", $frameLine)); //version - $frameLine = join('', explode("\x89", $frameLine)); //version - $frameLine = join('♦', explode("\x01", $frameLine)); - $frameLine = join('⋅', explode("\0", $frameLine)); - } - - ?> - - "; - echo join("
", $frame); - echo "
"; - - } - } - - //---------------------------------------------------------------------- - public static function serial($frame) - { - return gzcompress(join("\n", $frame), 9); - } - - //---------------------------------------------------------------------- - public static function unserial($code) - { - return explode("\n", gzuncompress($code)); - } - - //---------------------------------------------------------------------- - public static function newFrame($version) - { - if($version < 1 || $version > QRSPEC_VERSION_MAX) - return null; - - if(!isset(self::$frames[$version])) { - - $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat'; - - if (QR_CACHEABLE) { - if (file_exists($fileName)) { - self::$frames[$version] = self::unserial(file_get_contents($fileName)); - } else { - self::$frames[$version] = self::createFrame($version); - file_put_contents($fileName, self::serial(self::$frames[$version])); - } - } else { - self::$frames[$version] = self::createFrame($version); - } - } - - if(is_null(self::$frames[$version])) - return null; - - return self::$frames[$version]; - } - - //---------------------------------------------------------------------- - public static function rsBlockNum($spec) { return $spec[0] + $spec[3]; } - public static function rsBlockNum1($spec) { return $spec[0]; } - public static function rsDataCodes1($spec) { return $spec[1]; } - public static function rsEccCodes1($spec) { return $spec[2]; } - public static function rsBlockNum2($spec) { return $spec[3]; } - public static function rsDataCodes2($spec) { return $spec[4]; } - public static function rsEccCodes2($spec) { return $spec[2]; } - public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); } - public static function rsEccLength($spec) { return ($spec[0] + $spec[3]) * $spec[2]; } - - } - - - -//---- qrimage.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Image output of code using GD2 - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - define('QR_IMAGE', true); - - class QRimage { - - //---------------------------------------------------------------------- - public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE) - { - $image = self::image($frame, $pixelPerPoint, $outerFrame); - - if ($filename === false) { - Header("Content-type: image/png"); - ImagePng($image); - } else { - if($saveandprint===TRUE){ - ImagePng($image, $filename); - header("Content-type: image/png"); - ImagePng($image); - }else{ - ImagePng($image, $filename); - } - } - - ImageDestroy($image); - } - - //---------------------------------------------------------------------- - public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85) - { - $image = self::image($frame, $pixelPerPoint, $outerFrame); - - if ($filename === false) { - Header("Content-type: image/jpeg"); - ImageJpeg($image, null, $q); - } else { - ImageJpeg($image, $filename, $q); - } - - ImageDestroy($image); - } - - //---------------------------------------------------------------------- - private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4) - { - $h = count($frame); - $w = strlen($frame[0]); - - $imgW = $w + 2*$outerFrame; - $imgH = $h + 2*$outerFrame; - - $base_image =ImageCreate($imgW, $imgH); - - $col[0] = ImageColorAllocate($base_image,255,255,255); - $col[1] = ImageColorAllocate($base_image,0,0,0); - - imagefill($base_image, 0, 0, $col[0]); - - for($y=0; $y<$h; $y++) { - for($x=0; $x<$w; $x++) { - if ($frame[$y][$x] == '1') { - ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]); - } - } - } - - $target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint); - ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH); - ImageDestroy($base_image); - - return $target_image; - } - } - - - -//---- qrinput.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Input encoding class - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - define('STRUCTURE_HEADER_BITS', 20); - define('MAX_STRUCTURED_SYMBOLS', 16); - - class QRinputItem { - - public $mode; - public $size; - public $data; - public $bstream; - - public function __construct($mode, $size, $data, $bstream = null) - { - $setData = array_slice($data, 0, $size); - - if (count($setData) < $size) { - $setData = array_merge($setData, array_fill(0,$size-count($setData),0)); - } - - if(!QRinput::check($mode, $size, $setData)) { - throw new \Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData)); - return null; - } - - $this->mode = $mode; - $this->size = $size; - $this->data = $setData; - $this->bstream = $bstream; - } - - //---------------------------------------------------------------------- - public function encodeModeNum($version) - { - try { - - $words = (int)($this->size / 3); - $bs = new QRbitstream(); - - $val = 0x1; - $bs->appendNum(4, $val); - $bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size); - - for($i=0; $i<$words; $i++) { - $val = (ord($this->data[$i*3 ]) - ord('0')) * 100; - $val += (ord($this->data[$i*3+1]) - ord('0')) * 10; - $val += (ord($this->data[$i*3+2]) - ord('0')); - $bs->appendNum(10, $val); - } - - if($this->size - $words * 3 == 1) { - $val = ord($this->data[$words*3]) - ord('0'); - $bs->appendNum(4, $val); - } else if($this->size - $words * 3 == 2) { - $val = (ord($this->data[$words*3 ]) - ord('0')) * 10; - $val += (ord($this->data[$words*3+1]) - ord('0')); - $bs->appendNum(7, $val); - } - - $this->bstream = $bs; - return 0; - - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - public function encodeModeAn($version) - { - try { - $words = (int)($this->size / 2); - $bs = new QRbitstream(); - - $bs->appendNum(4, 0x02); - $bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size); - - for($i=0; $i<$words; $i++) { - $val = (int)QRinput::lookAnTable(ord($this->data[$i*2 ])) * 45; - $val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1])); - - $bs->appendNum(11, $val); - } - - if($this->size & 1) { - $val = QRinput::lookAnTable(ord($this->data[$words * 2])); - $bs->appendNum(6, $val); - } - - $this->bstream = $bs; - return 0; - - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - public function encodeMode8($version) - { - try { - $bs = new QRbitstream(); - - $bs->appendNum(4, 0x4); - $bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size); - - for($i=0; $i<$this->size; $i++) { - $bs->appendNum(8, ord($this->data[$i])); - } - - $this->bstream = $bs; - return 0; - - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - public function encodeModeKanji($version) - { - try { - - $bs = new QRbitrtream(); - - $bs->appendNum(4, 0x8); - $bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2)); - - for($i=0; $i<$this->size; $i+=2) { - $val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]); - if($val <= 0x9ffc) { - $val -= 0x8140; - } else { - $val -= 0xc140; - } - - $h = ($val >> 8) * 0xc0; - $val = ($val & 0xff) + $h; - - $bs->appendNum(13, $val); - } - - $this->bstream = $bs; - return 0; - - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - public function encodeModeStructure() - { - try { - $bs = new QRbitstream(); - - $bs->appendNum(4, 0x03); - $bs->appendNum(4, ord($this->data[1]) - 1); - $bs->appendNum(4, ord($this->data[0]) - 1); - $bs->appendNum(8, ord($this->data[2])); - - $this->bstream = $bs; - return 0; - - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - public function estimateBitStreamSizeOfEntry($version) - { - $bits = 0; - - if($version == 0) - $version = 1; - - switch($this->mode) { - case QR_MODE_NUM: $bits = QRinput::estimateBitsModeNum($this->size); break; - case QR_MODE_AN: $bits = QRinput::estimateBitsModeAn($this->size); break; - case QR_MODE_8: $bits = QRinput::estimateBitsMode8($this->size); break; - case QR_MODE_KANJI: $bits = QRinput::estimateBitsModeKanji($this->size);break; - case QR_MODE_STRUCTURE: return STRUCTURE_HEADER_BITS; - default: - return 0; - } - - $l = QRspec::lengthIndicator($this->mode, $version); - $m = 1 << $l; - $num = (int)(($this->size + $m - 1) / $m); - - $bits += $num * (4 + $l); - - return $bits; - } - - //---------------------------------------------------------------------- - public function encodeBitStream($version) - { - try { - - unset($this->bstream); - $words = QRspec::maximumWords($this->mode, $version); - - if($this->size > $words) { - - $st1 = new QRinputItem($this->mode, $words, $this->data); - $st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words)); - - $st1->encodeBitStream($version); - $st2->encodeBitStream($version); - - $this->bstream = new QRbitstream(); - $this->bstream->append($st1->bstream); - $this->bstream->append($st2->bstream); - - unset($st1); - unset($st2); - - } else { - - $ret = 0; - - switch($this->mode) { - case QR_MODE_NUM: $ret = $this->encodeModeNum($version); break; - case QR_MODE_AN: $ret = $this->encodeModeAn($version); break; - case QR_MODE_8: $ret = $this->encodeMode8($version); break; - case QR_MODE_KANJI: $ret = $this->encodeModeKanji($version);break; - case QR_MODE_STRUCTURE: $ret = $this->encodeModeStructure(); break; - - default: - break; - } - - if($ret < 0) - return -1; - } - - return $this->bstream->size(); - - } catch (Exception $e) { - return -1; - } - } - }; - - //########################################################################## - - class QRinput { - - public $items; - - private $version; - private $level; - - //---------------------------------------------------------------------- - public function __construct($version = 0, $level = QR_ECLEVEL_L) - { - if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) { - throw new \Exception('Invalid version no'); - return NULL; - } - - $this->version = $version; - $this->level = $level; - } - - //---------------------------------------------------------------------- - public function getVersion() - { - return $this->version; - } - - //---------------------------------------------------------------------- - public function setVersion($version) - { - if($version < 0 || $version > QRSPEC_VERSION_MAX) { - throw new \Exception('Invalid version no'); - return -1; - } - - $this->version = $version; - - return 0; - } - - //---------------------------------------------------------------------- - public function getErrorCorrectionLevel() - { - return $this->level; - } - - //---------------------------------------------------------------------- - public function setErrorCorrectionLevel($level) - { - if($level > QR_ECLEVEL_H) { - throw new \Exception('Invalid ECLEVEL'); - return -1; - } - - $this->level = $level; - - return 0; - } - - //---------------------------------------------------------------------- - public function appendEntry(QRinputItem $entry) - { - $this->items[] = $entry; - } - - //---------------------------------------------------------------------- - public function append($mode, $size, $data) - { - try { - $entry = new QRinputItem($mode, $size, $data); - $this->items[] = $entry; - return 0; - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - - public function insertStructuredAppendHeader($size, $index, $parity) - { - if( $size > MAX_STRUCTURED_SYMBOLS ) { - throw new \Exception('insertStructuredAppendHeader wrong size'); - } - - if( $index <= 0 || $index > MAX_STRUCTURED_SYMBOLS ) { - throw new \Exception('insertStructuredAppendHeader wrong index'); - } - - $buf = array($size, $index, $parity); - - try { - $entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf); - array_unshift($this->items, $entry); - return 0; - } catch (Exception $e) { - return -1; - } - } - - //---------------------------------------------------------------------- - public function calcParity() - { - $parity = 0; - - foreach($this->items as $item) { - if($item->mode != QR_MODE_STRUCTURE) { - for($i=$item->size-1; $i>=0; $i--) { - $parity ^= $item->data[$i]; - } - } - } - - return $parity; - } - - //---------------------------------------------------------------------- - public static function checkModeNum($size, $data) - { - for($i=0; $i<$size; $i++) { - if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){ - return false; - } - } - - return true; - } - - //---------------------------------------------------------------------- - public static function estimateBitsModeNum($size) - { - $w = (int)$size / 3; - $bits = $w * 10; - - switch($size - $w * 3) { - case 1: - $bits += 4; - break; - case 2: - $bits += 7; - break; - default: - break; - } - - return $bits; - } - - //---------------------------------------------------------------------- - public static $anTable = array( - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - ); - - //---------------------------------------------------------------------- - public static function lookAnTable($c) - { - return (($c > 127)?-1:self::$anTable[$c]); - } - - //---------------------------------------------------------------------- - public static function checkModeAn($size, $data) - { - for($i=0; $i<$size; $i++) { - if (self::lookAnTable(ord($data[$i])) == -1) { - return false; - } - } - - return true; - } - - //---------------------------------------------------------------------- - public static function estimateBitsModeAn($size) - { - $w = (int)($size / 2); - $bits = $w * 11; - - if($size & 1) { - $bits += 6; - } - - return $bits; - } - - //---------------------------------------------------------------------- - public static function estimateBitsMode8($size) - { - return $size * 8; - } - - //---------------------------------------------------------------------- - public function estimateBitsModeKanji($size) - { - return (int)(($size / 2) * 13); - } - - //---------------------------------------------------------------------- - public static function checkModeKanji($size, $data) - { - if($size & 1) - return false; - - for($i=0; $i<$size; $i+=2) { - $val = (ord($data[$i]) << 8) | ord($data[$i+1]); - if( $val < 0x8140 - || ($val > 0x9ffc && $val < 0xe040) - || $val > 0xebbf) { - return false; - } - } - - return true; - } - - /*********************************************************************** - * Validation - **********************************************************************/ - - public static function check($mode, $size, $data) - { - if($size <= 0) - return false; - - switch($mode) { - case QR_MODE_NUM: return self::checkModeNum($size, $data); break; - case QR_MODE_AN: return self::checkModeAn($size, $data); break; - case QR_MODE_KANJI: return self::checkModeKanji($size, $data); break; - case QR_MODE_8: return true; break; - case QR_MODE_STRUCTURE: return true; break; - - default: - break; - } - - return false; - } - - - //---------------------------------------------------------------------- - public function estimateBitStreamSize($version) - { - $bits = 0; - - foreach($this->items as $item) { - $bits += $item->estimateBitStreamSizeOfEntry($version); - } - - return $bits; - } - - //---------------------------------------------------------------------- - public function estimateVersion() - { - $version = 0; - $prev = 0; - do { - $prev = $version; - $bits = $this->estimateBitStreamSize($prev); - $version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level); - if ($version < 0) { - return -1; - } - } while ($version > $prev); - - return $version; - } - - //---------------------------------------------------------------------- - public static function lengthOfCode($mode, $version, $bits) - { - $payload = $bits - 4 - QRspec::lengthIndicator($mode, $version); - switch($mode) { - case QR_MODE_NUM: - $chunks = (int)($payload / 10); - $remain = $payload - $chunks * 10; - $size = $chunks * 3; - if($remain >= 7) { - $size += 2; - } else if($remain >= 4) { - $size += 1; - } - break; - case QR_MODE_AN: - $chunks = (int)($payload / 11); - $remain = $payload - $chunks * 11; - $size = $chunks * 2; - if($remain >= 6) - $size++; - break; - case QR_MODE_8: - $size = (int)($payload / 8); - break; - case QR_MODE_KANJI: - $size = (int)(($payload / 13) * 2); - break; - case QR_MODE_STRUCTURE: - $size = (int)($payload / 8); - break; - default: - $size = 0; - break; - } - - $maxsize = QRspec::maximumWords($mode, $version); - if($size < 0) $size = 0; - if($size > $maxsize) $size = $maxsize; - - return $size; - } - - //---------------------------------------------------------------------- - public function createBitStream() - { - $total = 0; - - foreach($this->items as $item) { - $bits = $item->encodeBitStream($this->version); - - if($bits < 0) - return -1; - - $total += $bits; - } - - return $total; - } - - //---------------------------------------------------------------------- - public function convertData() - { - $ver = $this->estimateVersion(); - if($ver > $this->getVersion()) { - $this->setVersion($ver); - } - - for(;;) { - $bits = $this->createBitStream(); - - if($bits < 0) - return -1; - - $ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level); - if($ver < 0) { - throw new \Exception('WRONG VERSION'); - return -1; - } else if($ver > $this->getVersion()) { - $this->setVersion($ver); - } else { - break; - } - } - - return 0; - } - - //---------------------------------------------------------------------- - public function appendPaddingBit(&$bstream) - { - $bits = $bstream->size(); - $maxwords = QRspec::getDataLength($this->version, $this->level); - $maxbits = $maxwords * 8; - - if ($maxbits == $bits) { - return 0; - } - - if ($maxbits - $bits < 5) { - return $bstream->appendNum($maxbits - $bits, 0); - } - - $bits += 4; - $words = (int)(($bits + 7) / 8); - - $padding = new QRbitstream(); - $ret = $padding->appendNum($words * 8 - $bits + 4, 0); - - if($ret < 0) - return $ret; - - $padlen = $maxwords - $words; - - if($padlen > 0) { - - $padbuf = array(); - for($i=0; $i<$padlen; $i++) { - $padbuf[$i] = ($i&1)?0x11:0xec; - } - - $ret = $padding->appendBytes($padlen, $padbuf); - - if($ret < 0) - return $ret; - - } - - $ret = $bstream->append($padding); - - return $ret; - } - - //---------------------------------------------------------------------- - public function mergeBitStream() - { - if($this->convertData() < 0) { - return null; - } - - $bstream = new QRbitstream(); - - foreach($this->items as $item) { - $ret = $bstream->append($item->bstream); - if($ret < 0) { - return null; - } - } - - return $bstream; - } - - //---------------------------------------------------------------------- - public function getBitStream() - { - - $bstream = $this->mergeBitStream(); - - if($bstream == null) { - return null; - } - - $ret = $this->appendPaddingBit($bstream); - if($ret < 0) { - return null; - } - - return $bstream; - } - - //---------------------------------------------------------------------- - public function getByteStream() - { - $bstream = $this->getBitStream(); - if($bstream == null) { - return null; - } - - return $bstream->toByte(); - } - } - - - - - - -//---- qrbitstream.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Bitstream class - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - class QRbitstream { - - public $data = array(); - - //---------------------------------------------------------------------- - public function size() - { - return count($this->data); - } - - //---------------------------------------------------------------------- - public function allocate($setLength) - { - $this->data = array_fill(0, $setLength, 0); - return 0; - } - - //---------------------------------------------------------------------- - public static function newFromNum($bits, $num) - { - $bstream = new QRbitstream(); - $bstream->allocate($bits); - - $mask = 1 << ($bits - 1); - for($i=0; $i<$bits; $i++) { - if($num & $mask) { - $bstream->data[$i] = 1; - } else { - $bstream->data[$i] = 0; - } - $mask = $mask >> 1; - } - - return $bstream; - } - - //---------------------------------------------------------------------- - public static function newFromBytes($size, $data) - { - $bstream = new QRbitstream(); - $bstream->allocate($size * 8); - $p=0; - - for($i=0; $i<$size; $i++) { - $mask = 0x80; - for($j=0; $j<8; $j++) { - if($data[$i] & $mask) { - $bstream->data[$p] = 1; - } else { - $bstream->data[$p] = 0; - } - $p++; - $mask = $mask >> 1; - } - } - - return $bstream; - } - - //---------------------------------------------------------------------- - public function append(QRbitstream $arg) - { - if (is_null($arg)) { - return -1; - } - - if($arg->size() == 0) { - return 0; - } - - if($this->size() == 0) { - $this->data = $arg->data; - return 0; - } - - $this->data = array_values(array_merge($this->data, $arg->data)); - - return 0; - } - - //---------------------------------------------------------------------- - public function appendNum($bits, $num) - { - if ($bits == 0) - return 0; - - $b = QRbitstream::newFromNum($bits, $num); - - if(is_null($b)) - return -1; - - $ret = $this->append($b); - unset($b); - - return $ret; - } - - //---------------------------------------------------------------------- - public function appendBytes($size, $data) - { - if ($size == 0) - return 0; - - $b = QRbitstream::newFromBytes($size, $data); - - if(is_null($b)) - return -1; - - $ret = $this->append($b); - unset($b); - - return $ret; - } - - //---------------------------------------------------------------------- - public function toByte() - { - - $size = $this->size(); - - if($size == 0) { - return array(); - } - - $data = array_fill(0, (int)(($size + 7) / 8), 0); - $bytes = (int)($size / 8); - - $p = 0; - - for($i=0; $i<$bytes; $i++) { - $v = 0; - for($j=0; $j<8; $j++) { - $v = $v << 1; - $v |= $this->data[$p]; - $p++; - } - $data[$i] = $v; - } - - if($size & 7) { - $v = 0; - for($j=0; $j<($size & 7); $j++) { - $v = $v << 1; - $v |= $this->data[$p]; - $p++; - } - $data[$bytes] = $v; - } - - return $data; - } - - } - - - - -//---- qrsplit.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Input splitting classes - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * The following data / specifications are taken from - * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) - * or - * "Automatic identification and data capture techniques -- - * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - class QRsplit { - - public $dataStr = ''; - public $input; - public $modeHint; - - //---------------------------------------------------------------------- - public function __construct($dataStr, $input, $modeHint) - { - $this->dataStr = $dataStr; - $this->input = $input; - $this->modeHint = $modeHint; - } - - //---------------------------------------------------------------------- - public static function isdigitat($str, $pos) - { - if ($pos >= strlen($str)) - return false; - - return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9'))); - } - - //---------------------------------------------------------------------- - public static function isalnumat($str, $pos) - { - if ($pos >= strlen($str)) - return false; - - return (QRinput::lookAnTable(ord($str[$pos])) >= 0); - } - - //---------------------------------------------------------------------- - public function identifyMode($pos) - { - if ($pos >= strlen($this->dataStr)) - return QR_MODE_NUL; - - $c = $this->dataStr[$pos]; - - if(self::isdigitat($this->dataStr, $pos)) { - return QR_MODE_NUM; - } else if(self::isalnumat($this->dataStr, $pos)) { - return QR_MODE_AN; - } else if($this->modeHint == QR_MODE_KANJI) { - - if ($pos+1 < strlen($this->dataStr)) - { - $d = $this->dataStr[$pos+1]; - $word = (ord($c) << 8) | ord($d); - if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) { - return QR_MODE_KANJI; - } - } - } - - return QR_MODE_8; - } - - //---------------------------------------------------------------------- - public function eatNum() - { - $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); - - $p = 0; - while(self::isdigitat($this->dataStr, $p)) { - $p++; - } - - $run = $p; - $mode = $this->identifyMode($p); - - if($mode == QR_MODE_8) { - $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln - + QRinput::estimateBitsMode8(1) // + 4 + l8 - - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 - if($dif > 0) { - return $this->eat8(); - } - } - if($mode == QR_MODE_AN) { - $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln - + QRinput::estimateBitsModeAn(1) // + 4 + la - - QRinput::estimateBitsModeAn($run + 1);// - 4 - la - if($dif > 0) { - return $this->eatAn(); - } - } - - $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr)); - if($ret < 0) - return -1; - - return $run; - } - - //---------------------------------------------------------------------- - public function eatAn() - { - $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); - $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); - - $p = 0; - - while(self::isalnumat($this->dataStr, $p)) { - if(self::isdigitat($this->dataStr, $p)) { - $q = $p; - while(self::isdigitat($this->dataStr, $q)) { - $q++; - } - - $dif = QRinput::estimateBitsModeAn($p) // + 4 + la - + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln - - QRinput::estimateBitsModeAn($q); // - 4 - la - - if($dif < 0) { - break; - } else { - $p = $q; - } - } else { - $p++; - } - } - - $run = $p; - - if(!self::isalnumat($this->dataStr, $p)) { - $dif = QRinput::estimateBitsModeAn($run) + 4 + $la - + QRinput::estimateBitsMode8(1) // + 4 + l8 - - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 - if($dif > 0) { - return $this->eat8(); - } - } - - $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr)); - if($ret < 0) - return -1; - - return $run; - } - - //---------------------------------------------------------------------- - public function eatKanji() - { - $p = 0; - - while($this->identifyMode($p) == QR_MODE_KANJI) { - $p += 2; - } - - $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr)); - if($ret < 0) - return -1; - - return $run; - } - - //---------------------------------------------------------------------- - public function eat8() - { - $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); - $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); - - $p = 1; - $dataStrLen = strlen($this->dataStr); - - while($p < $dataStrLen) { - - $mode = $this->identifyMode($p); - if($mode == QR_MODE_KANJI) { - break; - } - if($mode == QR_MODE_NUM) { - $q = $p; - while(self::isdigitat($this->dataStr, $q)) { - $q++; - } - $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 - + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln - - QRinput::estimateBitsMode8($q); // - 4 - l8 - if($dif < 0) { - break; - } else { - $p = $q; - } - } else if($mode == QR_MODE_AN) { - $q = $p; - while(self::isalnumat($this->dataStr, $q)) { - $q++; - } - $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 - + QRinput::estimateBitsModeAn($q - $p) + 4 + $la - - QRinput::estimateBitsMode8($q); // - 4 - l8 - if($dif < 0) { - break; - } else { - $p = $q; - } - } else { - $p++; - } - } - - $run = $p; - $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr)); - - if($ret < 0) - return -1; - - return $run; - } - - //---------------------------------------------------------------------- - public function splitString() - { - while (strlen($this->dataStr) > 0) - { - if($this->dataStr == '') - return 0; - - $mode = $this->identifyMode(0); - - switch ($mode) { - case QR_MODE_NUM: $length = $this->eatNum(); break; - case QR_MODE_AN: $length = $this->eatAn(); break; - case QR_MODE_KANJI: - if ($hint == QR_MODE_KANJI) - $length = $this->eatKanji(); - else $length = $this->eat8(); - break; - default: $length = $this->eat8(); break; - - } - - if($length == 0) return 0; - if($length < 0) return -1; - - $this->dataStr = substr($this->dataStr, $length); - } - } - - //---------------------------------------------------------------------- - public function toUpper() - { - $stringLen = strlen($this->dataStr); - $p = 0; - - while ($p<$stringLen) { - $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint); - if($mode == QR_MODE_KANJI) { - $p += 2; - } else { - if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) { - $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32); - } - $p++; - } - } - - return $this->dataStr; - } - - //---------------------------------------------------------------------- - public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true) - { - if(is_null($string) || $string == '\0' || $string == '') { - throw new \Exception('empty string!!!'); - } - - $split = new QRsplit($string, $input, $modeHint); - - if(!$casesensitive) - $split->toUpper(); - - return $split->splitString(); - } - } - - - -//---- qrrscode.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Reed-Solomon error correction support - * - * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q - * (libfec is released under the GNU Lesser General Public License.) - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - class QRrsItem { - - public $mm; // Bits per symbol - public $nn; // Symbols per block (= (1<= $this->nn) { - $x -= $this->nn; - $x = ($x >> $this->mm) + ($x & $this->nn); - } - - return $x; - } - - //---------------------------------------------------------------------- - public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) - { - // Common code for intializing a Reed-Solomon control block (char or int symbols) - // Copyright 2004 Phil Karn, KA9Q - // May be used under the terms of the GNU Lesser General Public License (LGPL) - - $rs = null; - - // Check parameter ranges - if($symsize < 0 || $symsize > 8) return $rs; - if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs; - if($prim <= 0 || $prim >= (1<<$symsize)) return $rs; - if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values! - if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding - - $rs = new QRrsItem(); - $rs->mm = $symsize; - $rs->nn = (1<<$symsize)-1; - $rs->pad = $pad; - - $rs->alpha_to = array_fill(0, $rs->nn+1, 0); - $rs->index_of = array_fill(0, $rs->nn+1, 0); - - // PHP style macro replacement ;) - $NN =& $rs->nn; - $A0 =& $NN; - - // Generate Galois field lookup tables - $rs->index_of[0] = $A0; // log(zero) = -inf - $rs->alpha_to[$A0] = 0; // alpha**-inf = 0 - $sr = 1; - - for($i=0; $i<$rs->nn; $i++) { - $rs->index_of[$sr] = $i; - $rs->alpha_to[$i] = $sr; - $sr <<= 1; - if($sr & (1<<$symsize)) { - $sr ^= $gfpoly; - } - $sr &= $rs->nn; - } - - if($sr != 1){ - // field generator polynomial is not primitive! - $rs = NULL; - return $rs; - } - - /* Form RS code generator polynomial from its roots */ - $rs->genpoly = array_fill(0, $nroots+1, 0); - - $rs->fcr = $fcr; - $rs->prim = $prim; - $rs->nroots = $nroots; - $rs->gfpoly = $gfpoly; - - /* Find prim-th root of 1, used in decoding */ - for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn) - ; // intentional empty-body loop! - - $rs->iprim = (int)($iprim / $prim); - $rs->genpoly[0] = 1; - - for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) { - $rs->genpoly[$i+1] = 1; - - // Multiply rs->genpoly[] by @**(root + x) - for ($j = $i; $j > 0; $j--) { - if ($rs->genpoly[$j] != 0) { - $rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)]; - } else { - $rs->genpoly[$j] = $rs->genpoly[$j-1]; - } - } - // rs->genpoly[0] can never be zero - $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)]; - } - - // convert rs->genpoly[] to index form for quicker encoding - for ($i = 0; $i <= $nroots; $i++) - $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]]; - - return $rs; - } - - //---------------------------------------------------------------------- - public function encode_rs_char($data, &$parity) - { - $MM =& $this->mm; - $NN =& $this->nn; - $ALPHA_TO =& $this->alpha_to; - $INDEX_OF =& $this->index_of; - $GENPOLY =& $this->genpoly; - $NROOTS =& $this->nroots; - $FCR =& $this->fcr; - $PRIM =& $this->prim; - $IPRIM =& $this->iprim; - $PAD =& $this->pad; - $A0 =& $NN; - - $parity = array_fill(0, $NROOTS, 0); - - for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) { - - $feedback = $INDEX_OF[$data[$i] ^ $parity[0]]; - if($feedback != $A0) { - // feedback term is non-zero - - // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must - // always be for the polynomials constructed by init_rs() - $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback); - - for($j=1;$j<$NROOTS;$j++) { - $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])]; - } - } - - // Shift - array_shift($parity); - if($feedback != $A0) { - array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]); - } else { - array_push($parity, 0); - } - } - } - } - - //########################################################################## - - class QRrs { - - public static $items = array(); - - //---------------------------------------------------------------------- - public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) - { - foreach(self::$items as $rs) { - if($rs->pad != $pad) continue; - if($rs->nroots != $nroots) continue; - if($rs->mm != $symsize) continue; - if($rs->gfpoly != $gfpoly) continue; - if($rs->fcr != $fcr) continue; - if($rs->prim != $prim) continue; - - return $rs; - } - - $rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad); - array_unshift(self::$items, $rs); - - return $rs; - } - } - - - -//---- qrmask.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Masking - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - define('N1', 3); - define('N2', 3); - define('N3', 40); - define('N4', 10); - - class QRmask { - - public $runLength = array(); - - //---------------------------------------------------------------------- - public function __construct() - { - $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0); - } - - //---------------------------------------------------------------------- - public function writeFormatInformation($width, &$frame, $mask, $level) - { - $blacks = 0; - $format = QRspec::getFormatInfo($mask, $level); - - for($i=0; $i<8; $i++) { - if($format & 1) { - $blacks += 2; - $v = 0x85; - } else { - $v = 0x84; - } - - $frame[8][$width - 1 - $i] = chr($v); - if($i < 6) { - $frame[$i][8] = chr($v); - } else { - $frame[$i + 1][8] = chr($v); - } - $format = $format >> 1; - } - - for($i=0; $i<7; $i++) { - if($format & 1) { - $blacks += 2; - $v = 0x85; - } else { - $v = 0x84; - } - - $frame[$width - 7 + $i][8] = chr($v); - if($i == 0) { - $frame[8][7] = chr($v); - } else { - $frame[8][6 - $i] = chr($v); - } - - $format = $format >> 1; - } - - return $blacks; - } - - //---------------------------------------------------------------------- - public function mask0($x, $y) { return ($x+$y)&1; } - public function mask1($x, $y) { return ($y&1); } - public function mask2($x, $y) { return ($x%3); } - public function mask3($x, $y) { return ($x+$y)%3; } - public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; } - public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3; } - public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1; } - public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1; } - - //---------------------------------------------------------------------- - private function generateMaskNo($maskNo, $width, $frame) - { - $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); - - for($y=0; $y<$width; $y++) { - for($x=0; $x<$width; $x++) { - if(ord($frame[$y][$x]) & 0x80) { - $bitMask[$y][$x] = 0; - } else { - $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y); - $bitMask[$y][$x] = ($maskFunc == 0)?1:0; - } - - } - } - - return $bitMask; - } - - //---------------------------------------------------------------------- - public static function serial($bitFrame) - { - $codeArr = array(); - - foreach ($bitFrame as $line) - $codeArr[] = join('', $line); - - return gzcompress(join("\n", $codeArr), 9); - } - - //---------------------------------------------------------------------- - public static function unserial($code) - { - $codeArr = array(); - - $codeLines = explode("\n", gzuncompress($code)); - foreach ($codeLines as $line) - $codeArr[] = str_split($line); - - return $codeArr; - } - - //---------------------------------------------------------------------- - public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false) - { - $b = 0; - $bitMask = array(); - - $fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat'; - - if (QR_CACHEABLE) { - if (file_exists($fileName)) { - $bitMask = self::unserial(file_get_contents($fileName)); - } else { - $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); - if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo)) - mkdir(QR_CACHE_DIR.'mask_'.$maskNo); - file_put_contents($fileName, self::serial($bitMask)); - } - } else { - $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); - } - - if ($maskGenOnly) - return; - - $d = $s; - - for($y=0; $y<$width; $y++) { - for($x=0; $x<$width; $x++) { - if($bitMask[$y][$x] == 1) { - $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]); - } - $b += (int)(ord($d[$y][$x]) & 1); - } - } - - return $b; - } - - //---------------------------------------------------------------------- - public function makeMask($width, $frame, $maskNo, $level) - { - $masked = array_fill(0, $width, str_repeat("\0", $width)); - $this->makeMaskNo($maskNo, $width, $frame, $masked); - $this->writeFormatInformation($width, $masked, $maskNo, $level); - - return $masked; - } - - //---------------------------------------------------------------------- - public function calcN1N3($length) - { - $demerit = 0; - - for($i=0; $i<$length; $i++) { - - if($this->runLength[$i] >= 5) { - $demerit += (N1 + ($this->runLength[$i] - 5)); - } - if($i & 1) { - if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) { - $fact = (int)($this->runLength[$i] / 3); - if(($this->runLength[$i-2] == $fact) && - ($this->runLength[$i-1] == $fact) && - ($this->runLength[$i+1] == $fact) && - ($this->runLength[$i+2] == $fact)) { - if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) { - $demerit += N3; - } else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) { - $demerit += N3; - } - } - } - } - } - return $demerit; - } - - //---------------------------------------------------------------------- - public function evaluateSymbol($width, $frame) - { - $head = 0; - $demerit = 0; - - for($y=0; $y<$width; $y++) { - $head = 0; - $this->runLength[0] = 1; - - $frameY = $frame[$y]; - - if ($y>0) - $frameYM = $frame[$y-1]; - - for($x=0; $x<$width; $x++) { - if(($x > 0) && ($y > 0)) { - $b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]); - $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]); - - if(($b22 | ($w22 ^ 1))&1) { - $demerit += N2; - } - } - if(($x == 0) && (ord($frameY[$x]) & 1)) { - $this->runLength[0] = -1; - $head = 1; - $this->runLength[$head] = 1; - } else if($x > 0) { - if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) { - $head++; - $this->runLength[$head] = 1; - } else { - $this->runLength[$head]++; - } - } - } - - $demerit += $this->calcN1N3($head+1); - } - - for($x=0; $x<$width; $x++) { - $head = 0; - $this->runLength[0] = 1; - - for($y=0; $y<$width; $y++) { - if($y == 0 && (ord($frame[$y][$x]) & 1)) { - $this->runLength[0] = -1; - $head = 1; - $this->runLength[$head] = 1; - } else if($y > 0) { - if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) { - $head++; - $this->runLength[$head] = 1; - } else { - $this->runLength[$head]++; - } - } - } - - $demerit += $this->calcN1N3($head+1); - } - - return $demerit; - } - - - //---------------------------------------------------------------------- - public function mask($width, $frame, $level) - { - $minDemerit = PHP_INT_MAX; - $bestMaskNum = 0; - $bestMask = array(); - - $checked_masks = array(0,1,2,3,4,5,6,7); - - if (QR_FIND_FROM_RANDOM !== false) { - - $howManuOut = 8-(QR_FIND_FROM_RANDOM % 9); - for ($i = 0; $i < $howManuOut; $i++) { - $remPos = rand (0, count($checked_masks)-1); - unset($checked_masks[$remPos]); - $checked_masks = array_values($checked_masks); - } - - } - - $bestMask = $frame; - - foreach($checked_masks as $i) { - $mask = array_fill(0, $width, str_repeat("\0", $width)); - - $demerit = 0; - $blacks = 0; - $blacks = $this->makeMaskNo($i, $width, $frame, $mask); - $blacks += $this->writeFormatInformation($width, $mask, $i, $level); - $blacks = (int)(100 * $blacks / ($width * $width)); - $demerit = (int)((int)(abs($blacks - 50) / 5) * N4); - $demerit += $this->evaluateSymbol($width, $mask); - - if($demerit < $minDemerit) { - $minDemerit = $demerit; - $bestMask = $mask; - $bestMaskNum = $i; - } - } - - return $bestMask; - } - - //---------------------------------------------------------------------- - } - - - - -//---- qrencode.php ----------------------------- - - - - -/* - * PHP QR Code encoder - * - * Main encoder classes. - * - * Based on libqrencode C library distributed under LGPL 2.1 - * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi - * - * PHP QR Code is distributed under LGPL 3 - * Copyright (C) 2010 Dominik Dzienia - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - class QRrsblock { - public $dataLength; - public $data = array(); - public $eccLength; - public $ecc = array(); - - public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs) - { - $rs->encode_rs_char($data, $ecc); - - $this->dataLength = $dl; - $this->data = $data; - $this->eccLength = $el; - $this->ecc = $ecc; - } - }; - - //########################################################################## - - class QRrawcode { - public $version; - public $datacode = array(); - public $ecccode = array(); - public $blocks; - public $rsblocks = array(); //of RSblock - public $count; - public $dataLength; - public $eccLength; - public $b1; - - //---------------------------------------------------------------------- - public function __construct(QRinput $input) - { - $spec = array(0,0,0,0,0); - - $this->datacode = $input->getByteStream(); - if(is_null($this->datacode)) { - throw new \Exception('null imput string'); - } - - QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec); - - $this->version = $input->getVersion(); - $this->b1 = QRspec::rsBlockNum1($spec); - $this->dataLength = QRspec::rsDataLength($spec); - $this->eccLength = QRspec::rsEccLength($spec); - $this->ecccode = array_fill(0, $this->eccLength, 0); - $this->blocks = QRspec::rsBlockNum($spec); - - $ret = $this->init($spec); - if($ret < 0) { - throw new \Exception('block alloc error'); - return null; - } - - $this->count = 0; - } - - //---------------------------------------------------------------------- - public function init(array $spec) - { - $dl = QRspec::rsDataCodes1($spec); - $el = QRspec::rsEccCodes1($spec); - $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); - - - $blockNo = 0; - $dataPos = 0; - $eccPos = 0; - for($i=0; $iecccode,$eccPos); - $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); - $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); - - $dataPos += $dl; - $eccPos += $el; - $blockNo++; - } - - if(QRspec::rsBlockNum2($spec) == 0) - return 0; - - $dl = QRspec::rsDataCodes2($spec); - $el = QRspec::rsEccCodes2($spec); - $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); - - if($rs == NULL) return -1; - - for($i=0; $iecccode,$eccPos); - $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); - $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); - - $dataPos += $dl; - $eccPos += $el; - $blockNo++; - } - - return 0; - } - - //---------------------------------------------------------------------- - public function getCode() - { - $ret; - - if($this->count < $this->dataLength) { - $row = $this->count % $this->blocks; - $col = $this->count / $this->blocks; - if($col >= $this->rsblocks[0]->dataLength) { - $row += $this->b1; - } - $ret = $this->rsblocks[$row]->data[$col]; - } else if($this->count < $this->dataLength + $this->eccLength) { - $row = ($this->count - $this->dataLength) % $this->blocks; - $col = ($this->count - $this->dataLength) / $this->blocks; - $ret = $this->rsblocks[$row]->ecc[$col]; - } else { - return 0; - } - $this->count++; - - return $ret; - } - } - - //########################################################################## - - class QRcode { - - public $version; - public $width; - public $data; - - //---------------------------------------------------------------------- - public function encodeMask(QRinput $input, $mask) - { - if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) { - throw new \Exception('wrong version'); - } - if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) { - throw new \Exception('wrong level'); - } - - $raw = new QRrawcode($input); - - QRtools::markTime('after_raw'); - - $version = $raw->version; - $width = QRspec::getWidth($version); - $frame = QRspec::newFrame($version); - - $filler = new FrameFiller($width, $frame); - if(is_null($filler)) { - return NULL; - } - - // inteleaved data and ecc codes - for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) { - $code = $raw->getCode(); - $bit = 0x80; - for($j=0; $j<8; $j++) { - $addr = $filler->next(); - $filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0)); - $bit = $bit >> 1; - } - } - - QRtools::markTime('after_filler'); - - unset($raw); - - // remainder bits - $j = QRspec::getRemainder($version); - for($i=0; $i<$j; $i++) { - $addr = $filler->next(); - $filler->setFrameAt($addr, 0x02); - } - - $frame = $filler->frame; - unset($filler); - - - // masking - $maskObj = new QRmask(); - if($mask < 0) { - - if (QR_FIND_BEST_MASK) { - $masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel()); - } else { - $masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel()); - } - } else { - $masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel()); - } - - if($masked == NULL) { - return NULL; - } - - QRtools::markTime('after_mask'); - - $this->version = $version; - $this->width = $width; - $this->data = $masked; - - return $this; - } - - //---------------------------------------------------------------------- - public function encodeInput(QRinput $input) - { - return $this->encodeMask($input, -1); - } - - //---------------------------------------------------------------------- - public function encodeString8bit($string, $version, $level) - { - if(string == NULL) { - throw new \Exception('empty string!'); - return NULL; - } - - $input = new QRinput($version, $level); - if($input == NULL) return NULL; - - $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string)); - if($ret < 0) { - unset($input); - return NULL; - } - return $this->encodeInput($input); - } - - //---------------------------------------------------------------------- - public function encodeString($string, $version, $level, $hint, $casesensitive) - { - - if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) { - throw new \Exception('bad hint'); - return NULL; - } - - $input = new QRinput($version, $level); - if($input == NULL) return NULL; - - $ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive); - if($ret < 0) { - return NULL; - } - - return $this->encodeInput($input); - } - - //---------------------------------------------------------------------- - public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false) - { - $enc = QRencode::factory($level, $size, $margin); - return $enc->encodePNG($text, $outfile, $saveandprint=false); - } - - //---------------------------------------------------------------------- - public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) - { - $enc = QRencode::factory($level, $size, $margin); - return $enc->encode($text, $outfile); - } - - //---------------------------------------------------------------------- - public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) - { - $enc = QRencode::factory($level, $size, $margin); - return $enc->encodeRAW($text, $outfile); - } - } - - //########################################################################## - - class FrameFiller { - - public $width; - public $frame; - public $x; - public $y; - public $dir; - public $bit; - - //---------------------------------------------------------------------- - public function __construct($width, &$frame) - { - $this->width = $width; - $this->frame = $frame; - $this->x = $width - 1; - $this->y = $width - 1; - $this->dir = -1; - $this->bit = -1; - } - - //---------------------------------------------------------------------- - public function setFrameAt($at, $val) - { - $this->frame[$at['y']][$at['x']] = chr($val); - } - - //---------------------------------------------------------------------- - public function getFrameAt($at) - { - return ord($this->frame[$at['y']][$at['x']]); - } - - //---------------------------------------------------------------------- - public function next() - { - do { - - if($this->bit == -1) { - $this->bit = 0; - return array('x'=>$this->x, 'y'=>$this->y); - } - - $x = $this->x; - $y = $this->y; - $w = $this->width; - - if($this->bit == 0) { - $x--; - $this->bit++; - } else { - $x++; - $y += $this->dir; - $this->bit--; - } - - if($this->dir < 0) { - if($y < 0) { - $y = 0; - $x -= 2; - $this->dir = 1; - if($x == 6) { - $x--; - $y = 9; - } - } - } else { - if($y == $w) { - $y = $w - 1; - $x -= 2; - $this->dir = -1; - if($x == 6) { - $x--; - $y -= 8; - } - } - } - if($x < 0 || $y < 0) return null; - - $this->x = $x; - $this->y = $y; - - } while(ord($this->frame[$y][$x]) & 0x80); - - return array('x'=>$x, 'y'=>$y); - } - - } ; - - //########################################################################## - - class QRencode { - - public $casesensitive = true; - public $eightbit = false; - - public $version = 0; - public $size = 3; - public $margin = 4; - - public $structured = 0; // not supported yet - - public $level = QR_ECLEVEL_L; - public $hint = QR_MODE_8; - - //---------------------------------------------------------------------- - public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4) - { - $enc = new QRencode(); - $enc->size = $size; - $enc->margin = $margin; - - switch ($level.'') { - case '0': - case '1': - case '2': - case '3': - $enc->level = $level; - break; - case 'l': - case 'L': - $enc->level = QR_ECLEVEL_L; - break; - case 'm': - case 'M': - $enc->level = QR_ECLEVEL_M; - break; - case 'q': - case 'Q': - $enc->level = QR_ECLEVEL_Q; - break; - case 'h': - case 'H': - $enc->level = QR_ECLEVEL_H; - break; - } - - return $enc; - } - - //---------------------------------------------------------------------- - public function encodeRAW($intext, $outfile = false) - { - $code = new QRcode(); - - if($this->eightbit) { - $code->encodeString8bit($intext, $this->version, $this->level); - } else { - $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); - } - - return $code->data; - } - - //---------------------------------------------------------------------- - public function encode($intext, $outfile = false) - { - $code = new QRcode(); - - if($this->eightbit) { - $code->encodeString8bit($intext, $this->version, $this->level); - } else { - $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); - } - - QRtools::markTime('after_encode'); - - if ($outfile!== false) { - file_put_contents($outfile, join("\n", QRtools::binarize($code->data))); - } else { - return QRtools::binarize($code->data); - } - } - - //---------------------------------------------------------------------- - public function encodePNG($intext, $outfile = false,$saveandprint=false) - { - try { - - ob_start(); - $tab = $this->encode($intext); - $err = ob_get_contents(); - ob_end_clean(); - - if ($err != '') - QRtools::log($outfile, $err); - - $maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin)); - - QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint); - - } catch (Exception $e) { - - QRtools::log($outfile, $e->getMessage()); - - } - } - } - - diff --git a/niucloud/core/core/util/Queue.php b/niucloud/core/core/util/Queue.php deleted file mode 100644 index 912b4db1..00000000 --- a/niucloud/core/core/util/Queue.php +++ /dev/null @@ -1,251 +0,0 @@ -default_method = $this->method; - } - - /** - * 实例化当前队列 - * @return static - */ - public static function instance() - { - if (is_null(self::$instance)) { - self::$instance = new static(); - } - return self::$instance; - } - - /** - * 设置队列名称 - * @param string $queue_name - * @return $this - */ - public function setQueueName(string $queue_name) - { - $this->queue_name = $queue_name; - return $this; - } - - /** - * 加入队列 - * @param array|null $data - * @return bool - */ - public function push() - { - if (!$this->job) { - return $this->setError('JOB_NOT_EXISTS'); - } - $jodValue = $this->getValues(); - $res = $this->send(...$jodValue); - if (!$res) { - $res = $this->send(...$jodValue); - if (!$res) { - Log::error('队列推送失败,参数:' . json_encode($jodValue, JSON_THROW_ON_ERROR)); - } - } -// //todo 队列扩展策略调度, - - $this->clean(); - return $res; - } - - /** - * 向队列发送一条消息 - * @param $queue - * @param $data - * @param $delay - * @return mixed - */ - public function send($queue, $data, $delay = 0) - { - $pre_queue = md5(root_path()); //1.0.5版本之前为redis-queue - $queue_waiting = $pre_queue.'{redis-queue}-waiting'; //1.0.5版本之前为redis-queue-waiting - $queue_delay = $pre_queue.'{redis-queue}-delayed';//1.0.5版本之前为redis-queue-delayed - $now = time(); - if (extension_loaded('redis')) { - try { - $redis = new \Redis(); - $redis->connect(env('redis.redis_hostname'), env('redis.port'), 8); - if (env('redis.redis_password', '')) { - $redis->auth(env('redis.redis_password', '')); - } - $redis->select(env('redis.select')); - if(!$redis->ping()){ - $redis->connect(env('redis.redis_hostname'), env('redis.port'), 8); - if (env('redis.redis_password', '')) { - $redis->auth(env('redis.redis_password', '')); - } - $redis->select(env('redis.select')); - } - $package_str = json_encode([ - 'id' => rand(), - 'time' => $now, - 'delay' => $delay, - 'attempts' => 0, - 'queue' => $queue, - 'data' => $data - ]); - if ($delay) { - if(!$redis->zAdd($queue_delay, ($now + $delay), $package_str)){ - $redis->zAdd($queue_delay, ($now + $delay), $package_str); - } - return true; - } - if(!$redis->lPush($queue_waiting . $queue, $package_str)){ - $res = $redis->lPush($queue_waiting . $queue, $package_str); - Log::write($res); - } - return true; - } catch ( Throwable $e ) { - return false; - } - }else{ - return false; - } - - } - - /** - * 清除数据 - */ - public function clean() - { - $this->secs = 0; - $this->data = []; - $this->queue_name = null; - $this->method = $this->default_method; - } - - /** - * 获取参数 - * @param $data - * @return array - */ - protected function getValues() - { - - return [$this->job, ['method' => $this->method, 'data' => $this->data], $this->secs]; - } - - /** - * 不可访问时调用 - * @param $method - * @param $arguments - * @return $this - * @throws Exception - * @throws Exception - * @throws Exception - */ - public function __call($method, $arguments) - { - if (in_array($method, $this->allow_function)) { - if ($method === 'data') { - $this->{$method} = $arguments; - } else { - $this->{$method} = $arguments[0] ?? null; - } - return $this; - } else { - throw new Exception('Method does not exist' . __CLASS__ . '->' . $method . '()'); - } - } - - /** - * 设置错误信息 - * @param string|null $error - * @return bool - */ - protected function setError(?string $error = null) - { - $this->error = $error; - return false; - } - - /** - * 获取错误信息 - * @return string - */ - public function getError() - { - $error = $this->error; - $this->error = null; - return $error; - } -} diff --git a/niucloud/core/core/util/Snowflake.php b/niucloud/core/core/util/Snowflake.php deleted file mode 100644 index 84f2322c..00000000 --- a/niucloud/core/core/util/Snowflake.php +++ /dev/null @@ -1,91 +0,0 @@ - self::MAX_DATA_CENTER_ID || $data_center_id < 0) { -// throw new Exception('Data center ID can not be greater than ' . self::MAX_DATA_CENTER_ID . ' or less than 0'); -// } -// -// if ($machine_id > self::MAX_MACHINE_ID || $machine_id < 0) { -// throw new Exception('Machine ID can not be greater than ' . self::MAX_MACHINE_ID . ' or less than 0'); -// } - -// $this->data_center_id = $data_center_id; -// $this->machine_id = $machine_id; - $this->last_timestamp = 0; - $this->sequence = 0; - } - - /** - * @throws Exception - */ - public function generateId() - { - $timestamp = $this->getTimestamp(); - - // 当前时间小于上一次生成时间,发生时钟回拨 - if ($timestamp < $this->last_timestamp) { - throw new Exception('Clock moved backwards.'); - } - - // 当前时间与上一次生成时间相同 - if ($timestamp == $this->last_timestamp) { - $this->sequence = ($this->sequence + 1) & self::MAX_SEQUENCE; - - // 当前毫秒的序列已经达到最大值,等待下一毫秒 - if ($this->sequence == 0) { - $timestamp = $this->nextMillis($this->last_timestamp); - } - } else { - // 新的一毫秒,序列从0开始 - $this->sequence = 0; - } - - $this->last_timestamp = $timestamp; - - return (($timestamp - self::START_EPOCH) << (self::SEQUENCE_BITS)) -// | ($this->data_center_id << (self::SEQUENCE_BITS + self::MACHINE_ID_BITS)) -// | ($this->machine_id << self::SEQUENCE_BITS) - | $this->sequence; - } - - private function getTimestamp() - { - return floor(microtime(true) * 1000); - } - - private function nextMillis($last_timestamp) - { - $timestamp = $this->getTimestamp(); - - while ($timestamp <= $last_timestamp) { - $timestamp = $this->getTimestamp(); - } - - return $timestamp; - } -} \ No newline at end of file diff --git a/niucloud/core/core/util/Terminal.php b/niucloud/core/core/util/Terminal.php deleted file mode 100644 index 964097e8..00000000 --- a/niucloud/core/core/util/Terminal.php +++ /dev/null @@ -1,56 +0,0 @@ - array("pipe", "r"), // 标准输入,我们不需要 - 1 => array("pipe", "w"), // 标准输出,我们需要将其捕获 - 2 => array("pipe", "w") // 标准错误,我们也需要将其捕获 - ); - $process = proc_open($command, $descriptorspec, $pipes, $cwd); - - // 检查进程是否成功创建 - if (!is_resource($process)) { - return "Could not execute command: $command"; - } - - // 从管道中获取命令的输出 - $output = ''; - while (!feof($pipes[1])) { - $output .= fgets($pipes[1]); - } - while (!feof($pipes[2])) { - $output .= fgets($pipes[2]); - } - - // 关闭管道和进程 - fclose($pipes[0]); - fclose($pipes[1]); - fclose($pipes[2]); - $status = proc_close($process); - - // 判断命令的执行结果 - if ($status === 0) { - return str_contains($output, 'Command failed') ? $output : true; - } else { - return $output; - } - } -} \ No newline at end of file diff --git a/niucloud/core/core/util/TokenAuth.php b/niucloud/core/core/util/TokenAuth.php deleted file mode 100644 index 35cd7310..00000000 --- a/niucloud/core/core/util/TokenAuth.php +++ /dev/null @@ -1,109 +0,0 @@ -request->host(); - $time = time(); - $params += [ - 'iss' => $host, - 'aud' => $host, - 'iat' => $time, - 'nbf' => $time, - 'exp' => $time + $expire_time, - ]; - - $params['jti'] = $id . "_" . $type; - $token = JWT::encode($params, Env::get('app.app_key', 'niucloud456$%^')); - $cache_token = Cache::get("token_" . $params['jti']); - $cache_token_arr = $cache_token ?: []; -// if(!empty($cache_token)) -// { -// -// $cache_token_arr[] = $token; -// } - $cache_token_arr[] = $token; - Cache::tag("token")->set("token_" . $params['jti'], $cache_token_arr); - return compact('token', 'params'); - } - - /** - * 解析token - * @param string $token - * @param string $type - * @return array - */ - public static function parseToken(string $token, string $type): array - { - $payload = JWT::decode($token, Env::get('app.app_key', 'niucloud456$%^'), ['HS256']); - if (!empty($payload)) { - $token_info = json_decode(json_encode($payload), true, 512, JSON_THROW_ON_ERROR); - - if (explode("_", $token_info['jti'])[1] != $type) { - return []; - } - if (!empty($token_info) && !in_array($token, Cache::get('token_' . $token_info['jti'], []))) { - return []; - } - return $token_info; - } else { - return []; - } - } - - /** - * 清理token - * @param int $id - * @param string $type - * @param string|null $token - * @return Response - */ - public static function clearToken(int $id, string $type, ?string $token = '') - { - if (!empty($token)) { - $token_cache = Cache::get("token_" . $id . "_" . $type, []); - //todo 也可以通过修改过期时间来实现 - if (!empty($token_cache)) { - if (($key = array_search($token, $token_cache)) !== false) { - array_splice($token_cache, $key, 1); - } - Cache::set("token_" . $id . "_" . $type, $token_cache); - } - } else { - Cache::set("token_" . $id . "_" . $type, []); - } - return success(); - } -} diff --git a/niucloud/core/core/util/barcode/class/BCGArgumentException.php b/niucloud/core/core/util/barcode/class/BCGArgumentException.php deleted file mode 100644 index 030f3e46..00000000 --- a/niucloud/core/core/util/barcode/class/BCGArgumentException.php +++ /dev/null @@ -1,25 +0,0 @@ -param = $param; - parent::__construct($message, 20000); - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGBarcode.php b/niucloud/core/core/util/barcode/class/BCGBarcode.php deleted file mode 100644 index 317e773b..00000000 --- a/niucloud/core/core/util/barcode/class/BCGBarcode.php +++ /dev/null @@ -1,436 +0,0 @@ -setOffsetX(0); - $this->setOffsetY(0); - $this->setForegroundColor(0x000000); - $this->setBackgroundColor(0xffffff); - $this->setScale(1); - } - - /** - * Parses the text before displaying it. - * - * @param mixed $text - */ - public function parse($text) { - } - - /** - * Gets the foreground color of the barcode. - * - * @return BCGColor - */ - public function getForegroundColor() { - return $this->colorFg; - } - - /** - * Sets the foreground color of the barcode. It could be a BCGColor - * value or simply a language code (white, black, yellow...) or hex value. - * - * @param mixed $code - */ - public function setForegroundColor($code) { - if ($code instanceof BCGColor) { - $this->colorFg = $code; - } else { - $this->colorFg = new BCGColor($code); - } - } - - /** - * Gets the background color of the barcode. - * - * @return BCGColor - */ - public function getBackgroundColor() { - return $this->colorBg; - } - - /** - * Sets the background color of the barcode. It could be a BCGColor - * value or simply a language code (white, black, yellow...) or hex value. - * - * @param mixed $code - */ - public function setBackgroundColor($code) { - if ($code instanceof BCGColor) { - $this->colorBg = $code; - } else { - $this->colorBg = new BCGColor($code); - } - - foreach ($this->labels as $label) { - $label->setBackgroundColor($this->colorBg); - } - } - - /** - * Sets the color. - * - * @param mixed $fg - * @param mixed $bg - */ - public function setColor($fg, $bg) { - $this->setForegroundColor($fg); - $this->setBackgroundColor($bg); - } - - /** - * Gets the scale of the barcode. - * - * @return int - */ - public function getScale() { - return $this->scale; - } - - /** - * Sets the scale of the barcode in pixel. - * If the scale is lower than 1, an exception is raised. - * - * @param int $scale - */ - public function setScale($scale) { - $scale = intval($scale); - if ($scale <= 0) { - throw new BCGArgumentException('The scale must be larger than 0.', 'scale'); - } - - $this->scale = $scale; - } - - /** - * Abstract method that draws the barcode on the resource. - * - * @param resource $im - */ - public abstract function draw($im); - - /** - * Returns the maximal size of a barcode. - * [0]->width - * [1]->height - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $labels = $this->getBiggestLabels(false); - $pixelsAround = array(0, 0, 0, 0); // TRBL - if (isset($labels[BCGLabel::POSITION_TOP])) { - $dimension = $labels[BCGLabel::POSITION_TOP]->getDimension(); - $pixelsAround[0] += $dimension[1]; - } - - if (isset($labels[BCGLabel::POSITION_RIGHT])) { - $dimension = $labels[BCGLabel::POSITION_RIGHT]->getDimension(); - $pixelsAround[1] += $dimension[0]; - } - - if (isset($labels[BCGLabel::POSITION_BOTTOM])) { - $dimension = $labels[BCGLabel::POSITION_BOTTOM]->getDimension(); - $pixelsAround[2] += $dimension[1]; - } - - if (isset($labels[BCGLabel::POSITION_LEFT])) { - $dimension = $labels[BCGLabel::POSITION_LEFT]->getDimension(); - $pixelsAround[3] += $dimension[0]; - } - - $finalW = ($w + $this->offsetX) * $this->scale; - $finalH = ($h + $this->offsetY) * $this->scale; - - // This section will check if a top/bottom label is too big for its width and left/right too big for its height - $reversedLabels = $this->getBiggestLabels(true); - foreach ($reversedLabels as $label) { - $dimension = $label->getDimension(); - $alignment = $label->getAlignment(); - if ($label->getPosition() === BCGLabel::POSITION_LEFT || $label->getPosition() === BCGLabel::POSITION_RIGHT) { - if ($alignment === BCGLabel::ALIGN_TOP) { - $pixelsAround[2] = max($pixelsAround[2], $dimension[1] - $finalH); - } elseif ($alignment === BCGLabel::ALIGN_CENTER) { - $temp = ceil(($dimension[1] - $finalH) / 2); - $pixelsAround[0] = max($pixelsAround[0], $temp); - $pixelsAround[2] = max($pixelsAround[2], $temp); - } elseif ($alignment === BCGLabel::ALIGN_BOTTOM) { - $pixelsAround[0] = max($pixelsAround[0], $dimension[1] - $finalH); - } - } else { - if ($alignment === BCGLabel::ALIGN_LEFT) { - $pixelsAround[1] = max($pixelsAround[1], $dimension[0] - $finalW); - } elseif ($alignment === BCGLabel::ALIGN_CENTER) { - $temp = ceil(($dimension[0] - $finalW) / 2); - $pixelsAround[1] = max($pixelsAround[1], $temp); - $pixelsAround[3] = max($pixelsAround[3], $temp); - } elseif ($alignment === BCGLabel::ALIGN_RIGHT) { - $pixelsAround[3] = max($pixelsAround[3], $dimension[0] - $finalW); - } - } - } - - $this->pushLabel[0] = $pixelsAround[3]; - $this->pushLabel[1] = $pixelsAround[0]; - - $finalW = ($w + $this->offsetX) * $this->scale + $pixelsAround[1] + $pixelsAround[3]; - $finalH = ($h + $this->offsetY) * $this->scale + $pixelsAround[0] + $pixelsAround[2]; - - return array($finalW, $finalH); - } - - /** - * Gets the X offset. - * - * @return int - */ - public function getOffsetX() { - return $this->offsetX; - } - - /** - * Sets the X offset. - * - * @param int $offsetX - */ - public function setOffsetX($offsetX) { - $offsetX = intval($offsetX); - if ($offsetX < 0) { - throw new BCGArgumentException('The offset X must be 0 or larger.', 'offsetX'); - } - - $this->offsetX = $offsetX; - } - - /** - * Gets the Y offset. - * - * @return int - */ - public function getOffsetY() { - return $this->offsetY; - } - - /** - * Sets the Y offset. - * - * @param int $offsetY - */ - public function setOffsetY($offsetY) { - $offsetY = intval($offsetY); - if ($offsetY < 0) { - throw new BCGArgumentException('The offset Y must be 0 or larger.', 'offsetY'); - } - - $this->offsetY = $offsetY; - } - - /** - * Adds the label to the drawing. - * - * @param BCGLabel $label - */ - public function addLabel(BCGLabel $label) { - $label->setBackgroundColor($this->colorBg); - $this->labels[] = $label; - } - - /** - * Removes the label from the drawing. - * - * @param BCGLabel $label - */ - public function removeLabel(BCGLabel $label) { - $remove = -1; - $c = count($this->labels); - for ($i = 0; $i < $c; $i++) { - if ($this->labels[$i] === $label) { - $remove = $i; - break; - } - } - - if ($remove > -1) { - array_splice($this->labels, $remove, 1); - } - } - - /** - * Clears the labels. - */ - public function clearLabels() { - $this->labels = array(); - } - - /** - * Draws the text. - * The coordinate passed are the positions of the barcode. - * $x1 and $y1 represent the top left corner. - * $x2 and $y2 represent the bottom right corner. - * - * @param resource $im - * @param int $x1 - * @param int $y1 - * @param int $x2 - * @param int $y2 - */ - protected function drawText($im, $x1, $y1, $x2, $y2) { - foreach ($this->labels as $label) { - $label->draw($im, - ($x1 + $this->offsetX) * $this->scale + $this->pushLabel[0], - ($y1 + $this->offsetY) * $this->scale + $this->pushLabel[1], - ($x2 + $this->offsetX) * $this->scale + $this->pushLabel[0], - ($y2 + $this->offsetY) * $this->scale + $this->pushLabel[1]); - } - } - - /** - * Draws 1 pixel on the resource at a specific position with a determined color. - * - * @param resource $im - * @param int $x - * @param int $y - * @param int $color - */ - protected function drawPixel($im, $x, $y, $color = self::COLOR_FG) { - $xR = ($x + $this->offsetX) * $this->scale + $this->pushLabel[0]; - $yR = ($y + $this->offsetY) * $this->scale + $this->pushLabel[1]; - - // We always draw a rectangle - imagefilledrectangle($im, - $xR, - $yR, - $xR + $this->scale - 1, - $yR + $this->scale - 1, - $this->getColor($im, $color)); - } - - /** - * Draws an empty rectangle on the resource at a specific position with a determined color. - * - * @param resource $im - * @param int $x1 - * @param int $y1 - * @param int $x2 - * @param int $y2 - * @param int $color - */ - protected function drawRectangle($im, $x1, $y1, $x2, $y2, $color = self::COLOR_FG) { - if ($this->scale === 1) { - imagefilledrectangle($im, - ($x1 + $this->offsetX) + $this->pushLabel[0], - ($y1 + $this->offsetY) + $this->pushLabel[1], - ($x2 + $this->offsetX) + $this->pushLabel[0], - ($y2 + $this->offsetY) + $this->pushLabel[1], - $this->getColor($im, $color)); - } else { - imagefilledrectangle($im, ($x1 + $this->offsetX) * $this->scale + $this->pushLabel[0], ($y1 + $this->offsetY) * $this->scale + $this->pushLabel[1], ($x2 + $this->offsetX) * $this->scale + $this->pushLabel[0] + $this->scale - 1, ($y1 + $this->offsetY) * $this->scale + $this->pushLabel[1] + $this->scale - 1, $this->getColor($im, $color)); - imagefilledrectangle($im, ($x1 + $this->offsetX) * $this->scale + $this->pushLabel[0], ($y1 + $this->offsetY) * $this->scale + $this->pushLabel[1], ($x1 + $this->offsetX) * $this->scale + $this->pushLabel[0] + $this->scale - 1, ($y2 + $this->offsetY) * $this->scale + $this->pushLabel[1] + $this->scale - 1, $this->getColor($im, $color)); - imagefilledrectangle($im, ($x2 + $this->offsetX) * $this->scale + $this->pushLabel[0], ($y1 + $this->offsetY) * $this->scale + $this->pushLabel[1], ($x2 + $this->offsetX) * $this->scale + $this->pushLabel[0] + $this->scale - 1, ($y2 + $this->offsetY) * $this->scale + $this->pushLabel[1] + $this->scale - 1, $this->getColor($im, $color)); - imagefilledrectangle($im, ($x1 + $this->offsetX) * $this->scale + $this->pushLabel[0], ($y2 + $this->offsetY) * $this->scale + $this->pushLabel[1], ($x2 + $this->offsetX) * $this->scale + $this->pushLabel[0] + $this->scale - 1, ($y2 + $this->offsetY) * $this->scale + $this->pushLabel[1] + $this->scale - 1, $this->getColor($im, $color)); - } - } - - /** - * Draws a filled rectangle on the resource at a specific position with a determined color. - * - * @param resource $im - * @param int $x1 - * @param int $y1 - * @param int $x2 - * @param int $y2 - * @param int $color - */ - protected function drawFilledRectangle($im, $x1, $y1, $x2, $y2, $color = self::COLOR_FG) { - if ($x1 > $x2) { // Swap - $x1 ^= $x2 ^= $x1 ^= $x2; - } - - if ($y1 > $y2) { // Swap - $y1 ^= $y2 ^= $y1 ^= $y2; - } - - imagefilledrectangle($im, - ($x1 + $this->offsetX) * $this->scale + $this->pushLabel[0], - ($y1 + $this->offsetY) * $this->scale + $this->pushLabel[1], - ($x2 + $this->offsetX) * $this->scale + $this->pushLabel[0] + $this->scale - 1, - ($y2 + $this->offsetY) * $this->scale + $this->pushLabel[1] + $this->scale - 1, - $this->getColor($im, $color)); - } - - /** - * Allocates the color based on the integer. - * - * @param resource $im - * @param int $color - * @return resource - */ - protected function getColor($im, $color) { - if ($color === self::COLOR_BG) { - return $this->colorBg->allocate($im); - } else { - return $this->colorFg->allocate($im); - } - } - - /** - * Returning the biggest label widths for LEFT/RIGHT and heights for TOP/BOTTOM. - * - * @param bool $reversed - * @return BCGLabel[] - */ - private function getBiggestLabels($reversed = false) { - $searchLR = $reversed ? 1 : 0; - $searchTB = $reversed ? 0 : 1; - - $labels = array(); - foreach ($this->labels as $label) { - $position = $label->getPosition(); - if (isset($labels[$position])) { - $savedDimension = $labels[$position]->getDimension(); - $dimension = $label->getDimension(); - if ($position === BCGLabel::POSITION_LEFT || $position === BCGLabel::POSITION_RIGHT) { - if ($dimension[$searchLR] > $savedDimension[$searchLR]) { - $labels[$position] = $label; - } - } else { - if ($dimension[$searchTB] > $savedDimension[$searchTB]) { - $labels[$position] = $label; - } - } - } else { - $labels[$position] = $label; - } - } - - return $labels; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGBarcode1D.php b/niucloud/core/core/util/barcode/class/BCGBarcode1D.php deleted file mode 100644 index 7202a8cb..00000000 --- a/niucloud/core/core/util/barcode/class/BCGBarcode1D.php +++ /dev/null @@ -1,259 +0,0 @@ -setThickness(30); - - $this->defaultLabel = new BCGLabel(); - $this->defaultLabel->setPosition(BCGLabel::POSITION_BOTTOM); - $this->setLabel(self::AUTO_LABEL); - $this->setFont(new BCGFontPhp(5)); - - $this->text = ''; - $this->checksumValue = false; - $this->positionX = 0; - } - - /** - * Gets the thickness. - * - * @return int - */ - public function getThickness() { - return $this->thickness; - } - - /** - * Sets the thickness. - * - * @param int $thickness - */ - public function setThickness($thickness) { - $thickness = intval($thickness); - if ($thickness <= 0) { - throw new BCGArgumentException('The thickness must be larger than 0.', 'thickness'); - } - - $this->thickness = $thickness; - } - - /** - * Gets the label. - * If the label was set to BCGBarcode1D::AUTO_LABEL, the label will display the value from the text parsed. - * - * @return string - */ - public function getLabel() { - $label = $this->label; - if ($this->label === self::AUTO_LABEL) { - $label = $this->text; - if ($this->displayChecksum === true && ($checksum = $this->processChecksum()) !== false) { - $label .= $checksum; - } - } - - return $label; - } - - /** - * Sets the label. - * You can use BCGBarcode::AUTO_LABEL to have the label automatically written based on the parsed text. - * - * @param string $label - */ - public function setLabel($label) { - $this->label = $label; - } - - /** - * Gets the font. - * - * @return BCGFont - */ - public function getFont() { - return $this->font; - } - - /** - * Sets the font. - * - * @param mixed $font BCGFont or int - */ - public function setFont($font) { - if (is_int($font)) { - if ($font === 0) { - $font = null; - } else { - $font = new BCGFontPhp($font); - } - } - - $this->font = $font; - } - - /** - * Parses the text before displaying it. - * - * @param mixed $text - */ - public function parse($text) { - $this->text = $text; - $this->checksumValue = false; // Reset checksumValue - $this->validate(); - - parent::parse($text); - - $this->addDefaultLabel(); - } - - /** - * Gets the checksum of a Barcode. - * If no checksum is available, return FALSE. - * - * @return string - */ - public function getChecksum() { - return $this->processChecksum(); - } - - /** - * Sets if the checksum is displayed with the label or not. - * The checksum must be activated in some case to make this variable effective. - * - * @param boolean $displayChecksum - */ - public function setDisplayChecksum($displayChecksum) { - $this->displayChecksum = (bool)$displayChecksum; - } - - /** - * Adds the default label. - */ - protected function addDefaultLabel() { - $label = $this->getLabel(); - $font = $this->font; - if ($label !== null && $label !== '' && $font !== null && $this->defaultLabel !== null) { - $this->defaultLabel->setText($label); - $this->defaultLabel->setFont($font); - $this->addLabel($this->defaultLabel); - } - } - - /** - * Validates the input - */ - protected function validate() { - // No validation in the abstract class. - } - - /** - * Returns the index in $keys (useful for checksum). - * - * @param mixed $var - * @return mixed - */ - protected function findIndex($var) { - return array_search($var, $this->keys); - } - - /** - * Returns the code of the char (useful for drawing bars). - * - * @param mixed $var - * @return string - */ - protected function findCode($var) { - return $this->code[$this->findIndex($var)]; - } - - /** - * Draws all chars thanks to $code. If $startBar is true, the line begins by a space. - * If $startBar is false, the line begins by a bar. - * - * @param resource $im - * @param string $code - * @param boolean $startBar - */ - protected function drawChar($im, $code, $startBar = true) { - $colors = array(BCGBarcode::COLOR_FG, BCGBarcode::COLOR_BG); - $currentColor = $startBar ? 0 : 1; - $c = strlen($code); - for ($i = 0; $i < $c; $i++) { - for ($j = 0; $j < intval($code[$i]) + 1; $j++) { - $this->drawSingleBar($im, $colors[$currentColor]); - $this->nextX(); - } - - $currentColor = ($currentColor + 1) % 2; - } - } - - /** - * Draws a Bar of $color depending of the resolution. - * - * @param resource $img - * @param int $color - */ - protected function drawSingleBar($im, $color) { - $this->drawFilledRectangle($im, $this->positionX, 0, $this->positionX, $this->thickness - 1, $color); - } - - /** - * Moving the pointer right to write a bar. - */ - protected function nextX() { - $this->positionX++; - } - - /** - * Method that saves FALSE into the checksumValue. This means no checksum - * but this method should be overriden when needed. - */ - protected function calculateChecksum() { - $this->checksumValue = false; - } - - /** - * Returns FALSE because there is no checksum. This method should be - * overriden to return correctly the checksum in string with checksumValue. - * - * @return string - */ - protected function processChecksum() { - return false; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGColor.php b/niucloud/core/core/util/barcode/class/BCGColor.php deleted file mode 100644 index 7bd0650d..00000000 --- a/niucloud/core/core/util/barcode/class/BCGColor.php +++ /dev/null @@ -1,154 +0,0 @@ -r = intval($args[0]); - $this->g = intval($args[1]); - $this->b = intval($args[2]); - } elseif ($c === 1) { - if (is_string($args[0]) && strlen($args[0]) === 7 && $args[0][0] === '#') { // Hex Value in String - $this->r = intval(substr($args[0], 1, 2), 16); - $this->g = intval(substr($args[0], 3, 2), 16); - $this->b = intval(substr($args[0], 5, 2), 16); - } else { - if (is_string($args[0])) { - $args[0] = self::getColor($args[0]); - } - - $args[0] = intval($args[0]); - $this->r = ($args[0] & 0xff0000) >> 16; - $this->g = ($args[0] & 0x00ff00) >> 8; - $this->b = ($args[0] & 0x0000ff); - } - } else { - $this->r = $this->g = $this->b = 0; - } - } - - /** - * Sets the color transparent. - * - * @param bool $transparent - */ - public function setTransparent($transparent) { - $this->transparent = $transparent; - } - - /** - * Returns Red Color. - * - * @return int - */ - public function r() { - return $this->r; - } - - /** - * Returns Green Color. - * - * @return int - */ - public function g() { - return $this->g; - } - - /** - * Returns Blue Color. - * - * @return int - */ - public function b() { - return $this->b; - } - - /** - * Returns the int value for PHP color. - * - * @param resource $im - * @return int - */ - public function allocate(&$im) { - $allocated = imagecolorallocate($im, $this->r, $this->g, $this->b); - if ($this->transparent) { - return imagecolortransparent($im, $allocated); - } else { - return $allocated; - } - } - - /** - * Returns class of BCGColor depending of the string color. - * - * If the color doens't exist, it takes the default one. - * - * @param string $code - * @param string $default - */ - public static function getColor($code, $default = 'white') { - switch(strtolower($code)) { - case '': - case 'white': - return 0xffffff; - case 'black': - return 0x000000; - case 'maroon': - return 0x800000; - case 'red': - return 0xff0000; - case 'orange': - return 0xffa500; - case 'yellow': - return 0xffff00; - case 'olive': - return 0x808000; - case 'purple': - return 0x800080; - case 'fuchsia': - return 0xff00ff; - case 'lime': - return 0x00ff00; - case 'green': - return 0x008000; - case 'navy': - return 0x000080; - case 'blue': - return 0x0000ff; - case 'aqua': - return 0x00ffff; - case 'teal': - return 0x008080; - case 'silver': - return 0xc0c0c0; - case 'gray': - return 0x808080; - default: - return self::getColor($default, 'white'); - } - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGDrawException.php b/niucloud/core/core/util/barcode/class/BCGDrawException.php deleted file mode 100644 index 792732d3..00000000 --- a/niucloud/core/core/util/barcode/class/BCGDrawException.php +++ /dev/null @@ -1,21 +0,0 @@ - \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGDrawing.php b/niucloud/core/core/util/barcode/class/BCGDrawing.php deleted file mode 100644 index 612522cf..00000000 --- a/niucloud/core/core/util/barcode/class/BCGDrawing.php +++ /dev/null @@ -1,248 +0,0 @@ -im = null; - $this->setFilename($filename); - $this->color = $color; - $this->dpi = null; - $this->rotateDegree = 0.0; - } - - /** - * Destructor. - */ - public function __destruct() { - $this->destroy(); - } - - /** - * Gets the filename. - * - * @return string - */ - public function getFilename() { - return $this->filename; - } - - /** - * Sets the filename. - * - * @param string $filaneme - */ - public function setFilename($filename) { - $this->filename = $filename; - } - - /** - * @return resource. - */ - public function get_im() { - return $this->im; - } - - /** - * Sets the image. - * - * @param resource $im - */ - public function set_im($im) { - $this->im = $im; - } - - /** - * Gets Barcode for drawing. - * - * @return BCGBarcode - */ - public function getBarcode() { - return $this->barcode; - } - - /** - * Sets Barcode for drawing. - * - * @param BCGBarcode $Barcode - */ - public function setBarcode(BCGBarcode $barcode) { - $this->barcode = $barcode; - } - - /** - * Gets the DPI for supported filetype. - * - * @return float - */ - public function getDPI() { - return $this->dpi; - } - - /** - * Sets the DPI for supported filetype. - * - * @param float $dpi - */ - public function setDPI($dpi) { - $this->dpi = $dpi; - } - - /** - * Gets the rotation angle in degree clockwise. - * - * @return float - */ - public function getRotationAngle() { - return $this->rotateDegree; - } - - /** - * Sets the rotation angle in degree clockwise. - * - * @param float $degree - */ - public function setRotationAngle($degree) { - $this->rotateDegree = (float)$degree; - } - - /** - * Draws the Barcode on the image $im. - */ - public function draw() { - $size = $this->barcode->getDimension(0, 0); - $this->w = max(1, $size[0]); - $this->h = max(1, $size[1]); - $this->init(); - $this->barcode->draw($this->im); - } - - /** - * Saves $im into the file (many format available). - * - * @param int $image_style - * @param int $quality - */ - public function finish($image_style = self::IMG_FORMAT_PNG, $quality = 100) { - $drawer = null; - - $im = $this->im; - if ($this->rotateDegree > 0.0) { - if (function_exists('imagerotate')) { - $im = imagerotate($this->im, 360 - $this->rotateDegree, $this->color->allocate($this->im)); - } else { - throw new BCGDrawException('The method imagerotate doesn\'t exist on your server. Do not use any rotation.'); - } - } - - if ($image_style === self::IMG_FORMAT_PNG) { - $drawer = new BCGDrawPNG($im); - $drawer->setFilename($this->filename); - $drawer->setDPI($this->dpi); - } elseif ($image_style === self::IMG_FORMAT_JPEG) { - $drawer = new BCGDrawJPG($im); - $drawer->setFilename($this->filename); - $drawer->setDPI($this->dpi); - $drawer->setQuality($quality); - } elseif ($image_style === self::IMG_FORMAT_GIF) { - // Some PHP versions have a bug if passing 2nd argument as null. - if ($this->filename === null || $this->filename === '') { - imagegif($im); - } else { - imagegif($im, $this->filename); - } - } elseif ($image_style === self::IMG_FORMAT_WBMP) { - imagewbmp($im, $this->filename); - } - - if ($drawer !== null) { - $drawer->draw(); - } - } - - /** - * Writes the Error on the picture. - * - * @param Exception $exception - */ - public function drawException($exception) { - $this->w = 1; - $this->h = 1; - $this->init(); - - // Is the image big enough? - $w = imagesx($this->im); - $h = imagesy($this->im); - - $text = 'Error: ' . $exception->getMessage(); - - $width = imagefontwidth(2) * strlen($text); - $height = imagefontheight(2); - if ($width > $w || $height > $h) { - $width = max($w, $width); - $height = max($h, $height); - - // We change the size of the image - $newimg = imagecreatetruecolor($width, $height); - imagefill($newimg, 0, 0, imagecolorat($this->im, 0, 0)); - imagecopy($newimg, $this->im, 0, 0, 0, 0, $w, $h); - $this->im = $newimg; - } - - $black = new BCGColor('black'); - imagestring($this->im, 2, 0, 0, $text, $black->allocate($this->im)); - } - - /** - * Free the memory of PHP (called also by destructor). - */ - public function destroy() { - @imagedestroy($this->im); - } - - /** - * Init Image and color background. - */ - private function init() { - if ($this->im === null) { - $this->im = imagecreatetruecolor($this->w, $this->h) - or die('Can\'t Initialize the GD Libraty'); - imagefilledrectangle($this->im, 0, 0, $this->w - 1, $this->h - 1, $this->color->allocate($this->im)); - } - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGFont.php b/niucloud/core/core/util/barcode/class/BCGFont.php deleted file mode 100644 index c58c0de3..00000000 --- a/niucloud/core/core/util/barcode/class/BCGFont.php +++ /dev/null @@ -1,23 +0,0 @@ - \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGFontFile.php b/niucloud/core/core/util/barcode/class/BCGFontFile.php deleted file mode 100644 index 4c304eb5..00000000 --- a/niucloud/core/core/util/barcode/class/BCGFontFile.php +++ /dev/null @@ -1,209 +0,0 @@ -path = $fontPath; - $this->size = $size; - $this->foregroundColor = new BCGColor('black'); - $this->setRotationAngle(0); - $this->setBoxFix(self::PHP_BOX_FIX); - } - - /** - * Gets the text associated to the font. - * - * @return string - */ - public function getText() { - return $this->text; - } - - /** - * Sets the text associated to the font. - * - * @param string text - */ - public function setText($text) { - $this->text = $text; - $this->box = null; - } - - /** - * Gets the rotation in degree. - * - * @return int - */ - public function getRotationAngle() { - return (360 - $this->rotationAngle) % 360; - } - - /** - * Sets the rotation in degree. - * - * @param int - */ - public function setRotationAngle($rotationAngle) { - $this->rotationAngle = (int)$rotationAngle; - if ($this->rotationAngle !== 90 && $this->rotationAngle !== 180 && $this->rotationAngle !== 270) { - $this->rotationAngle = 0; - } - - $this->rotationAngle = (360 - $this->rotationAngle) % 360; - - $this->box = null; - } - - /** - * Gets the background color. - * - * @return BCGColor - */ - public function getBackgroundColor() { - } - - /** - * Sets the background color. - * - * @param BCGColor $backgroundColor - */ - public function setBackgroundColor($backgroundColor) { - } - - /** - * Gets the foreground color. - * - * @return BCGColor - */ - public function getForegroundColor() { - return $this->foregroundColor; - } - - /** - * Sets the foreground color. - * - * @param BCGColor $foregroundColor - */ - public function setForegroundColor($foregroundColor) { - $this->foregroundColor = $foregroundColor; - } - - /** - * Gets the box fix information. - * - * @return int - */ - public function getBoxFix() { - return $this->boxFix; - } - - /** - * Sets the box fix information. - * - * @param int $value - */ - public function setBoxFix($value) { - $this->boxFix = intval($value); - } - - /** - * Returns the width and height that the text takes to be written. - * - * @return int[] - */ - public function getDimension() { - $w = 0.0; - $h = 0.0; - $box = $this->getBox(); - - if ($box !== null) { - $minX = min(array($box[0], $box[2], $box[4], $box[6])); - $maxX = max(array($box[0], $box[2], $box[4], $box[6])); - $minY = min(array($box[1], $box[3], $box[5], $box[7])); - $maxY = max(array($box[1], $box[3], $box[5], $box[7])); - - $w = $maxX - $minX; - $h = $maxY - $minY; - } - - $rotationAngle = $this->getRotationAngle(); - if ($rotationAngle === 90 || $rotationAngle === 270) { - return array($h + self::PHP_BOX_FIX, $w); - } else { - return array($w + self::PHP_BOX_FIX, $h); - } - } - - /** - * Draws the text on the image at a specific position. - * $x and $y represent the left bottom corner. - * - * @param resource $im - * @param int $x - * @param int $y - */ - public function draw($im, $x, $y) { - $drawingPosition = $this->getDrawingPosition($x, $y); - imagettftext($im, $this->size, $this->rotationAngle, $drawingPosition[0], $drawingPosition[1], $this->foregroundColor->allocate($im), $this->path, $this->text); - } - - private function getDrawingPosition($x, $y) { - $dimension = $this->getDimension(); - $box = $this->getBox(); - $rotationAngle = $this->getRotationAngle(); - if ($rotationAngle === 0) { - $y += abs(min($box[5], $box[7])); - } elseif ($rotationAngle === 90) { - $x += abs(min($box[5], $box[7])); - $y += $dimension[1]; - } elseif ($rotationAngle === 180) { - $x += $dimension[0]; - $y += abs(max($box[1], $box[3])); - } elseif ($rotationAngle === 270) { - $x += abs(max($box[1], $box[3])); - } - - return array($x, $y); - } - - private function getBox() { - if ($this->box === null) { - $gd = imagecreate(1, 1); - $this->box = imagettftext($gd, $this->size, 0, 0, 0, 0, $this->path, $this->text); - } - - return $this->box; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGFontPhp.php b/niucloud/core/core/util/barcode/class/BCGFontPhp.php deleted file mode 100644 index a2f8ba80..00000000 --- a/niucloud/core/core/util/barcode/class/BCGFontPhp.php +++ /dev/null @@ -1,153 +0,0 @@ -font = max(0, intval($font)); - $this->backgroundColor = new BCGColor('white'); - $this->foregroundColor = new BCGColor('black'); - $this->setRotationAngle(0); - } - - /** - * Gets the text associated to the font. - * - * @return string - */ - public function getText() { - return $this->text; - } - - /** - * Sets the text associated to the font. - * - * @param string text - */ - public function setText($text) { - $this->text = $text; - } - - /** - * Gets the rotation in degree. - * - * @return int - */ - public function getRotationAngle() { - return (360 - $this->rotationAngle) % 360; - } - - /** - * Sets the rotation in degree. - * - * @param int - */ - public function setRotationAngle($rotationAngle) { - $this->rotationAngle = (int)$rotationAngle; - if ($this->rotationAngle !== 90 && $this->rotationAngle !== 180 && $this->rotationAngle !== 270) { - $this->rotationAngle = 0; - } - - $this->rotationAngle = (360 - $this->rotationAngle) % 360; - } - - /** - * Gets the background color. - * - * @return BCGColor - */ - public function getBackgroundColor() { - return $this->backgroundColor; - } - - /** - * Sets the background color. - * - * @param BCGColor $backgroundColor - */ - public function setBackgroundColor($backgroundColor) { - $this->backgroundColor = $backgroundColor; - } - - /** - * Gets the foreground color. - * - * @return BCGColor - */ - public function getForegroundColor() { - return $this->foregroundColor; - } - - /** - * Sets the foreground color. - * - * @param BCGColor $foregroundColor - */ - public function setForegroundColor($foregroundColor) { - $this->foregroundColor = $foregroundColor; - } - - /** - * Returns the width and height that the text takes to be written. - * - * @return int[] - */ - public function getDimension() { - $w = imagefontwidth($this->font) * strlen($this->text); - $h = imagefontheight($this->font); - - $rotationAngle = $this->getRotationAngle(); - if ($rotationAngle === 90 || $rotationAngle === 270) { - return array($h, $w); - } else { - return array($w, $h); - } - } - - /** - * Draws the text on the image at a specific position. - * $x and $y represent the left bottom corner. - * - * @param resource $im - * @param int $x - * @param int $y - */ - public function draw($im, $x, $y) { - if ($this->getRotationAngle() !== 0) { - if (!function_exists('imagerotate')) { - throw new BCGDrawException('The method imagerotate doesn\'t exist on your server. Do not use any rotation.'); - } - - $w = imagefontwidth($this->font) * strlen($this->text); - $h = imagefontheight($this->font); - $gd = imagecreatetruecolor($w, $h); - imagefilledrectangle($gd, 0, 0, $w - 1, $h - 1, $this->backgroundColor->allocate($gd)); - imagestring($gd, $this->font, 0, 0, $this->text, $this->foregroundColor->allocate($gd)); - $gd = imagerotate($gd, $this->rotationAngle, 0); - imagecopy($im, $gd, $x, $y, 0, 0, imagesx($gd), imagesy($gd)); - } else { - imagestring($im, $this->font, $x, $y, $this->text, $this->foregroundColor->allocate($im)); - } - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGLabel.php b/niucloud/core/core/util/barcode/class/BCGLabel.php deleted file mode 100644 index 7c933c74..00000000 --- a/niucloud/core/core/util/barcode/class/BCGLabel.php +++ /dev/null @@ -1,320 +0,0 @@ -setFont($font); - $this->setText($text); - $this->setPosition($position); - $this->setAlignment($alignment); - $this->setSpacing(4); - $this->setOffset(0); - $this->setRotationAngle(0); - $this->setBackgroundColor(new BCGColor('white')); - $this->setForegroundColor(new BCGColor('black')); - } - - /** - * Gets the text. - * - * @return string - */ - public function getText() { - return $this->font->getText(); - } - - /** - * Sets the text. - * - * @param string $text - */ - public function setText($text) { - $this->text = $text; - $this->font->setText($this->text); - } - - /** - * Gets the font. - * - * @return BCGFont - */ - public function getFont() { - return $this->font; - } - - /** - * Sets the font. - * - * @param BCGFont $font - */ - public function setFont($font) { - if ($font === null) { - throw new BCGArgumentException('Font cannot be null.', 'font'); - } - - $this->font = clone $font; - $this->font->setText($this->text); - $this->font->setRotationAngle($this->rotationAngle); - $this->font->setBackgroundColor($this->backgroundColor); - $this->font->setForegroundColor($this->foregroundColor); - } - - /** - * Gets the text position for drawing. - * - * @return int - */ - public function getPosition() { - return $this->position; - } - - /** - * Sets the text position for drawing. - * - * @param int $position - */ - public function setPosition($position) { - $position = intval($position); - if ($position !== self::POSITION_TOP && $position !== self::POSITION_RIGHT && $position !== self::POSITION_BOTTOM && $position !== self::POSITION_LEFT) { - throw new BCGArgumentException('The text position must be one of a valid constant.', 'position'); - } - - $this->position = $position; - } - - /** - * Gets the text alignment for drawing. - * - * @return int - */ - public function getAlignment() { - return $this->alignment; - } - - /** - * Sets the text alignment for drawing. - * - * @param int $alignment - */ - public function setAlignment($alignment) { - $alignment = intval($alignment); - if ($alignment !== self::ALIGN_LEFT && $alignment !== self::ALIGN_TOP && $alignment !== self::ALIGN_CENTER && $alignment !== self::ALIGN_RIGHT && $alignment !== self::ALIGN_BOTTOM) { - throw new BCGArgumentException('The text alignment must be one of a valid constant.', 'alignment'); - } - - $this->alignment = $alignment; - } - - /** - * Gets the offset. - * - * @return int - */ - public function getOffset() { - return $this->offset; - } - - /** - * Sets the offset. - * - * @param int $offset - */ - public function setOffset($offset) { - $this->offset = intval($offset); - } - - /** - * Gets the spacing. - * - * @return int - */ - public function getSpacing() { - return $this->spacing; - } - - /** - * Sets the spacing. - * - * @param int $spacing - */ - public function setSpacing($spacing) { - $this->spacing = max(0, intval($spacing)); - } - - /** - * Gets the rotation angle in degree. - * - * @return int - */ - public function getRotationAngle() { - return $this->font->getRotationAngle(); - } - - /** - * Sets the rotation angle in degree. - * - * @param int $rotationAngle - */ - public function setRotationAngle($rotationAngle) { - $this->rotationAngle = intval($rotationAngle); - $this->font->setRotationAngle($this->rotationAngle); - } - - /** - * Gets the background color in case of rotation. - * - * @return BCGColor - */ - public function getBackgroundColor() { - return $this->backgroundColor; - } - - /** - * Sets the background color in case of rotation. - * - * @param BCGColor $backgroundColor - */ - public /*internal*/ function setBackgroundColor($backgroundColor) { - $this->backgroundColor = $backgroundColor; - $this->font->setBackgroundColor($this->backgroundColor); - } - - /** - * Gets the foreground color. - * - * @return BCGColor - */ - public function getForegroundColor() { - return $this->font->getForegroundColor(); - } - - /** - * Sets the foreground color. - * - * @param BCGColor $foregroundColor - */ - public function setForegroundColor($foregroundColor) { - $this->foregroundColor = $foregroundColor; - $this->font->setForegroundColor($this->foregroundColor); - } - - /** - * Gets the dimension taken by the label, including the spacing and offset. - * [0]: width - * [1]: height - * - * @return int[] - */ - public function getDimension() { - $w = 0; - $h = 0; - - $dimension = $this->font->getDimension(); - $w = $dimension[0]; - $h = $dimension[1]; - - if ($this->position === self::POSITION_TOP || $this->position === self::POSITION_BOTTOM) { - $h += $this->spacing; - $w += max(0, $this->offset); - } else { - $w += $this->spacing; - $h += max(0, $this->offset); - } - - return array($w, $h); - } - - /** - * Draws the text. - * The coordinate passed are the positions of the barcode. - * $x1 and $y1 represent the top left corner. - * $x2 and $y2 represent the bottom right corner. - * - * @param resource $im - * @param int $x1 - * @param int $y1 - * @param int $x2 - * @param int $y2 - */ - public /*internal*/ function draw($im, $x1, $y1, $x2, $y2) { - $x = 0; - $y = 0; - - $fontDimension = $this->font->getDimension(); - - if ($this->position === self::POSITION_TOP || $this->position === self::POSITION_BOTTOM) { - if ($this->position === self::POSITION_TOP) { - $y = $y1 - $this->spacing - $fontDimension[1]; - } elseif ($this->position === self::POSITION_BOTTOM) { - $y = $y2 + $this->spacing; - } - - if ($this->alignment === self::ALIGN_CENTER) { - $x = ($x2 - $x1) / 2 + $x1 - $fontDimension[0] / 2 + $this->offset; - } elseif ($this->alignment === self::ALIGN_LEFT) { - $x = $x1 + $this->offset; - } else { - $x = $x2 + $this->offset - $fontDimension[0]; - } - } else { - if ($this->position === self::POSITION_LEFT) { - $x = $x1 - $this->spacing - $fontDimension[0]; - } elseif ($this->position === self::POSITION_RIGHT) { - $x = $x2 + $this->spacing; - } - - if ($this->alignment === self::ALIGN_CENTER) { - $y = ($y2 - $y1) / 2 + $y1 - $fontDimension[1] / 2 + $this->offset; - } elseif ($this->alignment === self::ALIGN_TOP) { - $y = $y1 + $this->offset; - } else { - $y = $y2 + $this->offset - $fontDimension[1]; - } - } - - $this->font->setText($this->text); - $this->font->draw($im, $x, $y); - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGParseException.php b/niucloud/core/core/util/barcode/class/BCGParseException.php deleted file mode 100644 index ce4eeb9f..00000000 --- a/niucloud/core/core/util/barcode/class/BCGParseException.php +++ /dev/null @@ -1,25 +0,0 @@ -barcode = $barcode; - parent::__construct($message, 10000); - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGcodabar.barcode.php b/niucloud/core/core/util/barcode/class/BCGcodabar.barcode.php deleted file mode 100644 index 91189fed..00000000 --- a/niucloud/core/core/util/barcode/class/BCGcodabar.barcode.php +++ /dev/null @@ -1,122 +0,0 @@ -keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '$', ':', '/', '.', '+', 'A', 'B', 'C', 'D'); - $this->code = array( // 0 added to add an extra space - '00000110', /* 0 */ - '00001100', /* 1 */ - '00010010', /* 2 */ - '11000000', /* 3 */ - '00100100', /* 4 */ - '10000100', /* 5 */ - '01000010', /* 6 */ - '01001000', /* 7 */ - '01100000', /* 8 */ - '10010000', /* 9 */ - '00011000', /* - */ - '00110000', /* $ */ - '10001010', /* : */ - '10100010', /* / */ - '10101000', /* . */ - '00111110', /* + */ - '00110100', /* A */ - '01010010', /* B */ - '00010110', /* C */ - '00011100' /* D */ - ); - } - - /** - * Parses the text before displaying it. - * - * @param mixed $text - */ - public function parse($text) { - parent::parse(strtoupper($text)); // Only Capital Letters are Allowed - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - $c = strlen($this->text); - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, $this->findCode($this->text[$i]), true); - } - - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $textLength = 0; - $c = strlen($this->text); - for ($i = 0; $i < $c; $i++) { - $index = $this->findIndex($this->text[$i]); - if ($index !== false) { - $textLength += 8; - $textLength += substr_count($this->code[$index], '1'); - } - } - - $w += $textLength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Validates the input. - */ - protected function validate() { - $c = strlen($this->text); - if ($c === 0) { - throw new BCGParseException('codabar', 'No data has been entered.'); - } - - // Checking if all chars are allowed - for ($i = 0; $i < $c; $i++) { - if (array_search($this->text[$i], $this->keys) === false) { - throw new BCGParseException('codabar', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } - } - - // Must start by A, B, C or D - if ($c == 0 || ($this->text[0] !== 'A' && $this->text[0] !== 'B' && $this->text[0] !== 'C' && $this->text[0] !== 'D')) { - throw new BCGParseException('codabar', 'The text must start by the character A, B, C, or D.'); - } - - // Must end by A, B, C or D - $c2 = $c - 1; - if ($c2 === 0 || ($this->text[$c2] !== 'A' && $this->text[$c2] !== 'B' && $this->text[$c2] !== 'C' && $this->text[$c2] !== 'D')) { - throw new BCGParseException('codabar', 'The text must end by the character A, B, C, or D.'); - } - - parent::validate(); - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGcode11.barcode.php b/niucloud/core/core/util/barcode/class/BCGcode11.barcode.php deleted file mode 100644 index 7c11a22c..00000000 --- a/niucloud/core/core/util/barcode/class/BCGcode11.barcode.php +++ /dev/null @@ -1,185 +0,0 @@ -keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-'); - $this->code = array( // 0 added to add an extra space - '000010', /* 0 */ - '100010', /* 1 */ - '010010', /* 2 */ - '110000', /* 3 */ - '001010', /* 4 */ - '101000', /* 5 */ - '011000', /* 6 */ - '000110', /* 7 */ - '100100', /* 8 */ - '100000', /* 9 */ - '001000' /* - */ - ); - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - // Starting Code - $this->drawChar($im, '001100', true); - - // Chars - $c = strlen($this->text); - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, $this->findCode($this->text[$i]), true); - } - - // Checksum - $this->calculateChecksum(); - $c = count($this->checksumValue); - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, $this->code[$this->checksumValue[$i]], true); - } - - // Ending Code - $this->drawChar($im, '00110', true); - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $startlength = 8; - - $textlength = 0; - $c = strlen($this->text); - for ($i = 0; $i < $c; $i++) { - $textlength += $this->getIndexLength($this->findIndex($this->text[$i])); - } - - $checksumlength = 0; - $this->calculateChecksum(); - $c = count($this->checksumValue); - for ($i = 0; $i < $c; $i++) { - $checksumlength += $this->getIndexLength($this->checksumValue[$i]); - } - - $endlength = 7; - - $w += $startlength + $textlength + $checksumlength + $endlength; - $h += $this->thickness; - - return parent::getDimension($w, $h); - } - - /** - * Validates the input. - */ - protected function validate() { - $c = strlen($this->text); - if ($c === 0) { - throw new BCGParseException('code11', 'No data has been entered.'); - } - - // Checking if all chars are allowed - for ($i = 0; $i < $c; $i++) { - if (array_search($this->text[$i], $this->keys) === false) { - throw new BCGParseException('code11', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } - } - - parent::validate(); - } - - /** - * Overloaded method to calculate checksum. - */ - protected function calculateChecksum() { - // Checksum - // First CheckSUM "C" - // The "C" checksum character is the modulo 11 remainder of the sum of the weighted - // value of the data characters. The weighting value starts at "1" for the right-most - // data character, 2 for the second to last, 3 for the third-to-last, and so on up to 20. - // After 10, the sequence wraps around back to 1. - - // Second CheckSUM "K" - // Same as CheckSUM "C" but we count the CheckSum "C" at the end - // After 9, the sequence wraps around back to 1. - $sequence_multiplier = array(10, 9); - $temp_text = $this->text; - $this->checksumValue = array(); - for ($z = 0; $z < 2; $z++) { - $c = strlen($temp_text); - - // We don't display the K CheckSum if the original text had a length less than 10 - if ($c <= 10 && $z === 1) { - break; - } - - $checksum = 0; - for ($i = $c, $j = 0; $i > 0; $i--, $j++) { - $multiplier = $i % $sequence_multiplier[$z]; - if ($multiplier === 0) { - $multiplier = $sequence_multiplier[$z]; - } - - $checksum += $this->findIndex($temp_text[$j]) * $multiplier; - } - - $this->checksumValue[$z] = $checksum % 11; - $temp_text .= $this->keys[$this->checksumValue[$z]]; - } - } - - /** - * Overloaded method to display the checksum. - */ - protected function processChecksum() { - if ($this->checksumValue === false) { // Calculate the checksum only once - $this->calculateChecksum(); - } - - if ($this->checksumValue !== false) { - $ret = ''; - $c = count($this->checksumValue); - for ($i = 0; $i < $c; $i++) { - $ret .= $this->keys[$this->checksumValue[$i]]; - } - - return $ret; - } - - return false; - } - - private function getIndexLength($index) { - $length = 0; - if ($index !== false) { - $length += 6; - $length += substr_count($this->code[$index], '1'); - } - - return $length; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGcode128.barcode.php b/niucloud/core/core/util/barcode/class/BCGcode128.barcode.php deleted file mode 100644 index 0cfeed6f..00000000 --- a/niucloud/core/core/util/barcode/class/BCGcode128.barcode.php +++ /dev/null @@ -1,885 +0,0 @@ -keysA = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'; - for ($i = 0; $i < 32; $i++) { - $this->keysA .= chr($i); - } - - /* CODE 128 B */ - $this->keysB = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~' . chr(127); - - /* CODE 128 C */ - $this->keysC = '0123456789'; - - $this->code = array( - '101111', /* 00 */ - '111011', /* 01 */ - '111110', /* 02 */ - '010112', /* 03 */ - '010211', /* 04 */ - '020111', /* 05 */ - '011102', /* 06 */ - '011201', /* 07 */ - '021101', /* 08 */ - '110102', /* 09 */ - '110201', /* 10 */ - '120101', /* 11 */ - '001121', /* 12 */ - '011021', /* 13 */ - '011120', /* 14 */ - '002111', /* 15 */ - '012011', /* 16 */ - '012110', /* 17 */ - '112100', /* 18 */ - '110021', /* 19 */ - '110120', /* 20 */ - '102101', /* 21 */ - '112001', /* 22 */ - '201020', /* 23 */ - '200111', /* 24 */ - '210011', /* 25 */ - '210110', /* 26 */ - '201101', /* 27 */ - '211001', /* 28 */ - '211100', /* 29 */ - '101012', /* 30 */ - '101210', /* 31 */ - '121010', /* 32 */ - '000212', /* 33 */ - '020012', /* 34 */ - '020210', /* 35 */ - '001202', /* 36 */ - '021002', /* 37 */ - '021200', /* 38 */ - '100202', /* 39 */ - '120002', /* 40 */ - '120200', /* 41 */ - '001022', /* 42 */ - '001220', /* 43 */ - '021020', /* 44 */ - '002012', /* 45 */ - '002210', /* 46 */ - '022010', /* 47 */ - '202010', /* 48 */ - '100220', /* 49 */ - '120020', /* 50 */ - '102002', /* 51 */ - '102200', /* 52 */ - '102020', /* 53 */ - '200012', /* 54 */ - '200210', /* 55 */ - '220010', /* 56 */ - '201002', /* 57 */ - '201200', /* 58 */ - '221000', /* 59 */ - '203000', /* 60 */ - '110300', /* 61 */ - '320000', /* 62 */ - '000113', /* 63 */ - '000311', /* 64 */ - '010013', /* 65 */ - '010310', /* 66 */ - '030011', /* 67 */ - '030110', /* 68 */ - '001103', /* 69 */ - '001301', /* 70 */ - '011003', /* 71 */ - '011300', /* 72 */ - '031001', /* 73 */ - '031100', /* 74 */ - '130100', /* 75 */ - '110003', /* 76 */ - '302000', /* 77 */ - '130001', /* 78 */ - '023000', /* 79 */ - '000131', /* 80 */ - '010031', /* 81 */ - '010130', /* 82 */ - '003101', /* 83 */ - '013001', /* 84 */ - '013100', /* 85 */ - '300101', /* 86 */ - '310001', /* 87 */ - '310100', /* 88 */ - '101030', /* 89 */ - '103010', /* 90 */ - '301010', /* 91 */ - '000032', /* 92 */ - '000230', /* 93 */ - '020030', /* 94 */ - '003002', /* 95 */ - '003200', /* 96 */ - '300002', /* 97 */ - '300200', /* 98 */ - '002030', /* 99 */ - '003020', /* 100*/ - '200030', /* 101*/ - '300020', /* 102*/ - '100301', /* 103*/ - '100103', /* 104*/ - '100121', /* 105*/ - '122000' /*STOP*/ - ); - $this->setStart($start); - $this->setTilde(true); - - // Latches and Shifts - $this->latch = array( - array(null, self::KEYA_CODEB, self::KEYA_CODEC), - array(self::KEYB_CODEA, null, self::KEYB_CODEC), - array(self::KEYC_CODEA, self::KEYC_CODEB, null) - ); - $this->shift = array( - array(null, self::KEYA_SHIFT), - array(self::KEYB_SHIFT, null) - ); - $this->fnc = array( - array(self::KEYA_FNC1, self::KEYA_FNC2, self::KEYA_FNC3, self::KEYA_FNC4), - array(self::KEYB_FNC1, self::KEYB_FNC2, self::KEYB_FNC3, self::KEYB_FNC4), - array(self::KEYC_FNC1, null, null, null) - ); - - // Method available - $this->METHOD = array(CODE128_A => 'A', CODE128_B => 'B', CODE128_C => 'C'); - } - - /** - * Specifies the start code. Can be 'A', 'B', 'C', or null - * - Table A: Capitals + ASCII 0-31 + punct - * - Table B: Capitals + LowerCase + punct - * - Table C: Numbers - * - * If null is specified, the table selection is automatically made. - * The default is null. - * - * @param string $table - */ - public function setStart($table) { - if ($table !== 'A' && $table !== 'B' && $table !== 'C' && $table !== null) { - throw new BCGArgumentException('The starting table must be A, B, C or null.', 'table'); - } - - $this->starting_text = $table; - } - - /** - * Gets the tilde. - * - * @return bool - */ - public function getTilde() { - return $this->tilde; - } - - /** - * Accepts tilde to be process as a special character. - * If true, you can do this: - * - ~~ : to make ONE tilde - * - ~Fx : to insert FCNx. x is equal from 1 to 4. - * - * @param boolean $accept - */ - public function setTilde($accept) { - $this->tilde = (bool)$accept; - } - - /** - * Parses the text before displaying it. - * - * @param mixed $text - */ - public function parse($text) { - $this->setStartFromText($text); - - $this->text = ''; - $seq = ''; - - $currentMode = $this->starting_text; - - // Here, we format correctly what the user gives. - if (!is_array($text)) { - $seq = $this->getSequence($text, $currentMode); - $this->text = $text; - } else { - // This loop checks for UnknownText AND raises an exception if a character is not allowed in a table - reset($text); - while (list($key1, $val1) = each($text)) { // We take each value - if (!is_array($val1)) { // This is not a table - if (is_string($val1)) { // If it's a string, parse as unknown - $seq .= $this->getSequence($val1, $currentMode); - $this->text .= $val1; - } else { - // it's the case of "array(ENCODING, 'text')" - // We got ENCODING in $val1, calling 'each' again will get 'text' in $val2 - list($key2, $val2) = each($text); - $seq .= $this->{'setParse' . $this->METHOD[$val1]}($val2, $currentMode); - $this->text .= $val2; - } - } else { // The method is specified - // $val1[0] = ENCODING - // $val1[1] = 'text' - $value = isset($val1[1]) ? $val1[1] : ''; // If data available - $seq .= $this->{'setParse' . $this->METHOD[$val1[0]]}($value, $currentMode); - $this->text .= $value; - } - } - } - - if ($seq !== '') { - $bitstream = $this->createBinaryStream($this->text, $seq); - $this->setData($bitstream); - } - - $this->addDefaultLabel(); - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - $c = count($this->data); - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, $this->data[$i], true); - } - - $this->drawChar($im, '1', true); - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - // Contains start + text + checksum + stop - $textlength = count($this->data) * 11; - $endlength = 2; // + final bar - - $w += $textlength + $endlength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Validates the input. - */ - protected function validate() { - $c = count($this->data); - if ($c === 0) { - throw new BCGParseException('code128', 'No data has been entered.'); - } - - parent::validate(); - } - - /** - * Overloaded method to calculate checksum. - */ - protected function calculateChecksum() { - // Checksum - // First Char (START) - // + Starting with the first data character following the start character, - // take the value of the character (between 0 and 102, inclusive) multiply - // it by its character position (1) and add that to the running checksum. - // Modulated 103 - $this->checksumValue = $this->indcheck[0]; - $c = count($this->indcheck); - for ($i = 1; $i < $c; $i++) { - $this->checksumValue += $this->indcheck[$i] * $i; - } - - $this->checksumValue = $this->checksumValue % 103; - } - - /** - * Overloaded method to display the checksum. - */ - protected function processChecksum() { - if ($this->checksumValue === false) { // Calculate the checksum only once - $this->calculateChecksum(); - } - - if ($this->checksumValue !== false) { - if ($this->lastTable === 'C') { - return (string)$this->checksumValue; - } - - return $this->{'keys' . $this->lastTable}[$this->checksumValue]; - } - - return false; - } - - /** - * Specifies the starting_text table if none has been specified earlier. - * - * @param string $text - */ - private function setStartFromText($text) { - if ($this->starting_text === null) { - // If we have a forced table at the start, we get that one... - if (is_array($text)) { - if (is_array($text[0])) { - // Code like array(array(ENCODING, '')) - $this->starting_text = $this->METHOD[$text[0][0]]; - return; - } else { - if (is_string($text[0])) { - // Code like array('test') (Automatic text) - $text = $text[0]; - } else { - // Code like array(ENCODING, '') - $this->starting_text = $this->METHOD[$text[0]]; - return; - } - } - } - - // At this point, we had an "automatic" table selection... - // If we can get at least 4 numbers, go in C; otherwise go in B. - $tmp = preg_quote($this->keysC, '/'); - $length = strlen($text); - if ($length >= 4 && preg_match('/[' . $tmp . ']/', substr($text, 0, 4))) { - $this->starting_text = 'C'; - } else { - if ($length > 0 && strpos($this->keysB, $text[0]) !== false) { - $this->starting_text = 'B'; - } else { - $this->starting_text = 'A'; - } - } - } - } - - /** - * Extracts the ~ value from the $text at the $pos. - * If the tilde is not ~~, ~F1, ~F2, ~F3, ~F4; an error is raised. - * - * @param string $text - * @param int $pos - * @return string - */ - private static function extractTilde($text, $pos) { - if ($text[$pos] === '~') { - if (isset($text[$pos + 1])) { - // Do we have a tilde? - if ($text[$pos + 1] === '~') { - return '~~'; - } elseif ($text[$pos + 1] === 'F') { - // Do we have a number after? - if (isset($text[$pos + 2])) { - $v = intval($text[$pos + 2]); - if ($v >= 1 && $v <= 4) { - return '~F' . $v; - } else { - throw new BCGParseException('code128', 'Bad ~F. You must provide a number from 1 to 4.'); - } - } else { - throw new BCGParseException('code128', 'Bad ~F. You must provide a number from 1 to 4.'); - } - } else { - throw new BCGParseException('code128', 'Wrong code after the ~.'); - } - } else { - throw new BCGParseException('code128', 'Wrong code after the ~.'); - } - } else { - throw new BCGParseException('code128', 'There is no ~ at this location.'); - } - } - - /** - * Gets the "dotted" sequence for the $text based on the $currentMode. - * There is also a check if we use the special tilde ~ - * - * @param string $text - * @param string $currentMode - * @return string - */ - private function getSequenceParsed($text, $currentMode) { - if ($this->tilde) { - $sequence = ''; - $previousPos = 0; - while (($pos = strpos($text, '~', $previousPos)) !== false) { - $tildeData = self::extractTilde($text, $pos); - - $simpleTilde = ($tildeData === '~~'); - if ($simpleTilde && $currentMode !== 'B') { - throw new BCGParseException('code128', 'The Table ' . $currentMode . ' doesn\'t contain the character ~.'); - } - - // At this point, we know we have ~Fx - if ($tildeData !== '~F1' && $currentMode === 'C') { - // The mode C doesn't support ~F2, ~F3, ~F4 - throw new BCGParseException('code128', 'The Table C doesn\'t contain the function ' . $tildeData . '.'); - } - - $length = $pos - $previousPos; - if ($currentMode === 'C') { - if ($length % 2 === 1) { - throw new BCGParseException('code128', 'The text "' . $text . '" must have an even number of character to be encoded in Table C.'); - } - } - - $sequence .= str_repeat('.', $length); - $sequence .= '.'; - $sequence .= (!$simpleTilde) ? 'F' : ''; - $previousPos = $pos + strlen($tildeData); - } - - // Flushing - $length = strlen($text) - $previousPos; - if ($currentMode === 'C') { - if ($length % 2 === 1) { - throw new BCGParseException('code128', 'The text "' . $text . '" must have an even number of character to be encoded in Table C.'); - } - } - - $sequence .= str_repeat('.', $length); - - return $sequence; - } else { - return str_repeat('.', strlen($text)); - } - } - - /** - * Parses the text and returns the appropriate sequence for the Table A. - * - * @param string $text - * @param string $currentMode - * @return string - */ - private function setParseA($text, &$currentMode) { - $tmp = preg_quote($this->keysA, '/'); - - // If we accept the ~ for special character, we must allow it. - if ($this->tilde) { - $tmp .= '~'; - } - - $match = array(); - if (preg_match('/[^' . $tmp . ']/', $text, $match) === 1) { - // We found something not allowed - throw new BCGParseException('code128', 'The text "' . $text . '" can\'t be parsed with the Table A. The character "' . $match[0] . '" is not allowed.'); - } else { - $latch = ($currentMode === 'A') ? '' : '0'; - $currentMode = 'A'; - - return $latch . $this->getSequenceParsed($text, $currentMode); - } - } - - /** - * Parses the text and returns the appropriate sequence for the Table B. - * - * @param string $text - * @param string $currentMode - * @return string - */ - private function setParseB($text, &$currentMode) { - $tmp = preg_quote($this->keysB, '/'); - - $match = array(); - if (preg_match('/[^' . $tmp . ']/', $text, $match) === 1) { - // We found something not allowed - throw new BCGParseException('code128', 'The text "' . $text . '" can\'t be parsed with the Table B. The character "' . $match[0] . '" is not allowed.'); - } else { - $latch = ($currentMode === 'B') ? '' : '1'; - $currentMode = 'B'; - - return $latch . $this->getSequenceParsed($text, $currentMode); - } - } - - /** - * Parses the text and returns the appropriate sequence for the Table C. - * - * @param string $text - * @param string $currentMode - * @return string - */ - private function setParseC($text, &$currentMode) { - $tmp = preg_quote($this->keysC, '/'); - - // If we accept the ~ for special character, we must allow it. - if ($this->tilde) { - $tmp .= '~F'; - } - - $match = array(); - if (preg_match('/[^' . $tmp . ']/', $text, $match) === 1) { - // We found something not allowed - throw new BCGParseException('code128', 'The text "' . $text . '" can\'t be parsed with the Table C. The character "' . $match[0] . '" is not allowed.'); - } else { - $latch = ($currentMode === 'C') ? '' : '2'; - $currentMode = 'C'; - - return $latch . $this->getSequenceParsed($text, $currentMode); - } - } - - /** - * Depending on the $text, it will return the correct - * sequence to encode the text. - * - * @param string $text - * @param string $starting_text - * @return string - */ - private function getSequence($text, &$starting_text) { - $e = 10000; - $latLen = array( - array(0, 1, 1), - array(1, 0, 1), - array(1, 1, 0) - ); - $shftLen = array( - array($e, 1, $e), - array(1, $e, $e), - array($e, $e, $e) - ); - $charSiz = array(2, 2, 1); - - $startA = $e; - $startB = $e; - $startC = $e; - if ($starting_text === 'A') { $startA = 0; } - if ($starting_text === 'B') { $startB = 0; } - if ($starting_text === 'C') { $startC = 0; } - - $curLen = array($startA, $startB, $startC); - $curSeq = array(null, null, null); - - $nextNumber = false; - - $x = 0; - $xLen = strlen($text); - for ($x = 0; $x < $xLen; $x++) { - $input = $text[$x]; - - // 1. - for ($i = 0; $i < 3; $i++) { - for ($j = 0; $j < 3; $j++) { - if (($curLen[$i] + $latLen[$i][$j]) < $curLen[$j]) { - $curLen[$j] = $curLen[$i] + $latLen[$i][$j]; - $curSeq[$j] = $curSeq[$i] . $j; - } - } - } - - // 2. - $nxtLen = array($e, $e, $e); - $nxtSeq = array(); - - // 3. - $flag = false; - $posArray = array(); - - // Special case, we do have a tilde and we process them - if ($this->tilde && $input === '~') { - $tildeData = self::extractTilde($text, $x); - - if ($tildeData === '~~') { - // We simply skip a tilde - $posArray[] = 1; - $x++; - } elseif (substr($tildeData, 0, 2) === '~F') { - $v = intval($tildeData[2]); - $posArray[] = 0; - $posArray[] = 1; - if ($v === 1) { - $posArray[] = 2; - } - - $x += 2; - $flag = true; - } - } else { - $pos = strpos($this->keysA, $input); - if ($pos !== false) { - $posArray[] = 0; - } - - $pos = strpos($this->keysB, $input); - if ($pos !== false) { - $posArray[] = 1; - } - - // Do we have the next char a number?? OR a ~F1 - $pos = strpos($this->keysC, $input); - if ($nextNumber || ($pos !== false && isset($text[$x + 1]) && strpos($this->keysC, $text[$x + 1]) !== false)) { - $nextNumber = !$nextNumber; - $posArray[] = 2; - } - } - - $c = count($posArray); - for ($i = 0; $i < $c; $i++) { - if (($curLen[$posArray[$i]] + $charSiz[$posArray[$i]]) < $nxtLen[$posArray[$i]]) { - $nxtLen[$posArray[$i]] = $curLen[$posArray[$i]] + $charSiz[$posArray[$i]]; - $nxtSeq[$posArray[$i]] = $curSeq[$posArray[$i]] . '.'; - } - - for ($j = 0; $j < 2; $j++) { - if ($j === $posArray[$i]) { continue; } - if (($curLen[$j] + $shftLen[$j][$posArray[$i]] + $charSiz[$posArray[$i]]) < $nxtLen[$j]) { - $nxtLen[$j] = $curLen[$j] + $shftLen[$j][$posArray[$i]] + $charSiz[$posArray[$i]]; - $nxtSeq[$j] = $curSeq[$j] . chr($posArray[$i] + 65) . '.'; - } - } - } - - if ($c === 0) { - // We found an unsuported character - throw new BCGParseException('code128', 'Character ' . $input . ' not supported.'); - } - - if ($flag) { - for ($i = 0; $i < 5; $i++) { - if (isset($nxtSeq[$i])) { - $nxtSeq[$i] .= 'F'; - } - } - } - - // 4. - for ($i = 0; $i < 3; $i++) { - $curLen[$i] = $nxtLen[$i]; - if (isset($nxtSeq[$i])) { - $curSeq[$i] = $nxtSeq[$i]; - } - } - } - - // Every curLen under $e is possible but we take the smallest - $m = $e; - $k = -1; - for ($i = 0; $i < 3; $i++) { - if ($curLen[$i] < $m) { - $k = $i; - $m = $curLen[$i]; - } - } - - if ($k === -1) { - return ''; - } - - return $curSeq[$k]; - } - - /** - * Depending on the sequence $seq given (returned from getSequence()), - * this method will return the code stream in an array. Each char will be a - * string of bit based on the Code 128. - * - * Each letter from the sequence represents bits. - * - * 0 to 2 are latches - * A to B are Shift + Letter - * . is a char in the current encoding - * - * @param string $text - * @param string $seq - * @return string[][] - */ - private function createBinaryStream($text, $seq) { - $c = strlen($seq); - - $data = array(); // code stream - $indcheck = array(); // index for checksum - - $currentEncoding = 0; - if ($this->starting_text === 'A') { - $currentEncoding = 0; - $indcheck[] = self::KEY_STARTA; - $this->lastTable = 'A'; - } elseif ($this->starting_text === 'B') { - $currentEncoding = 1; - $indcheck[] = self::KEY_STARTB; - $this->lastTable = 'B'; - } elseif ($this->starting_text === 'C') { - $currentEncoding = 2; - $indcheck[] = self::KEY_STARTC; - $this->lastTable = 'C'; - } - - $data[] = $this->code[103 + $currentEncoding]; - - $temporaryEncoding = -1; - for ($i = 0, $counter = 0; $i < $c; $i++) { - $input = $seq[$i]; - $inputI = intval($input); - if ($input === '.') { - $this->encodeChar($data, $currentEncoding, $seq, $text, $i, $counter, $indcheck); - if ($temporaryEncoding !== -1) { - $currentEncoding = $temporaryEncoding; - $temporaryEncoding = -1; - } - } elseif ($input >= 'A' && $input <= 'B') { - // We shift - $encoding = ord($input) - 65; - $shift = $this->shift[$currentEncoding][$encoding]; - $indcheck[] = $shift; - $data[] = $this->code[$shift]; - if ($temporaryEncoding === -1) { - $temporaryEncoding = $currentEncoding; - } - - $currentEncoding = $encoding; - } elseif ($inputI >= 0 && $inputI < 3) { - $temporaryEncoding = -1; - - // We latch - $latch = $this->latch[$currentEncoding][$inputI]; - if ($latch !== null) { - $indcheck[] = $latch; - $this->lastTable = chr(65 + $inputI); - $data[] = $this->code[$latch]; - $currentEncoding = $inputI; - } - } - } - - return array($indcheck, $data); - } - - /** - * Encodes characters, base on its encoding and sequence - * - * @param int[] $data - * @param int $encoding - * @param string $seq - * @param string $text - * @param int $i - * @param int $counter - * @param int[] $indcheck - */ - private function encodeChar(&$data, $encoding, $seq, $text, &$i, &$counter, &$indcheck) { - if (isset($seq[$i + 1]) && $seq[$i + 1] === 'F') { - // We have a flag !! - if ($text[$counter + 1] === 'F') { - $number = $text[$counter + 2]; - $fnc = $this->fnc[$encoding][$number - 1]; - $indcheck[] = $fnc; - $data[] = $this->code[$fnc]; - - // Skip F + number - $counter += 2; - } else { - // Not supposed - } - - $i++; - } else { - if ($encoding === 2) { - // We take 2 numbers in the same time - $code = (int)substr($text, $counter, 2); - $indcheck[] = $code; - $data[] = $this->code[$code]; - $counter++; - $i++; - } else { - $keys = ($encoding === 0) ? $this->keysA : $this->keysB; - $pos = strpos($keys, $text[$counter]); - $indcheck[] = $pos; - $data[] = $this->code[$pos]; - } - } - - $counter++; - } - - /** - * Saves data into the classes. - * - * This method will save data, calculate real column number - * (if -1 was selected), the real error level (if -1 was - * selected)... It will add Padding to the end and generate - * the error codes. - * - * @param array $data - */ - private function setData($data) { - $this->indcheck = $data[0]; - $this->data = $data[1]; - $this->calculateChecksum(); - $this->data[] = $this->code[$this->checksumValue]; - $this->data[] = $this->code[self::KEY_STOP]; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGcode39.barcode.php b/niucloud/core/core/util/barcode/class/BCGcode39.barcode.php deleted file mode 100644 index 11e37124..00000000 --- a/niucloud/core/core/util/barcode/class/BCGcode39.barcode.php +++ /dev/null @@ -1,193 +0,0 @@ -starting = $this->ending = 43; - $this->keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%', '*'); - $this->code = array( // 0 added to add an extra space - '0001101000', /* 0 */ - '1001000010', /* 1 */ - '0011000010', /* 2 */ - '1011000000', /* 3 */ - '0001100010', /* 4 */ - '1001100000', /* 5 */ - '0011100000', /* 6 */ - '0001001010', /* 7 */ - '1001001000', /* 8 */ - '0011001000', /* 9 */ - '1000010010', /* A */ - '0010010010', /* B */ - '1010010000', /* C */ - '0000110010', /* D */ - '1000110000', /* E */ - '0010110000', /* F */ - '0000011010', /* G */ - '1000011000', /* H */ - '0010011000', /* I */ - '0000111000', /* J */ - '1000000110', /* K */ - '0010000110', /* L */ - '1010000100', /* M */ - '0000100110', /* N */ - '1000100100', /* O */ - '0010100100', /* P */ - '0000001110', /* Q */ - '1000001100', /* R */ - '0010001100', /* S */ - '0000101100', /* T */ - '1100000010', /* U */ - '0110000010', /* V */ - '1110000000', /* W */ - '0100100010', /* X */ - '1100100000', /* Y */ - '0110100000', /* Z */ - '0100001010', /* - */ - '1100001000', /* . */ - '0110001000', /* */ - '0101010000', /* $ */ - '0101000100', /* / */ - '0100010100', /* + */ - '0001010100', /* % */ - '0100101000' /* * */ - ); - - $this->setChecksum(false); - } - - /** - * Sets if we display the checksum. - * - * @param bool $checksum - */ - public function setChecksum($checksum) { - $this->checksum = (bool)$checksum; - } - - /** - * Parses the text before displaying it. - * - * @param mixed $text - */ - public function parse($text) { - parent::parse(strtoupper($text)); // Only Capital Letters are Allowed - } - - /** - * Draws the Barcode. - * - * @param resource $im - */ - public function draw($im) { - // Starting * - $this->drawChar($im, $this->code[$this->starting], true); - - // Chars - $c = strlen($this->text); - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, $this->findCode($this->text[$i]), true); - } - - // Checksum (rarely used) - if ($this->checksum === true) { - $this->calculateChecksum(); - $this->drawChar($im, $this->code[$this->checksumValue % 43], true); - } - - // Ending * - $this->drawChar($im, $this->code[$this->ending], true); - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - } - - /** - * Returns the maximal size of a Barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $textlength = 13 * strlen($this->text); - $startlength = 13; - $checksumlength = 0; - if ($this->checksum === true) { - $checksumlength = 13; - } - - $endlength = 13; - - $w += $startlength + $textlength + $checksumlength + $endlength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Validates the input. - */ - protected function validate() { - $c = strlen($this->text); - if ($c === 0) { - throw new BCGParseException('code39', 'No data has been entered.'); - } - - // Checking if all chars are allowed - for ($i = 0; $i < $c; $i++) { - if (array_search($this->text[$i], $this->keys) === false) { - throw new BCGParseException('code39', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } - } - - if (strpos($this->text, '*') !== false) { - throw new BCGParseException('code39', 'The character \'*\' is not allowed.'); - } - - parent::validate(); - } - - /** - * Overloaded method to calculate checksum. - */ - protected function calculateChecksum() { - $this->checksumValue = 0; - $c = strlen($this->text); - for ($i = 0; $i < $c; $i++) { - $this->checksumValue += $this->findIndex($this->text[$i]); - } - - $this->checksumValue = $this->checksumValue % 43; - } - - /** - * Overloaded method to display the checksum. - */ - protected function processChecksum() { - if ($this->checksumValue === false) { // Calculate the checksum only once - $this->calculateChecksum(); - } - - if ($this->checksumValue !== false) { - return $this->keys[$this->checksumValue]; - } - - return false; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGcode39extended.barcode.php b/niucloud/core/core/util/barcode/class/BCGcode39extended.barcode.php deleted file mode 100644 index fca6f1a2..00000000 --- a/niucloud/core/core/util/barcode/class/BCGcode39extended.barcode.php +++ /dev/null @@ -1,208 +0,0 @@ -keys[self::EXTENDED_1] = '($)'; - $this->keys[self::EXTENDED_2] = '(/)'; - $this->keys[self::EXTENDED_3] = '(+)'; - $this->keys[self::EXTENDED_4] = '(%)'; - } - - /** - * Parses the text before displaying it. - * - * @param mixed $text - */ - public function parse($text) { - $this->text = $text; - - $data = array(); - $indcheck = array(); - - $c = strlen($this->text); - for ($i = 0; $i < $c; $i++) { - $pos = array_search($this->text[$i], $this->keys); - if ($pos === false) { - // Search in extended? - $extended = self::getExtendedVersion($this->text[$i]); - if ($extended === false) { - throw new BCGParseException('code39extended', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } else { - $extc = strlen($extended); - for ($j = 0; $j < $extc; $j++) { - $v = $extended[$j]; - if ($v === '$') { - $indcheck[] = self::EXTENDED_1; - $data[] = $this->code[self::EXTENDED_1]; - } elseif ($v === '%') { - $indcheck[] = self::EXTENDED_2; - $data[] = $this->code[self::EXTENDED_2]; - } elseif ($v === '/') { - $indcheck[] = self::EXTENDED_3; - $data[] = $this->code[self::EXTENDED_3]; - } elseif ($v === '+') { - $indcheck[] = self::EXTENDED_4; - $data[] = $this->code[self::EXTENDED_4]; - } else { - $pos2 = array_search($v, $this->keys); - $indcheck[] = $pos2; - $data[] = $this->code[$pos2]; - } - } - } - } else { - $indcheck[] = $pos; - $data[] = $this->code[$pos]; - } - } - - $this->setData(array($indcheck, $data)); - $this->addDefaultLabel(); - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - // Starting * - $this->drawChar($im, $this->code[$this->starting], true); - $c = count($this->data); - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, $this->data[$i], true); - } - - // Checksum (rarely used) - if ($this->checksum === true) { - $this->drawChar($im, $this->code[$this->checksumValue % 43], true); - } - - // Ending * - $this->drawChar($im, $this->code[$this->ending], true); - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $textlength = 13 * count($this->data); - $startlength = 13; - $checksumlength = 0; - if ($this->checksum === true) { - $checksumlength = 13; - } - - $endlength = 13; - - $w += $startlength + $textlength + $checksumlength + $endlength; - $h += $this->thickness; - return BCGBarcode1D::getDimension($w, $h); - } - - /** - * Validates the input. - */ - protected function validate() { - $c = count($this->data); - if ($c === 0) { - throw new BCGParseException('code39extended', 'No data has been entered.'); - } - - parent::validate(); - } - - /** - * Overloaded method to calculate checksum. - */ - protected function calculateChecksum() { - $this->checksumValue = 0; - $c = count($this->indcheck); - for ($i = 0; $i < $c; $i++) { - $this->checksumValue += $this->indcheck[$i]; - } - - $this->checksumValue = $this->checksumValue % 43; - } - - /** - * Saves data into the classes. - * - * This method will save data, calculate real column number - * (if -1 was selected), the real error level (if -1 was - * selected)... It will add Padding to the end and generate - * the error codes. - * - * @param array $data - */ - private function setData($data) { - $this->indcheck = $data[0]; - $this->data = $data[1]; - $this->calculateChecksum(); - } - - /** - * Returns the extended reprensentation of the character. - * - * @param string $char - * @return string - */ - private static function getExtendedVersion($char) { - $o = ord($char); - if ($o === 0) { - return '%U'; - } elseif ($o >= 1 && $o <= 26) { - return '$' . chr($o + 64); - } elseif (($o >= 33 && $o <= 44) || $o === 47 || $o === 48) { - return '/' . chr($o + 32); - } elseif ($o >= 97 && $o <= 122) { - return '+' . chr($o - 32); - } elseif ($o >= 27 && $o <= 31) { - return '%' . chr($o + 38); - } elseif ($o >= 59 && $o <= 63) { - return '%' . chr($o + 11); - } elseif ($o >= 91 && $o <= 95) { - return '%' . chr($o - 16); - } elseif ($o >= 123 && $o <= 127) { - return '%' . chr($o - 43); - } elseif ($o === 64) { - return '%V'; - } elseif ($o === 96) { - return '%W'; - } elseif ($o > 127) { - return false; - } else { - return $char; - } - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGcode93.barcode.php b/niucloud/core/core/util/barcode/class/BCGcode93.barcode.php deleted file mode 100644 index 480e2c8f..00000000 --- a/niucloud/core/core/util/barcode/class/BCGcode93.barcode.php +++ /dev/null @@ -1,301 +0,0 @@ -starting = $this->ending = 47; /* * */ - $this->keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%', '($)', '(%)', '(/)', '(+)', '(*)'); - $this->code = array( - '020001', /* 0 */ - '000102', /* 1 */ - '000201', /* 2 */ - '000300', /* 3 */ - '010002', /* 4 */ - '010101', /* 5 */ - '010200', /* 6 */ - '000003', /* 7 */ - '020100', /* 8 */ - '030000', /* 9 */ - '100002', /* A */ - '100101', /* B */ - '100200', /* C */ - '110001', /* D */ - '110100', /* E */ - '120000', /* F */ - '001002', /* G */ - '001101', /* H */ - '001200', /* I */ - '011001', /* J */ - '021000', /* K */ - '000012', /* L */ - '000111', /* M */ - '000210', /* N */ - '010011', /* O */ - '020010', /* P */ - '101001', /* Q */ - '101100', /* R */ - '100011', /* S */ - '100110', /* T */ - '110010', /* U */ - '111000', /* V */ - '001011', /* W */ - '001110', /* X */ - '011010', /* Y */ - '012000', /* Z */ - '010020', /* - */ - '200001', /* . */ - '200100', /* */ - '210000', /* $ */ - '001020', /* / */ - '002010', /* + */ - '100020', /* % */ - '010110', /*($)*/ - '201000', /*(%)*/ - '200010', /*(/)*/ - '011100', /*(+)*/ - '000030' /*(*)*/ - ); - } - - /** - * Parses the text before displaying it. - * - * @param mixed $text - */ - public function parse($text) { - $this->text = $text; - - $data = array(); - $indcheck = array(); - - $c = strlen($this->text); - for ($i = 0; $i < $c; $i++) { - $pos = array_search($this->text[$i], $this->keys); - if ($pos === false) { - // Search in extended? - $extended = self::getExtendedVersion($this->text[$i]); - if ($extended === false) { - throw new BCGParseException('code93', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } else { - $extc = strlen($extended); - for ($j = 0; $j < $extc; $j++) { - $v = $extended[$j]; - if ($v === '$') { - $indcheck[] = self::EXTENDED_1; - $data[] = $this->code[self::EXTENDED_1]; - } elseif ($v === '%') { - $indcheck[] = self::EXTENDED_2; - $data[] = $this->code[self::EXTENDED_2]; - } elseif ($v === '/') { - $indcheck[] = self::EXTENDED_3; - $data[] = $this->code[self::EXTENDED_3]; - } elseif ($v === '+') { - $indcheck[] = self::EXTENDED_4; - $data[] = $this->code[self::EXTENDED_4]; - } else { - $pos2 = array_search($v, $this->keys); - $indcheck[] = $pos2; - $data[] = $this->code[$pos2]; - } - } - } - } else { - $indcheck[] = $pos; - $data[] = $this->code[$pos]; - } - } - - $this->setData(array($indcheck, $data)); - $this->addDefaultLabel(); - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - // Starting * - $this->drawChar($im, $this->code[$this->starting], true); - $c = count($this->data); - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, $this->data[$i], true); - } - - // Checksum - $c = count($this->checksumValue); - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, $this->code[$this->checksumValue[$i]], true); - } - - // Ending * - $this->drawChar($im, $this->code[$this->ending], true); - - // Draw a Final Bar - $this->drawChar($im, '0', true); - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $startlength = 9; - $textlength = 9 * count($this->data); - $checksumlength = 2 * 9; - $endlength = 9 + 1; // + final bar - - $w += $startlength + $textlength + $checksumlength + $endlength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Validates the input. - */ - protected function validate() { - $c = count($this->data); - if ($c === 0) { - throw new BCGParseException('code93', 'No data has been entered.'); - } - - parent::validate(); - } - - /** - * Overloaded method to calculate checksum. - */ - protected function calculateChecksum() { - // Checksum - // First CheckSUM "C" - // The "C" checksum character is the modulo 47 remainder of the sum of the weighted - // value of the data characters. The weighting value starts at "1" for the right-most - // data character, 2 for the second to last, 3 for the third-to-last, and so on up to 20. - // After 20, the sequence wraps around back to 1. - - // Second CheckSUM "K" - // Same as CheckSUM "C" but we count the CheckSum "C" at the end - // After 15, the sequence wraps around back to 1. - $sequence_multiplier = array(20, 15); - $this->checksumValue = array(); - $indcheck = $this->indcheck; - for ($z = 0; $z < 2; $z++) { - $checksum = 0; - for ($i = count($indcheck), $j = 0; $i > 0; $i--, $j++) { - $multiplier = $i % $sequence_multiplier[$z]; - if ($multiplier === 0) { - $multiplier = $sequence_multiplier[$z]; - } - - $checksum += $indcheck[$j] * $multiplier; - } - - $this->checksumValue[$z] = $checksum % 47; - $indcheck[] = $this->checksumValue[$z]; - } - } - - /** - * Overloaded method to display the checksum. - */ - protected function processChecksum() { - if ($this->checksumValue === false) { // Calculate the checksum only once - $this->calculateChecksum(); - } - - if ($this->checksumValue !== false) { - $ret = ''; - $c = count($this->checksumValue); - for ($i = 0; $i < $c; $i++) { - $ret .= $this->keys[$this->checksumValue[$i]]; - } - - return $ret; - } - - return false; - } - - /** - * Saves data into the classes. - * - * This method will save data, calculate real column number - * (if -1 was selected), the real error level (if -1 was - * selected)... It will add Padding to the end and generate - * the error codes. - * - * @param array $data - */ - private function setData($data) { - $this->indcheck = $data[0]; - $this->data = $data[1]; - $this->calculateChecksum(); - } - - /** - * Returns the extended reprensentation of the character. - * - * @param string $char - * @return string - */ - private static function getExtendedVersion($char) { - $o = ord($char); - if ($o === 0) { - return '%U'; - } elseif ($o >= 1 && $o <= 26) { - return '$' . chr($o + 64); - } elseif (($o >= 33 && $o <= 44) || $o === 47 || $o === 48) { - return '/' . chr($o + 32); - } elseif ($o >= 97 && $o <= 122) { - return '+' . chr($o - 32); - } elseif ($o >= 27 && $o <= 31) { - return '%' . chr($o + 38); - } elseif ($o >= 59 && $o <= 63) { - return '%' . chr($o + 11); - } elseif ($o >= 91 && $o <= 95) { - return '%' . chr($o - 16); - } elseif ($o >= 123 && $o <= 127) { - return '%' . chr($o - 43); - } elseif ($o === 64) { - return '%V'; - } elseif ($o === 96) { - return '%W'; - } elseif ($o > 127) { - return false; - } else { - return $char; - } - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGean13.barcode.php b/niucloud/core/core/util/barcode/class/BCGean13.barcode.php deleted file mode 100644 index 5289183e..00000000 --- a/niucloud/core/core/util/barcode/class/BCGean13.barcode.php +++ /dev/null @@ -1,322 +0,0 @@ -keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); - - // Left-Hand Odd Parity starting with a space - // Left-Hand Even Parity is the inverse (0=0012) starting with a space - // Right-Hand is the same of Left-Hand starting with a bar - $this->code = array( - '2100', /* 0 */ - '1110', /* 1 */ - '1011', /* 2 */ - '0300', /* 3 */ - '0021', /* 4 */ - '0120', /* 5 */ - '0003', /* 6 */ - '0201', /* 7 */ - '0102', /* 8 */ - '2001' /* 9 */ - ); - - // Parity, 0=Odd, 1=Even for manufacturer code. Depending on 1st System Digit - $this->codeParity = array( - array(0, 0, 0, 0, 0), /* 0 */ - array(0, 1, 0, 1, 1), /* 1 */ - array(0, 1, 1, 0, 1), /* 2 */ - array(0, 1, 1, 1, 0), /* 3 */ - array(1, 0, 0, 1, 1), /* 4 */ - array(1, 1, 0, 0, 1), /* 5 */ - array(1, 1, 1, 0, 0), /* 6 */ - array(1, 0, 1, 0, 1), /* 7 */ - array(1, 0, 1, 1, 0), /* 8 */ - array(1, 1, 0, 1, 0) /* 9 */ - ); - - $this->alignDefaultLabel(true); - } - - public function alignDefaultLabel($align) { - $this->alignLabel = (bool)$align; - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - $this->drawBars($im); - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - - if ($this->isDefaultEanLabelEnabled()) { - $dimension = $this->labelCenter1->getDimension(); - $this->drawExtendedBars($im, $dimension[1] - 2); - } - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $startlength = 3; - $centerlength = 5; - $textlength = 12 * 7; - $endlength = 3; - - $w += $startlength + $centerlength + $textlength + $endlength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Adds the default label. - */ - protected function addDefaultLabel() { - if ($this->isDefaultEanLabelEnabled()) { - $this->processChecksum(); - $label = $this->getLabel(); - $font = $this->font; - - $this->labelLeft = new BCGLabel(substr($label, 0, 1), $font, BCGLabel::POSITION_LEFT, BCGLabel::ALIGN_BOTTOM); - $this->labelLeft->setSpacing(4 * $this->scale); - - $this->labelCenter1 = new BCGLabel(substr($label, 1, 6), $font, BCGLabel::POSITION_BOTTOM, BCGLabel::ALIGN_LEFT); - $labelCenter1Dimension = $this->labelCenter1->getDimension(); - $this->labelCenter1->setOffset(($this->scale * 44 - $labelCenter1Dimension[0]) / 2 + $this->scale * 2); - - $this->labelCenter2 = new BCGLabel(substr($label, 7, 5) . $this->keys[$this->checksumValue], $font, BCGLabel::POSITION_BOTTOM, BCGLabel::ALIGN_LEFT); - $this->labelCenter2->setOffset(($this->scale * 44 - $labelCenter1Dimension[0]) / 2 + $this->scale * 48); - - if ($this->alignLabel) { - $labelDimension = $this->labelCenter1->getDimension(); - $this->labelLeft->setOffset($labelDimension[1]); - } else { - $labelDimension = $this->labelLeft->getDimension(); - $this->labelLeft->setOffset($labelDimension[1] / 2); - } - - $this->addLabel($this->labelLeft); - $this->addLabel($this->labelCenter1); - $this->addLabel($this->labelCenter2); - } - } - - /** - * Checks if the default ean label is enabled. - * - * @return bool - */ - protected function isDefaultEanLabelEnabled() { - $label = $this->getLabel(); - $font = $this->font; - return $label !== null && $label !== '' && $font !== null && $this->defaultLabel !== null; - } - - /** - * Validates the input. - */ - protected function validate() { - $c = strlen($this->text); - if ($c === 0) { - throw new BCGParseException('ean13', 'No data has been entered.'); - } - - $this->checkCharsAllowed(); - $this->checkCorrectLength(); - - parent::validate(); - } - - /** - * Check chars allowed. - */ - protected function checkCharsAllowed() { - // Checking if all chars are allowed - $c = strlen($this->text); - for ($i = 0; $i < $c; $i++) { - if (array_search($this->text[$i], $this->keys) === false) { - throw new BCGParseException('ean13', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } - } - } - - /** - * Check correct length. - */ - protected function checkCorrectLength() { - // If we have 13 chars, just flush the last one without throwing anything - $c = strlen($this->text); - if ($c === 13) { - $this->text = substr($this->text, 0, 12); - } elseif ($c !== 12) { - throw new BCGParseException('ean13', 'Must contain 12 digits, the 13th digit is automatically added.'); - } - } - - /** - * Overloaded method to calculate checksum. - */ - protected function calculateChecksum() { - // Calculating Checksum - // Consider the right-most digit of the message to be in an "odd" position, - // and assign odd/even to each character moving from right to left - // Odd Position = 3, Even Position = 1 - // Multiply it by the number - // Add all of that and do 10-(?mod10) - $odd = true; - $this->checksumValue = 0; - $c = strlen($this->text); - for ($i = $c; $i > 0; $i--) { - if ($odd === true) { - $multiplier = 3; - $odd = false; - } else { - $multiplier = 1; - $odd = true; - } - - if (!isset($this->keys[$this->text[$i - 1]])) { - return; - } - - $this->checksumValue += $this->keys[$this->text[$i - 1]] * $multiplier; - } - - $this->checksumValue = (10 - $this->checksumValue % 10) % 10; - } - - /** - * Overloaded method to display the checksum. - */ - protected function processChecksum() { - if ($this->checksumValue === false) { // Calculate the checksum only once - $this->calculateChecksum(); - } - - if ($this->checksumValue !== false) { - return $this->keys[$this->checksumValue]; - } - - return false; - } - - /** - * Draws the bars - * - * @param resource $im - */ - protected function drawBars($im) { - // Checksum - $this->calculateChecksum(); - $temp_text = $this->text . $this->keys[$this->checksumValue]; - - // Starting Code - $this->drawChar($im, '000', true); - - // Draw Second Code - $this->drawChar($im, $this->findCode($temp_text[1]), false); - - // Draw Manufacturer Code - for ($i = 0; $i < 5; $i++) { - $this->drawChar($im, self::inverse($this->findCode($temp_text[$i + 2]), $this->codeParity[(int)$temp_text[0]][$i]), false); - } - - // Draw Center Guard Bar - $this->drawChar($im, '00000', false); - - // Draw Product Code - for ($i = 7; $i < 13; $i++) { - $this->drawChar($im, $this->findCode($temp_text[$i]), true); - } - - // Draw Right Guard Bar - $this->drawChar($im, '000', true); - } - - /** - * Draws the extended bars on the image. - * - * @param resource $im - * @param int $plus - */ - protected function drawExtendedBars($im, $plus) { - $rememberX = $this->positionX; - $rememberH = $this->thickness; - - // We increase the bars - $this->thickness = $this->thickness + intval($plus / $this->scale); - $this->positionX = 0; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - $this->positionX += 2; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - - // Center Guard Bar - $this->positionX += 44; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - $this->positionX += 2; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - - // Last Bars - $this->positionX += 44; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - $this->positionX += 2; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - - $this->positionX = $rememberX; - $this->thickness = $rememberH; - } - - /** - * Inverses the string when the $inverse parameter is equal to 1. - * - * @param string $text - * @param int $inverse - * @return string - */ - private static function inverse($text, $inverse = 1) { - if ($inverse === 1) { - $text = strrev($text); - } - - return $text; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGean8.barcode.php b/niucloud/core/core/util/barcode/class/BCGean8.barcode.php deleted file mode 100644 index b89eb77b..00000000 --- a/niucloud/core/core/util/barcode/class/BCGean8.barcode.php +++ /dev/null @@ -1,244 +0,0 @@ -keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); - - // Left-Hand Odd Parity starting with a space - // Right-Hand is the same of Left-Hand starting with a bar - $this->code = array( - '2100', /* 0 */ - '1110', /* 1 */ - '1011', /* 2 */ - '0300', /* 3 */ - '0021', /* 4 */ - '0120', /* 5 */ - '0003', /* 6 */ - '0201', /* 7 */ - '0102', /* 8 */ - '2001' /* 9 */ - ); - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - // Checksum - $this->calculateChecksum(); - $temp_text = $this->text . $this->keys[$this->checksumValue]; - - // Starting Code - $this->drawChar($im, '000', true); - - // Draw First 4 Chars (Left-Hand) - for ($i = 0; $i < 4; $i++) { - $this->drawChar($im, $this->findCode($temp_text[$i]), false); - } - - // Draw Center Guard Bar - $this->drawChar($im, '00000', false); - - // Draw Last 4 Chars (Right-Hand) - for ($i = 4; $i < 8; $i++) { - $this->drawChar($im, $this->findCode($temp_text[$i]), true); - } - - // Draw Right Guard Bar - $this->drawChar($im, '000', true); - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - - if ($this->isDefaultEanLabelEnabled()) { - $dimension = $this->labelRight->getDimension(); - $this->drawExtendedBars($im, $dimension[1] - 2); - } - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $startlength = 3; - $centerlength = 5; - $textlength = 8 * 7; - $endlength = 3; - - $w += $startlength + $centerlength + $textlength + $endlength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Adds the default label. - */ - protected function addDefaultLabel() { - if ($this->isDefaultEanLabelEnabled()) { - $this->processChecksum(); - $label = $this->getLabel(); - $font = $this->font; - - $this->labelLeft = new BCGLabel(substr($label, 0, 4), $font, BCGLabel::POSITION_BOTTOM, BCGLabel::ALIGN_LEFT); - $labelLeftDimension = $this->labelLeft->getDimension(); - $this->labelLeft->setOffset(($this->scale * 30 - $labelLeftDimension[0]) / 2 + $this->scale * 2); - - $this->labelRight = new BCGLabel(substr($label, 4, 3) . $this->keys[$this->checksumValue], $font, BCGLabel::POSITION_BOTTOM, BCGLabel::ALIGN_LEFT); - $labelRightDimension = $this->labelRight->getDimension(); - $this->labelRight->setOffset(($this->scale * 30 - $labelRightDimension[0]) / 2 + $this->scale * 34); - - $this->addLabel($this->labelLeft); - $this->addLabel($this->labelRight); - } - } - - /** - * Checks if the default ean label is enabled. - * - * @return bool - */ - protected function isDefaultEanLabelEnabled() { - $label = $this->getLabel(); - $font = $this->font; - return $label !== null && $label !== '' && $font !== null && $this->defaultLabel !== null; - } - - /** - * Validates the input. - */ - protected function validate() { - $c = strlen($this->text); - if ($c === 0) { - throw new BCGParseException('ean8', 'No data has been entered.'); - } - - // Checking if all chars are allowed - for ($i = 0; $i < $c; $i++) { - if (array_search($this->text[$i], $this->keys) === false) { - throw new BCGParseException('ean8', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } - } - - // If we have 8 chars just flush the last one - if ($c === 8) { - $this->text = substr($this->text, 0, 7); - } elseif ($c !== 7) { - throw new BCGParseException('ean8', 'Must contain 7 digits, the 8th digit is automatically added.'); - } - - parent::validate(); - } - - /** - * Overloaded method to calculate checksum. - */ - protected function calculateChecksum() { - // Calculating Checksum - // Consider the right-most digit of the message to be in an "odd" position, - // and assign odd/even to each character moving from right to left - // Odd Position = 3, Even Position = 1 - // Multiply it by the number - // Add all of that and do 10-(?mod10) - $odd = true; - $this->checksumValue = 0; - $c = strlen($this->text); - for ($i = $c; $i > 0; $i--) { - if ($odd === true) { - $multiplier = 3; - $odd = false; - } else { - $multiplier = 1; - $odd = true; - } - - if (!isset($this->keys[$this->text[$i - 1]])) { - return; - } - - $this->checksumValue += $this->keys[$this->text[$i - 1]] * $multiplier; - } - - $this->checksumValue = (10 - $this->checksumValue % 10) % 10; - } - - /** - * Overloaded method to display the checksum. - */ - protected function processChecksum() { - if ($this->checksumValue === false) { // Calculate the checksum only once - $this->calculateChecksum(); - } - - if ($this->checksumValue !== false) { - return $this->keys[$this->checksumValue]; - } - - return false; - } - - /** - * Draws the extended bars on the image. - * - * @param resource $im - * @param int $plus - */ - private function drawExtendedBars($im, $plus) { - $rememberX = $this->positionX; - $rememberH = $this->thickness; - - // We increase the bars - $this->thickness = $this->thickness + intval($plus / $this->scale); - $this->positionX = 0; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - $this->positionX += 2; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - - // Center Guard Bar - $this->positionX += 30; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - $this->positionX += 2; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - - // Last Bars - $this->positionX += 30; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - $this->positionX += 2; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - - $this->positionX = $rememberX; - $this->thickness = $rememberH; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGgs1128.barcode.php b/niucloud/core/core/util/barcode/class/BCGgs1128.barcode.php deleted file mode 100644 index 0393f245..00000000 --- a/niucloud/core/core/util/barcode/class/BCGgs1128.barcode.php +++ /dev/null @@ -1,679 +0,0 @@ -identifiersAi = array( - '00' => array(self::NUMERIC, 18, 18, true), - '01' => array(self::NUMERIC, 14, 14, true), - '02' => array(self::NUMERIC, 14, 14, true), - '10' => array(self::ALPHA_NUMERIC, 1, 20, false), - '11' => array(self::DATE_YYMMDD, 6, 6, false), - '12' => array(self::DATE_YYMMDD, 6, 6, false), - '13' => array(self::DATE_YYMMDD, 6, 6, false), - '15' => array(self::DATE_YYMMDD, 6, 6, false), - '17' => array(self::DATE_YYMMDD, 6, 6, false), - '20' => array(self::NUMERIC, 2, 2, false), - '21' => array(self::ALPHA_NUMERIC, 1, 20, false), - '240' => array(self::ALPHA_NUMERIC, 1, 30, false), - '241' => array(self::ALPHA_NUMERIC, 1, 30, false), - '250' => array(self::ALPHA_NUMERIC, 1, 30, false), - '251' => array(self::ALPHA_NUMERIC, 1, 30, false), - '253' => array(self::NUMERIC, 14, 30, false), - '30' => array(self::NUMERIC, 1, 8, false), - '310y' => array(self::NUMERIC, 6, 6, false), - '311y' => array(self::NUMERIC, 6, 6, false), - '312y' => array(self::NUMERIC, 6, 6, false), - '313y' => array(self::NUMERIC, 6, 6, false), - '314y' => array(self::NUMERIC, 6, 6, false), - '315y' => array(self::NUMERIC, 6, 6, false), - '316y' => array(self::NUMERIC, 6, 6, false), - '320y' => array(self::NUMERIC, 6, 6, false), - '321y' => array(self::NUMERIC, 6, 6, false), - '322y' => array(self::NUMERIC, 6, 6, false), - '323y' => array(self::NUMERIC, 6, 6, false), - '324y' => array(self::NUMERIC, 6, 6, false), - '325y' => array(self::NUMERIC, 6, 6, false), - '326y' => array(self::NUMERIC, 6, 6, false), - '327y' => array(self::NUMERIC, 6, 6, false), - '328y' => array(self::NUMERIC, 6, 6, false), - '329y' => array(self::NUMERIC, 6, 6, false), - '330y' => array(self::NUMERIC, 6, 6, false), - '331y' => array(self::NUMERIC, 6, 6, false), - '332y' => array(self::NUMERIC, 6, 6, false), - '333y' => array(self::NUMERIC, 6, 6, false), - '334y' => array(self::NUMERIC, 6, 6, false), - '335y' => array(self::NUMERIC, 6, 6, false), - '336y' => array(self::NUMERIC, 6, 6, false), - '337y' => array(self::NUMERIC, 6, 6, false), - '340y' => array(self::NUMERIC, 6, 6, false), - '341y' => array(self::NUMERIC, 6, 6, false), - '342y' => array(self::NUMERIC, 6, 6, false), - '343y' => array(self::NUMERIC, 6, 6, false), - '344y' => array(self::NUMERIC, 6, 6, false), - '345y' => array(self::NUMERIC, 6, 6, false), - '346y' => array(self::NUMERIC, 6, 6, false), - '347y' => array(self::NUMERIC, 6, 6, false), - '348y' => array(self::NUMERIC, 6, 6, false), - '349y' => array(self::NUMERIC, 6, 6, false), - '350y' => array(self::NUMERIC, 6, 6, false), - '351y' => array(self::NUMERIC, 6, 6, false), - '352y' => array(self::NUMERIC, 6, 6, false), - '353y' => array(self::NUMERIC, 6, 6, false), - '354y' => array(self::NUMERIC, 6, 6, false), - '355y' => array(self::NUMERIC, 6, 6, false), - '356y' => array(self::NUMERIC, 6, 6, false), - '357y' => array(self::NUMERIC, 6, 6, false), - '360y' => array(self::NUMERIC, 6, 6, false), - '361y' => array(self::NUMERIC, 6, 6, false), - '362y' => array(self::NUMERIC, 6, 6, false), - '363y' => array(self::NUMERIC, 6, 6, false), - '364y' => array(self::NUMERIC, 6, 6, false), - '365y' => array(self::NUMERIC, 6, 6, false), - '366y' => array(self::NUMERIC, 6, 6, false), - '367y' => array(self::NUMERIC, 6, 6, false), - '368y' => array(self::NUMERIC, 6, 6, false), - '369y' => array(self::NUMERIC, 6, 6, false), - '37' => array(self::NUMERIC, 1, 8, false), - '390y' => array(self::NUMERIC, 1, 15, false), - '391y' => array(self::NUMERIC, 4, 18, false), - '392y' => array(self::NUMERIC, 1, 15, false), - '393y' => array(self::NUMERIC, 4, 18, false), - '400' => array(self::ALPHA_NUMERIC, 1, 30, false), - '401' => array(self::ALPHA_NUMERIC, 1, 30, false), - '402' => array(self::NUMERIC, 17, 17, false), - '403' => array(self::ALPHA_NUMERIC, 1, 30, false), - '410' => array(self::NUMERIC, 13, 13, true), - '411' => array(self::NUMERIC, 13, 13, true), - '412' => array(self::NUMERIC, 13, 13, true), - '413' => array(self::NUMERIC, 13, 13, true), - '414' => array(self::NUMERIC, 13, 13, true), - '415' => array(self::NUMERIC, 13, 13, true), - '420' => array(self::ALPHA_NUMERIC, 1, 20, false), - '421' => array(self::ALPHA_NUMERIC, 4, 12, false), - '422' => array(self::NUMERIC, 3, 3, false), - '8001' => array(self::NUMERIC, 14, 14, false), - '8002' => array(self::ALPHA_NUMERIC, 1, 20, false), - '8003' => array(self::ALPHA_NUMERIC, 15, 30, false), - '8004' => array(self::ALPHA_NUMERIC, 1, 30, false), - '8005' => array(self::NUMERIC, 6, 6, false), - '8006' => array(self::NUMERIC, 18, 18, false), - '8007' => array(self::ALPHA_NUMERIC, 1, 30, false), - '8018' => array(self::NUMERIC, 18, 18, false), - '8020' => array(self::ALPHA_NUMERIC, 1, 25, false), - '8100' => array(self::NUMERIC, 6, 6, false), - '8101' => array(self::NUMERIC, 10, 10, false), - '8102' => array(self::NUMERIC, 2, 2, false), - '90' => array(self::ALPHA_NUMERIC, 1, 30, false), - '91' => array(self::ALPHA_NUMERIC, 1, 30, false), - '92' => array(self::ALPHA_NUMERIC, 1, 30, false), - '93' => array(self::ALPHA_NUMERIC, 1, 30, false), - '94' => array(self::ALPHA_NUMERIC, 1, 30, false), - '95' => array(self::ALPHA_NUMERIC, 1, 30, false), - '96' => array(self::ALPHA_NUMERIC, 1, 30, false), - '97' => array(self::ALPHA_NUMERIC, 1, 30, false), - '98' => array(self::ALPHA_NUMERIC, 1, 30, false), - '99' => array(self::ALPHA_NUMERIC, 1, 30, false) - ); - - $this->setStrictMode(true); - $this->setTilde(true); - $this->setAllowsUnknownIdentifier(false); - $this->setNoLengthLimit(false); - } - - /** - * Gets the content checksum for an identifier. - * Do not pass the identifier code. - * - * @param string $content - * @return int - */ - public static function getAiContentChecksum($content) { - return self::calculateChecksumMod10($content); - } - - /** - * Enables or disables the strict mode. - * - * @param bool $strictMode - */ - public function setStrictMode($strictMode) { - $this->strictMode = $strictMode; - } - - /** - * Gets if the strict mode is activated. - * - * @return bool - */ - public function getStrictMode() { - return $this->strictMode; - } - - /** - * Allows unknown identifiers. - * - * @param bool $allow - */ - public function setAllowsUnknownIdentifier($allow) { - $this->allowsUnknownIdentifier = (bool)$allow; - } - - /** - * Gets if unkmown identifiers are allowed. - * - * @return bool - */ - public function getAllowsUnknownIdentifier() { - return $this->allowsUnknownIdentifier; - } - - /** - * Removes the limit of 48 characters. - * - * @param bool $noLengthLimit - */ - public function setNoLengthLimit($noLengthLimit) { - $this->noLengthLimit = (bool)$noLengthLimit; - } - - /** - * Gets if the limit of 48 characters is removed. - * - * @return bool - */ - public function getNoLengthLimit() { - return $this->noLengthLimit; - } - - /** - * Parses Text. - * - * @param string $text - */ - public function parse($text) { - parent::parse($this->parseGs1128($text)); - } - - /** - * Formats data for gs1-128. - * - * @return string - */ - private function formatGs1128() { - $formatedText = '~F1'; - $formatedLabel = ''; - $c = count($this->identifiersId); - - for ($i = 0; $i < $c; $i++) { - if ($i > 0) { - $formatedLabel .= ' '; - } - - if ($this->identifiersId[$i] !== null) { - $formatedLabel .= '(' . $this->identifiersId[$i] . ')'; - } - - $formatedText .= $this->identifiersId[$i]; - - $formatedLabel .= $this->identifiersContent[$i]; - $formatedText .= $this->identifiersContent[$i]; - - if (isset($this->identifiersAi[$this->identifiersId[$i]])) { - $ai_data = $this->identifiersAi[$this->identifiersId[$i]]; - } elseif (isset($this->identifiersId[$i][3])) { - $identifierWithVar = substr($this->identifiersId[$i], 0, -1) . 'y'; - $ai_data = isset($this->identifiersAi[$identifierWithVar]) ? $this->identifiersAi[$identifierWithVar] : null; - } else { - $ai_data = null; - } - - /* We'll check if we need to add a ~F1 () char */ - /* If we use the legacy mode, we always add a ~F1 () char between AIs */ - if ($ai_data !== null) { - if ((strlen($this->identifiersContent[$i]) < $ai_data[self::MAXLENGTH] && ($i + 1) !== $c) || (!$this->strictMode && ($i + 1) !== $c)) { - $formatedText .= '~F1'; - } - } elseif ($this->allowsUnknownIdentifier && $this->identifiersId[$i] === null && ($i + 1) !== $c) { - /* If this id is unknown, we add a ~F1 () char */ - $formatedText .= '~F1'; - } - } - - if ($this->noLengthLimit === false && (strlen(str_replace('~F1', chr(29), $formatedText)) - 1) > self::MAX_GS1128_CHARS) { - throw new BCGParseException('gs1128', 'The barcode can\'t contain more than ' . self::MAX_GS1128_CHARS . ' characters.'); - } - - $this->label = $formatedLabel; - return $formatedText; - } - - /** - * Parses the text to gs1-128. - * - * @param mixed $text - * @return mixed - */ - private function parseGs1128($text) { - /* We format correctly what the user gives */ - if (is_array($text)) { - $formatArray = array(); - foreach ($text as $content) { - if (is_array($content)) { /* double array */ - if (count($content) === 2) { - if (is_array($content[self::ID]) || is_array($content[self::CONTENT])) { - throw new BCGParseException('gs1128', 'Double arrays can\'t contain arrays.'); - } else { - $formatArray[] = '(' . $content[self::ID] . ')' . $content[self::CONTENT]; - } - } else { - throw new BCGParseException('gs1128', 'Double arrays must contain 2 values.'); - } - } else { /* simple array */ - $formatArray[] = $content; - } - } - - unset($text); - $text = $formatArray; - } else { /* string */ - $text = array($text); - } - - $textCount = count($text); - for ($cmpt = 0; $cmpt < $textCount; $cmpt++) { - /* We parse the content of the array */ - if (!$this->parseContent($text[$cmpt])) { - return; - } - } - - return $this->formatGs1128(); - } - - /** - * Splits the id and the content for each application identifiers (AIs). - * - * @param string $text - * @param int $cmpt - * @return bool - */ - private function parseContent($text) { - /* $yAlreadySet has 3 states: */ - /* null: There is no variable in the ID; true: the variable is already set; false: the variable is not set yet; */ - $content = null; - $yAlreadySet = null; - $realNameId = null; - $separatorsFound = 0; - $checksumAdded = 0; - $decimalPointRemoved = 0; - $toParse = str_replace('~F1', chr(29), $text); - $nbCharToParse = strlen($toParse); - $nbCharId = 0; - $isFormated = $toParse[0] === '(' ? true : false; - $maxCharId = $isFormated ? self::MAX_ID_FORMATED : self::MAX_ID_NOT_FORMATED; - $id = strtolower(substr($toParse, 0, min($maxCharId, $nbCharToParse))); - $id = $isFormated ? $this->findIdFormated($id, $yAlreadySet, $realNameId) : $this->findIdNotFormated($id, $yAlreadySet, $realNameId); - - if ($id === false) { - if ($this->allowsUnknownIdentifier === false) { - return false; - } - - $id = null; - $nbCharId = 0; - $content = $toParse; - } else { - $nbCharId = strlen($id) + ($isFormated ? 2 : 0); - $n = min($this->identifiersAi[$realNameId][self::MAXLENGTH], $nbCharToParse); - $content = substr($toParse, $nbCharId, $n); - } - - if ($id !== null) { - /* If we have an AI with an "y" var, we check if there is a decimal point in the next *MAXLENGTH* characters */ - /* if there is one, we take an extra character */ - if ($yAlreadySet !== null) { - if (strpos($content, '.') !== false || strpos($content, ',') !== false) { - $n++; - if ($n <= $nbCharToParse) { - /* We take an extra char */ - $content = substr($toParse, $nbCharId, $n); - } - } - } - } - - /* We check for separator */ - $separator = strpos($content, chr(29)); - if ($separator !== false) { - $content = substr($content, 0, $separator); - $separatorsFound++; - } - - if ($id !== null) { - /* We check the conformity */ - if (!$this->checkConformity($content, $id, $realNameId)) { - return false; - } - - /* We check the checksum */ - if (!$this->checkChecksum($content, $id, $realNameId, $checksumAdded)) { - return false; - } - - /* We check the vars */ - if (!$this->checkVars($content, $id, $yAlreadySet, $decimalPointRemoved)) { - return false; - } - } - - $this->identifiersId[] = $id; - $this->identifiersContent[] = $content; - - $nbCharLastContent = (((strlen($content) + $nbCharId) - $checksumAdded) + $decimalPointRemoved) + $separatorsFound; - if ($nbCharToParse - $nbCharLastContent > 0) { - /* If there is more than one content in this array, we parse again */ - $otherContent = substr($toParse, $nbCharLastContent, $nbCharToParse); - $nbCharOtherContent = strlen($otherContent); - - if ($otherContent[0] === chr(29)) { - $otherContent = substr($otherContent, 1); - $nbCharOtherContent--; - } - - if ($nbCharOtherContent > 0) { - $text = $otherContent; - return $this->parseContent($text); - } - } - - return true; - } - - /** - * Checks if an id exists. - * - * @param string $id - * @param bool $yAlreadySet - * @param string $realNameId - * @return bool - */ - private function idExists($id, &$yAlreadySet, &$realNameId) { - $yFound = isset($id[3]) && $id[3] === 'y'; - $idVarAdded = substr($id, 0, -1) . 'y'; - - if (isset($this->identifiersAi[$id])) { - if ($yFound) { - $yAlreadySet = false; - } - - $realNameId = $id; - return true; - } elseif (!$yFound && isset($this->identifiersAi[$idVarAdded])) { - /* if the id don't exist, we try to find this id with "y" at the last char */ - $yAlreadySet = true; - $realNameId = $idVarAdded; - return true; - } - - return false; - } - - /** - * Finds ID with formated content. - * - * @param string $id - * @param bool $yAlreadySet - * @param string $realNameId - * @return mixed - */ - private function findIdFormated($id, &$yAlreadySet, &$realNameId) { - $pos = strpos($id, ')'); - if ($pos === false) { - throw new BCGParseException('gs1128', 'Identifiers must have no more than 4 characters.'); - } else { - if ($pos < 3) { - throw new BCGParseException('gs1128', 'Identifiers must have at least 2 characters.'); - } - - $id = substr($id, 1, $pos - 1); - if ($this->idExists($id, $yAlreadySet, $realNameId)) { - return $id; - } - - if ($this->allowsUnknownIdentifier === false) { - throw new BCGParseException('gs1128', 'The identifier ' . $id . ' doesn\'t exist.'); - } - - return false; - } - } - - /** - * Finds ID with non-formated content. - * - * @param string $id - * @param bool $yAlreadySet - * @param string $realNameId - * @return mixed - */ - private function findIdNotFormated($id, &$yAlreadySet, &$realNameId) { - $tofind = $id; - - while (strlen($tofind) >= 2) { - if ($this->idExists($tofind, $yAlreadySet, $realNameId)) { - return $tofind; - } else { - $tofind = substr($tofind, 0, -1); - } - } - - if ($this->allowsUnknownIdentifier === false) { - throw new BCGParseException('gs1128', 'Error in formatting, can\'t find an identifier.'); - } - - return false; - } - - /** - * Checks confirmity of the content. - * - * @param string $content - * @param string $id - * @param string $realNameId - * @return bool - */ - private function checkConformity(&$content, $id, $realNameId) { - switch ($this->identifiersAi[$realNameId][self::KIND_OF_DATA]) { - case self::NUMERIC: - $content = str_replace(',', '.', $content); - if (!preg_match("/^[0-9.]+$/", $content)) { - throw new BCGParseException('gs1128', 'The value of "' . $id . '" must be numerical.'); - } - - break; - case self::DATE_YYMMDD: - $valid_date = true; - if (preg_match("/^[0-9]{6}$/", $content)) { - $year = substr($content, 0, 2); - $month = substr($content, 2, 2); - $day = substr($content, 4, 2); - - /* day can be 00 if we only need month and year */ - if (intval($month) < 1 || intval($month) > 12 || intval($day) < 0 || intval($day) > 31) { - $valid_date = false; - } - } else { - $valid_date = false; - } - - if (!$valid_date) { - throw new BCGParseException('gs1128', 'The value of "' . $id . '" must be in YYMMDD format.'); - } - - break; - } - - // We check the length of the content - $nbCharContent = strlen($content); - $checksumChar = 0; - $minlengthContent = $this->identifiersAi[$realNameId][self::MINLENGTH]; - $maxlengthContent = $this->identifiersAi[$realNameId][self::MAXLENGTH]; - - if ($this->identifiersAi[$realNameId][self::CHECKSUM]) { - $checksumChar++; - } - - if ($nbCharContent < ($minlengthContent - $checksumChar)) { - if ($minlengthContent === $maxlengthContent) { - throw new BCGParseException('gs1128', 'The value of "' . $id . '" must contain ' . $minlengthContent . ' character(s).'); - } else { - throw new BCGParseException('gs1128', 'The value of "' . $id . '" must contain between ' . $minlengthContent . ' and ' . $maxlengthContent . ' character(s).'); - } - } - - return true; - } - - /** - * Verifies the checksum. - * - * @param string $content - * @param string $id - * @param int $realNameId - * @param int $checksumAdded - * @return bool - */ - private function checkChecksum(&$content, $id, $realNameId, &$checksumAdded) { - if ($this->identifiersAi[$realNameId][self::CHECKSUM]) { - $nbCharContent = strlen($content); - $minlengthContent = $this->identifiersAi[$realNameId][self::MINLENGTH]; - if ($nbCharContent === ($minlengthContent - 1)) { - /* we need to calculate the checksum */ - $content .= self::getAiContentChecksum($content); - $checksumAdded++; - } elseif ($nbCharContent === $minlengthContent) { - /* we need to check the checksum */ - $checksum = self::getAiContentChecksum(substr($content, 0, -1)); - if (intval($content[$nbCharContent - 1]) !== $checksum) { - throw new BCGParseException('gs1128', 'The checksum of "(' . $id . ') ' . $content . '" must be: ' . $checksum); - } - } - } - - return true; - } - - /** - * Checks vars "y". - * - * @param string $content - * @param string $id - * @param bool $yAlreadySet - * @param int $decimalPointRemoved - * @return bool - */ - private function checkVars(&$content, &$id, $yAlreadySet, &$decimalPointRemoved) { - $nbCharContent = strlen($content); - /* We check for "y" var in AI */ - if ($yAlreadySet) { - /* We'll check if we have a decimal point */ - if (strpos($content, '.') !== false) { - throw new BCGParseException('gs1128', 'If you do not use any "y" variable, you have to insert a whole number.'); - } - } elseif ($yAlreadySet !== null) { - /* We need to replace the "y" var with the position of the decimal point */ - $pos = strpos($content, '.'); - if ($pos === false) { - $pos = $nbCharContent - 1; - } - - $id = str_replace('y', $nbCharContent - ($pos + 1), strtolower($id)); - $content = str_replace('.', '', $content); - $decimalPointRemoved++; - } - - return true; - } - - /** - * Checksum Mod10. - * - * @param int $content - * @return int - */ - private static function calculateChecksumMod10($content) { - // Calculating Checksum - // Consider the right-most digit of the message to be in an "odd" position, - // and assign odd/even to each character moving from right to left - // Odd Position = 3, Even Position = 1 - // Multiply it by the number - // Add all of that and do 10-(?mod10) - $odd = true; - $checksumValue = 0; - $c = strlen($content); - - for ($i = $c; $i > 0; $i--) { - if ($odd === true) { - $multiplier = 3; - $odd = false; - } else { - $multiplier = 1; - $odd = true; - } - - $checksumValue += ($content[$i - 1] * $multiplier); - } - - return (10 - $checksumValue % 10) % 10; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGi25.barcode.php b/niucloud/core/core/util/barcode/class/BCGi25.barcode.php deleted file mode 100644 index d4ee00c6..00000000 --- a/niucloud/core/core/util/barcode/class/BCGi25.barcode.php +++ /dev/null @@ -1,203 +0,0 @@ -keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); - $this->code = array( - '00110', /* 0 */ - '10001', /* 1 */ - '01001', /* 2 */ - '11000', /* 3 */ - '00101', /* 4 */ - '10100', /* 5 */ - '01100', /* 6 */ - '00011', /* 7 */ - '10010', /* 8 */ - '01010' /* 9 */ - ); - - $this->setChecksum(false); - $this->setRatio(2); - } - - /** - * Sets the checksum. - * - * @param bool $checksum - */ - public function setChecksum($checksum) { - $this->checksum = (bool)$checksum; - } - - /** - * Sets the ratio of the black bar compared to the white bars. - * - * @param int $ratio - */ - public function setRatio($ratio) { - $this->ratio = $ratio; - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - $temp_text = $this->text; - - // Checksum - if ($this->checksum === true) { - $this->calculateChecksum(); - $temp_text .= $this->keys[$this->checksumValue]; - } - - // Starting Code - $this->drawChar($im, '0000', true); - - // Chars - $c = strlen($temp_text); - for ($i = 0; $i < $c; $i += 2) { - $temp_bar = ''; - $c2 = strlen($this->findCode($temp_text[$i])); - for ($j = 0; $j < $c2; $j++) { - $temp_bar .= substr($this->findCode($temp_text[$i]), $j, 1); - $temp_bar .= substr($this->findCode($temp_text[$i + 1]), $j, 1); - } - - $this->drawChar($im, $this->changeBars($temp_bar), true); - } - - // Ending Code - $this->drawChar($im, $this->changeBars('100'), true); - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $textlength = (3 + ($this->ratio + 1) * 2) * strlen($this->text); - $startlength = 4; - $checksumlength = 0; - if ($this->checksum === true) { - $checksumlength = (3 + ($this->ratio + 1) * 2); - } - - $endlength = 2 + ($this->ratio + 1); - - $w += $startlength + $textlength + $checksumlength + $endlength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Validates the input. - */ - protected function validate() { - $c = strlen($this->text); - if ($c === 0) { - throw new BCGParseException('i25', 'No data has been entered.'); - } - - // Checking if all chars are allowed - for ($i = 0; $i < $c; $i++) { - if (array_search($this->text[$i], $this->keys) === false) { - throw new BCGParseException('i25', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } - } - - // Must be even - if ($c % 2 !== 0 && $this->checksum === false) { - throw new BCGParseException('i25', 'i25 must contain an even amount of digits if checksum is false.'); - } elseif ($c % 2 === 0 && $this->checksum === true) { - throw new BCGParseException('i25', 'i25 must contain an odd amount of digits if checksum is true.'); - } - - parent::validate(); - } - - /** - * Overloaded method to calculate checksum. - */ - protected function calculateChecksum() { - // Calculating Checksum - // Consider the right-most digit of the message to be in an "even" position, - // and assign odd/even to each character moving from right to left - // Even Position = 3, Odd Position = 1 - // Multiply it by the number - // Add all of that and do 10-(?mod10) - $even = true; - $this->checksumValue = 0; - $c = strlen($this->text); - for ($i = $c; $i > 0; $i--) { - if ($even === true) { - $multiplier = 3; - $even = false; - } else { - $multiplier = 1; - $even = true; - } - - $this->checksumValue += $this->keys[$this->text[$i - 1]] * $multiplier; - } - - $this->checksumValue = (10 - $this->checksumValue % 10) % 10; - } - - /** - * Overloaded method to display the checksum. - */ - protected function processChecksum() { - if ($this->checksumValue === false) { // Calculate the checksum only once - $this->calculateChecksum(); - } - - if ($this->checksumValue !== false) { - return $this->keys[$this->checksumValue]; - } - - return false; - } - - /** - * Changes the size of the bars based on the ratio - * - * @param string $in - * @return string - */ - private function changeBars($in) { - if ($this->ratio > 1) { - $c = strlen($in); - for ($i = 0; $i < $c; $i++) { - $in[$i] = $in[$i] === '1' ? $this->ratio : $in[$i]; - } - } - - return $in; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGintelligentmail.barcode.php b/niucloud/core/core/util/barcode/class/BCGintelligentmail.barcode.php deleted file mode 100644 index cb2a5f3c..00000000 --- a/niucloud/core/core/util/barcode/class/BCGintelligentmail.barcode.php +++ /dev/null @@ -1,649 +0,0 @@ -setQuietZone(true); - $this->setThickness(9); - } - - /** - * Gets the Quiet zone. - * - * @return bool - */ - public function getQuietZone() { - return $this->quietZone; - } - - /** - * Sets the Quiet zone. - * - * @param bool $quietZone - */ - public function setQuietZone($quietZone) { - $this->quietZone = (bool)$quietZone; - } - - /** - * Sets the tracking code. - * - * @param int $barcodeIdentifier 2-digit number. 2nd digit must be 0-4 - * @param int $serviceTypeIdentifier 3 digits - * @param int $mailerIdentifier 6 or 9 digits - * @param int $serialNumber 9 (if mailerId is 6) or 6 digits (if mailerId is 9) - */ - public function setTrackingCode($barcodeIdentifier, $serviceTypeIdentifier, $mailerIdentifier, $serialNumber) { - $barcodeIdentifier = (string)(int)$barcodeIdentifier; - $serviceTypeIdentifier = (int)$serviceTypeIdentifier; - $mailerIdentifier = (int)$mailerIdentifier; - $serialNumber = (string)(int)$serialNumber; - - $barcodeIdentifier = str_pad($barcodeIdentifier, 2, '0', STR_PAD_LEFT); - - if (strlen($barcodeIdentifier) !== 2) { - throw new BCGArgumentException('Barcode Identifier must contain 2 digits.', 'barcodeIdentifier'); - } - - $barcodeIdentifierSecondNumber = $barcodeIdentifier[1]; - if ($barcodeIdentifierSecondNumber !== '0' && $barcodeIdentifierSecondNumber !== '1' && $barcodeIdentifierSecondNumber !== '2' && $barcodeIdentifierSecondNumber !== '3' && $barcodeIdentifierSecondNumber !== '4') { - throw new BCGArgumentException('Barcode Identifier second digit must be a number between 0 and 4.', 'barcodeIdentifier'); - } - - if ($serviceTypeIdentifier < 0 || $serviceTypeIdentifier > 999) { - throw new BCGArgumentException('Service Type Identifier must be between 0 and 999.', 'serviceTypeIdentifier'); - } - - $mailerIdentifierLength = 6; - if ($mailerIdentifier > 899999) { - $mailerIdentifierLength = 9; - } - - if ($mailerIdentifierLength === 9 && strlen($serialNumber) > 6) { - throw new BCGArgumentException('If the Serial Number has more than 6 digits, the Mailer Identifier must be lower than 900000.', 'mailerIdentifier'); - } - - if ($mailerIdentifierLength === 9) { - if ($mailerIdentifierLength < 0 || $mailerIdentifier > 999999999) { - throw new BCGArgumentException('Mailer Identifier must be between 0 and 999999999.', 'mailerIdentifier'); - } - } - - $this->barcodeIdentifier = $barcodeIdentifier; - $this->serviceTypeIdentifier = str_pad($serviceTypeIdentifier, 3, '0', STR_PAD_LEFT); - $this->mailerIdentifier = str_pad($mailerIdentifier, $mailerIdentifierLength, '0', STR_PAD_LEFT); - $this->serialNumber = str_pad((int)$serialNumber, $mailerIdentifierLength === 6 ? 9 : 6, '0', STR_PAD_LEFT); - } - - /** - * Parses the text before displaying it. - * - * @param mixed $text - */ - public function parse($text) { - parent::parse($text); - - $number = self::executeStep1($this->text, $this->barcodeIdentifier, $this->serviceTypeIdentifier, $this->mailerIdentifier, $this->serialNumber); - $crc = self::executeStep2($number); - $codewords = self::executeStep3($number); - $codewords = self::executeStep4($codewords, $crc); - $characters = self::executeStep5($codewords, $crc); - $this->data = self::executeStep6($characters); - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - if ($this->quietZone) { - $this->positionX += 9; - } - - $c = strlen($this->data); - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, $this->data[$i]); - } - - $this->drawText($im, 0, 0, $this->positionX, $this->thickness + ($this->quietZone ? 4 : 0)); - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $w += 65 * 3; - $h += $this->thickness; - - // We remove the white on the right - $w -= 1.56; - - if ($this->quietZone) { - $w += 18; - $h += 4; - } - - return parent::getDimension($w, $h); - } - - /** - * Validates the input. - */ - protected function validate() { - // Tracking must have been entered - if ($this->barcodeIdentifier === null || $this->serviceTypeIdentifier === null || $this->mailerIdentifier === null || $this->serialNumber === null) { - throw new BCGParseException('intelligentmail', 'The tracking code must be set before calling the parse method.'); - } - - // Checking if all chars are allowed - $match = array(); - if (preg_match('/[^0-9]/', $this->text, $match)) { - throw new BCGParseException('intelligentmail', 'The character \'' . $match[0] . '\' is not allowed.'); - } - - // Must contain 0, 5, 9 or 11 chars - $c = strlen($this->text); - if ($c !== 0 && $c !== 5 && $c !== 9 && $c !== 11) { - throw new BCGParseException('intelligentmail', 'Must contain 0, 5, 9, or 11 characters.'); - } - - parent::validate(); - } - - /** - * Overloaded method for drawing special barcode. - * - * @param resource $im - * @param string $code - * @param boolean $startBar - */ - protected function drawChar($im, $code, $startBar = true) { - $y1 = 0; - $y2 = 0; - switch ($code) { - case 'A': - $y1 = 0; - $y2 = $this->thickness - ($this->thickness / 2.5); - break; - case 'D': - $y1 = 3.096; - $y2 = $this->thickness - 1; - break; - case 'F': - $y1 = 0; - $y2 = $this->thickness - 1; - break; - case 'T': - $y1 = 3.096; - $y2 = $this->thickness - ($this->thickness / 2.5); - break; - } - - if ($this->quietZone) { - $y1 += 2; - $y2 += 2; - } - - $this->drawFilledRectangle($im, $this->positionX, $y1, $this->positionX + 0.44, $y2, BCGBarcode::COLOR_FG); - $this->positionX += 3; - } - - /** - * Executes Step 1: Conversion of Data Fields into Binary Data - * - * @param string $text - * @param string $barcodeIdentifier - * @param string $serviceTypeIdentifier - * @param string $mailerIdentifier - * @param string $serialNumber - * @return string BCNumber - */ - private static function executeStep1($text, $barcodeIdentifier, $serviceTypeIdentifier, $mailerIdentifier, $serialNumber) { - $number = self::conversionRoutingCode($text); - $number = self::conversionTrackingCode($number, $barcodeIdentifier, $serviceTypeIdentifier, $mailerIdentifier, $serialNumber); - - return $number; - } - - /** - * Executes Step 2: Generation of 11-Bit CRC on Binary Data - * - * @param $number BCNumber - * @return int - */ - private static function executeStep2($number) { - $byteArray = str_pad(self::bcdecuc($number), 13, chr(0), STR_PAD_LEFT); - - $generatorPolynomial = 0x0f35; - $frameCheckSequence = 0x07ff; - $data = 0; - $byteIndex = 0; - $bit = 0; - - $data = (ord($byteArray[$byteIndex]) << 5) & 0xffff; - for ($bit = 2; $bit < 8; $bit++) { - if (($frameCheckSequence ^ $data) & 0x400) { - $frameCheckSequence = ($frameCheckSequence << 1) ^ $generatorPolynomial; - } else { - $frameCheckSequence = ($frameCheckSequence << 1); - } - - $frameCheckSequence &= 0x7ff; - $data <<= 1; - $data &= 0xffff; - } - - for ($byteIndex = 1; $byteIndex < 13; $byteIndex++) { - $data = (ord($byteArray[$byteIndex]) << 3) & 0xffff; - for ($bit = 0; $bit < 8; $bit++) { - if (($frameCheckSequence ^ $data) & 0x0400) { - $frameCheckSequence = ($frameCheckSequence << 1) ^ $generatorPolynomial; - } else { - $frameCheckSequence = ($frameCheckSequence << 1); - } - - $frameCheckSequence &= 0x7ff; - $data <<= 1; - $data &= 0xffff; - } - } - - return $frameCheckSequence; - } - - /** - * Executes Step 3: Conversion from Binary Data to Codewords - * - * @param string $number BCNumber - * @return int[] - */ - private static function executeStep3($number) { - $codewords = array(); - $codewords[9] = (int)bcmod($number, '636'); - $number = bcdiv($number, '636', 0); - - for ($i = 8; $i >= 0; $i--) { - $codewords[$i] = (int)bcmod($number, '1365'); - $number = bcdiv($number, '1365', 0); - } - - return $codewords; - } - - /** - * Executes Step 4: Inserting Additional Information into Codewords - * - * @param int[] $codewords - * @param int $crc - * @return int[] - */ - private static function executeStep4($codewords, $crc) { - $codewords[9] *= 2; - if ($crc & 0x400) { - $codewords[0] += 659; - } - - return $codewords; - } - - /** - * Executes Step 5: Conversion from Codewords to Characters - * - * @param int[] $codewords - * @param int $crc - * @return int[] - */ - private static function executeStep5($codewords, $crc) { - $characters = array(); - for ($i = 0; $i < 10; $i++) { - if ($codewords[$i] <= 1286) { - $characters[$i] = self::$characterTable1[$codewords[$i]]; - } else { - $characters[$i] = self::$characterTable2[$codewords[$i] - 1287]; - } - } - - for ($i = 0; $i < 10; $i++) { - $mask = 1 << $i; - if ($crc & $mask) { - $characters[$i] ^= 0x1fff; - } - } - - return $characters; - } - - /** - * Executes Step 6: Conversion from Characters to the Intelligent Mail Barcode - * - * @param int[] $characters - * @return string - */ - private static function executeStep6($characters) { - $bars = ''; - for ($i = 0; $i < 65; $i++) { - $barPosition = self::$barPositions[$i]; - $descender = $barPosition[0]; - $ascender = $barPosition[1]; - $extenderDescender = !!($characters[$descender[0]] & (1 << $descender[1])); - $extenderAscender = !!($characters[$ascender[0]] & (1 << $ascender[1])); - - if ($extenderDescender && $extenderAscender) { - $bars .= 'F'; - } elseif ($extenderDescender) { - $bars .= 'D'; - } elseif ($extenderAscender) { - $bars .= 'A'; - } else { - $bars .= 'T'; - } - } - - return $bars; - } - - /** - * Converts the routing code zipcode. - * - * @param string $zipcode - * @return string BCNumber - */ - private static function conversionRoutingCode($zipcode) { - $number = $zipcode; - switch (strlen($zipcode)) { - case 11: - $number = bcadd($number, '1000000000', 0); - case 9: - $number = bcadd($number, '100000', 0); - case 5: - $number = bcadd($number, '1', 0); - default: - return $number; - } - } - - /** - * Converts the tracking code number. - * - * @param string $number BCNumber - * @param string $barcodeIdentifier - * @param string $serviceTypeIdentifier - * @param string $mailerIdentifier - * @param string $serialNumber - * @return string BCNumber - */ - private static function conversionTrackingCode($number, $barcodeIdentifier, $serviceTypeIdentifier, $mailerIdentifier, $serialNumber) { - $number = bcmul($number, 10, 0); - $number = bcadd($number, $barcodeIdentifier[0], 0); - $number = bcmul($number, 5, 0); - $number = bcadd($number, $barcodeIdentifier[1], 0); - - $temp = $serviceTypeIdentifier . $mailerIdentifier . $serialNumber; - for ($i = 0; $i < 18; $i++) { - $number = bcmul($number, 10, 0); - $number = bcadd($number, $temp[$i], 0); - } - - return $number; - } - - /** - * Transforms a BCNumber into unsigned char*. - * - * @param string $dec BCNumber - * @param string - */ - private static function bcdecuc($dec) { - $last = bcmod($dec, 256); - $remain = bcdiv(bcsub($dec, $last), 256, 0); - - if ($remain == 0) { - return pack('C', $last); - } else { - return self::bcdecuc($remain) . pack('C', $last); - } - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGisbn.barcode.php b/niucloud/core/core/util/barcode/class/BCGisbn.barcode.php deleted file mode 100644 index 867cb0f7..00000000 --- a/niucloud/core/core/util/barcode/class/BCGisbn.barcode.php +++ /dev/null @@ -1,164 +0,0 @@ -setGS1($gs1); - } - - /** - * Adds the default label. - */ - protected function addDefaultLabel() { - if ($this->isDefaultEanLabelEnabled()) { - $isbn = $this->createISBNText(); - $font = $this->font; - - $topLabel = new BCGLabel($isbn, $font, BCGLabel::POSITION_TOP, BCGLabel::ALIGN_CENTER); - - $this->addLabel($topLabel); - } - - parent::addDefaultLabel(); - } - - /** - * Sets the first numbers of the barcode. - * - GS1_AUTO: Adds 978 before the code - * - GS1_PREFIX978: Adds 978 before the code - * - GS1_PREFIX979: Adds 979 before the code - * - * @param int $gs1 - */ - public function setGS1($gs1) { - $gs1 = (int)$gs1; - if ($gs1 !== self::GS1_AUTO && $gs1 !== self::GS1_PREFIX978 && $gs1 !== self::GS1_PREFIX979) { - throw new BCGArgumentException('The GS1 argument must be BCGisbn::GS1_AUTO, BCGisbn::GS1_PREFIX978, or BCGisbn::GS1_PREFIX979', 'gs1'); - } - - $this->gs1 = $gs1; - } - - /** - * Check chars allowed. - */ - protected function checkCharsAllowed() { - $c = strlen($this->text); - - // Special case, if we have 10 digits, the last one can be X - if ($c === 10) { - if (array_search($this->text[9], $this->keys) === false && $this->text[9] !== 'X') { - throw new BCGParseException('isbn', 'The character \'' . $this->text[9] . '\' is not allowed.'); - } - - // Drop the last char - $this->text = substr($this->text, 0, 9); - } - - return parent::checkCharsAllowed(); - } - - /** - * Check correct length. - */ - protected function checkCorrectLength() { - $c = strlen($this->text); - - // If we have 13 chars just flush the last one - if ($c === 13) { - $this->text = substr($this->text, 0, 12); - } elseif ($c === 9 || $c === 10) { - if ($c === 10) { - // Before dropping it, we check if it's legal - if (array_search($this->text[9], $this->keys) === false && $this->text[9] !== 'X') { - throw new BCGParseException('isbn', 'The character \'' . $this->text[9] . '\' is not allowed.'); - } - - $this->text = substr($this->text, 0, 9); - } - - if ($this->gs1 === self::GS1_AUTO || $this->gs1 === self::GS1_PREFIX978) { - $this->text = '978' . $this->text; - } elseif ($this->gs1 === self::GS1_PREFIX979) { - $this->text = '979' . $this->text; - } - } elseif ($c !== 12) { - throw new BCGParseException('isbn', 'The code parsed must be 9, 10, 12, or 13 digits long.'); - } - } - - /** - * Creates the ISBN text. - * - * @return string - */ - private function createISBNText() { - $isbn = ''; - if (!empty($this->text)) { - // We try to create the ISBN Text... the hyphen really depends the ISBN agency. - // We just put one before the checksum and one after the GS1 if present. - $c = strlen($this->text); - if ($c === 12 || $c === 13) { - // If we have 13 characters now, just transform it temporarily to find the checksum... - // Further in the code we take care of that anyway. - $lastCharacter = ''; - if ($c === 13) { - $lastCharacter = $this->text[12]; - $this->text = substr($this->text, 0, 12); - } - - $checksum = $this->processChecksum(); - $isbn = 'ISBN ' . substr($this->text, 0, 3) . '-' . substr($this->text, 3, 9) . '-' . $checksum; - - // Put the last character back - if ($c === 13) { - $this->text .= $lastCharacter; - } - } elseif ($c === 9 || $c === 10) { - $checksum = 0; - for ($i = 10; $i >= 2; $i--) { - $checksum += $this->text[10 - $i] * $i; - } - - $checksum = 11 - $checksum % 11; - if ($checksum === 10) { - $checksum = 'X'; // Changing type - } - - $isbn = 'ISBN ' . substr($this->text, 0, 9) . '-' . $checksum; - } - } - - return $isbn; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGmsi.barcode.php b/niucloud/core/core/util/barcode/class/BCGmsi.barcode.php deleted file mode 100644 index a322d829..00000000 --- a/niucloud/core/core/util/barcode/class/BCGmsi.barcode.php +++ /dev/null @@ -1,184 +0,0 @@ -keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); - $this->code = array( - '01010101', /* 0 */ - '01010110', /* 1 */ - '01011001', /* 2 */ - '01011010', /* 3 */ - '01100101', /* 4 */ - '01100110', /* 5 */ - '01101001', /* 6 */ - '01101010', /* 7 */ - '10010101', /* 8 */ - '10010110' /* 9 */ - ); - - $this->setChecksum(0); - } - - /** - * Sets how many checksums we display. 0 to 2. - * - * @param int $checksum - */ - public function setChecksum($checksum) { - $checksum = intval($checksum); - if ($checksum < 0 && $checksum > 2) { - throw new BCGArgumentException('The checksum must be between 0 and 2 included.', 'checksum'); - } - - $this->checksum = $checksum; - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - // Checksum - $this->calculateChecksum(); - - // Starting Code - $this->drawChar($im, '10', true); - - // Chars - $c = strlen($this->text); - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, $this->findCode($this->text[$i]), true); - } - - $c = count($this->checksumValue); - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, $this->findCode($this->checksumValue[$i]), true); - } - - // Ending Code - $this->drawChar($im, '010', true); - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $textlength = 12 * strlen($this->text); - $startlength = 3; - $checksumlength = $this->checksum * 12; - $endlength = 4; - - $w += $startlength + $textlength + $checksumlength + $endlength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Validates the input. - */ - protected function validate() { - $c = strlen($this->text); - if ($c === 0) { - throw new BCGParseException('msi', 'No data has been entered.'); - } - - // Checking if all chars are allowed - for ($i = 0; $i < $c; $i++) { - if (array_search($this->text[$i], $this->keys) === false) { - throw new BCGParseException('msi', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } - } - } - - /** - * Overloaded method to calculate checksum. - */ - protected function calculateChecksum() { - // Forming a new number - // If the original number is even, we take all even position - // If the original number is odd, we take all odd position - // 123456 = 246 - // 12345 = 135 - // Multiply by 2 - // Add up all the digit in the result (270 : 2+7+0) - // Add up other digit not used. - // 10 - (? Modulo 10). If result = 10, change to 0 - $last_text = $this->text; - $this->checksumValue = array(); - for ($i = 0; $i < $this->checksum; $i++) { - $new_text = ''; - $new_number = 0; - $c = strlen($last_text); - if ($c % 2 === 0) { // Even - $starting = 1; - } else { - $starting = 0; - } - - for ($j = $starting; $j < $c; $j += 2) { - $new_text .= $last_text[$j]; - } - - $new_text = strval(intval($new_text) * 2); - $c2 = strlen($new_text); - for ($j = 0; $j < $c2; $j++) { - $new_number += intval($new_text[$j]); - } - - for ($j = ($starting === 0) ? 1 : 0; $j < $c; $j += 2) { - $new_number += intval($last_text[$j]); - } - - $new_number = (10 - $new_number % 10) % 10; - $this->checksumValue[] = $new_number; - $last_text .= $new_number; - } - } - - /** - * Overloaded method to display the checksum. - */ - protected function processChecksum() { - if ($this->checksumValue === false) { // Calculate the checksum only once - $this->calculateChecksum(); - } - - if ($this->checksumValue !== false) { - $ret = ''; - $c = count($this->checksumValue); - for ($i = 0; $i < $c; $i++) { - $ret .= $this->keys[$this->checksumValue[$i]]; - } - - return $ret; - } - - return false; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGothercode.barcode.php b/niucloud/core/core/util/barcode/class/BCGothercode.barcode.php deleted file mode 100644 index a9ae2eda..00000000 --- a/niucloud/core/core/util/barcode/class/BCGothercode.barcode.php +++ /dev/null @@ -1,88 +0,0 @@ -keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - $this->drawChar($im, $this->text, true); - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - } - - /** - * Gets the label. - * If the label was set to BCGBarcode1D::AUTO_LABEL, the label will display the value from the text parsed. - * - * @return string - */ - public function getLabel() { - $label = $this->label; - if ($this->label === BCGBarcode1D::AUTO_LABEL) { - $label = ''; - } - - return $label; - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $array = str_split($this->text, 1); - $textlength = array_sum($array) + count($array); - - $w += $textlength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Validates the input. - */ - protected function validate() { - $c = strlen($this->text); - if ($c === 0) { - throw new BCGParseException('othercode', 'No data has been entered.'); - } - - // Checking if all chars are allowed - for ($i = 0; $i < $c; $i++) { - if (array_search($this->text[$i], $this->keys) === false) { - throw new BCGParseException('othercode', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } - } - - parent::validate(); - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGpostnet.barcode.php b/niucloud/core/core/util/barcode/class/BCGpostnet.barcode.php deleted file mode 100644 index 1988b084..00000000 --- a/niucloud/core/core/util/barcode/class/BCGpostnet.barcode.php +++ /dev/null @@ -1,138 +0,0 @@ -keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); - $this->code = array( - '11000', /* 0 */ - '00011', /* 1 */ - '00101', /* 2 */ - '00110', /* 3 */ - '01001', /* 4 */ - '01010', /* 5 */ - '01100', /* 6 */ - '10001', /* 7 */ - '10010', /* 8 */ - '10100' /* 9 */ - ); - - $this->setThickness(9); - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - // Checksum - $checksum = 0; - $c = strlen($this->text); - for ($i = 0; $i < $c; $i++) { - $checksum += intval($this->text[$i]); - } - - $checksum = 10 - ($checksum % 10); - - // Starting Code - $this->drawChar($im, '1'); - - // Code - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, $this->findCode($this->text[$i])); - } - - // Checksum - $this->drawChar($im, $this->findCode($checksum)); - - // Ending Code - $this->drawChar($im, '1'); - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $c = strlen($this->text); - $startlength = 3; - $textlength = $c * 5 * 3; - $checksumlength = 5 * 3; - $endlength = 3; - - // We remove the white on the right - $removelength = -1.56; - - $w += $startlength + $textlength + $checksumlength + $endlength + $removelength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Validates the input. - */ - protected function validate() { - $c = strlen($this->text); - if ($c === 0) { - throw new BCGParseException('postnet', 'No data has been entered.'); - } - - // Checking if all chars are allowed - for ($i = 0; $i < $c; $i++) { - if (array_search($this->text[$i], $this->keys) === false) { - throw new BCGParseException('postnet', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } - } - - // Must contain 5, 9 or 11 chars - if ($c !== 5 && $c !== 9 && $c !== 11) { - throw new BCGParseException('postnet', 'Must contain 5, 9, or 11 characters.'); - } - - parent::validate(); - } - - /** - * Overloaded method for drawing special barcode. - * - * @param resource $im - * @param string $code - * @param boolean $startBar - */ - protected function drawChar($im, $code, $startBar = true) { - $c = strlen($code); - for ($i = 0; $i < $c; $i++) { - if ($code[$i] === '0') { - $posY = $this->thickness - ($this->thickness / 2.5); - } else { - $posY = 0; - } - - $this->drawFilledRectangle($im, $this->positionX, $posY, $this->positionX + 0.44, $this->thickness - 1, BCGBarcode::COLOR_FG); - $this->positionX += 3; - } - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGs25.barcode.php b/niucloud/core/core/util/barcode/class/BCGs25.barcode.php deleted file mode 100644 index 3312b2cd..00000000 --- a/niucloud/core/core/util/barcode/class/BCGs25.barcode.php +++ /dev/null @@ -1,170 +0,0 @@ - 1/3 or 1/2 for the big bar - * - *-------------------------------------------------------------------- - * Copyright (C) Jean-Sebastien Goupil - * http://www.barcodephp.com - */ -include_once('BCGParseException.php'); -include_once('BCGBarcode1D.php'); - -class BCGs25 extends BCGBarcode1D { - private $checksum; - - /** - * Constructor. - */ - public function __construct() { - parent::__construct(); - - $this->keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); - $this->code = array( - '0000202000', /* 0 */ - '2000000020', /* 1 */ - '0020000020', /* 2 */ - '2020000000', /* 3 */ - '0000200020', /* 4 */ - '2000200000', /* 5 */ - '0020200000', /* 6 */ - '0000002020', /* 7 */ - '2000002000', /* 8 */ - '0020002000' /* 9 */ - ); - - $this->setChecksum(false); - } - - /** - * Sets if we display the checksum. - * - * @param bool $checksum - */ - public function setChecksum($checksum) { - $this->checksum = (bool)$checksum; - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - $temp_text = $this->text; - - // Checksum - if ($this->checksum === true) { - $this->calculateChecksum(); - $temp_text .= $this->keys[$this->checksumValue]; - } - - // Starting Code - $this->drawChar($im, '101000', true); - - // Chars - $c = strlen($temp_text); - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, $this->findCode($temp_text[$i]), true); - } - - // Ending Code - $this->drawChar($im, '10001', true); - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $c = strlen($this->text); - $startlength = 8; - $textlength = $c * 14; - $checksumlength = 0; - if ($c % 2 !== 0) { - $checksumlength = 14; - } - - $endlength = 7; - - $w += $startlength + $textlength + $checksumlength + $endlength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Validates the input. - */ - protected function validate() { - $c = strlen($this->text); - if ($c === 0) { - throw new BCGParseException('s25', 'No data has been entered.'); - } - - // Checking if all chars are allowed - for ($i = 0; $i < $c; $i++) { - if (array_search($this->text[$i], $this->keys) === false) { - throw new BCGParseException('s25', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } - } - - // Must be even - if ($c % 2 !== 0 && $this->checksum === false) { - throw new BCGParseException('s25', 's25 must contain an even amount of digits if checksum is false.'); - } elseif ($c % 2 === 0 && $this->checksum === true) { - throw new BCGParseException('s25', 's25 must contain an odd amount of digits if checksum is true.'); - } - - parent::validate(); - } - - /** - * Overloaded method to calculate checksum. - */ - protected function calculateChecksum() { - // Calculating Checksum - // Consider the right-most digit of the message to be in an "even" position, - // and assign odd/even to each character moving from right to left - // Even Position = 3, Odd Position = 1 - // Multiply it by the number - // Add all of that and do 10-(?mod10) - $even = true; - $this->checksumValue = 0; - $c = strlen($this->text); - for ($i = $c; $i > 0; $i--) { - if ($even === true) { - $multiplier = 3; - $even = false; - } else { - $multiplier = 1; - $even = true; - } - - $this->checksumValue += $this->keys[$this->text[$i - 1]] * $multiplier; - } - $this->checksumValue = (10 - $this->checksumValue % 10) % 10; - } - - /** - * Overloaded method to display the checksum. - */ - protected function processChecksum() { - if ($this->checksumValue === false) { // Calculate the checksum only once - $this->calculateChecksum(); - } - - if ($this->checksumValue !== false) { - return $this->keys[$this->checksumValue]; - } - - return false; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGupca.barcode.php b/niucloud/core/core/util/barcode/class/BCGupca.barcode.php deleted file mode 100644 index 37794331..00000000 --- a/niucloud/core/core/util/barcode/class/BCGupca.barcode.php +++ /dev/null @@ -1,146 +0,0 @@ -text = '0' . $this->text; // We will remove it at the end... don't worry - - parent::draw($im); - - // We remove the 0 in front, as we said :) - $this->text = substr($this->text, 1); - } - - /** - * Draws the extended bars on the image. - * - * @param resource $im - * @param int $plus - */ - protected function drawExtendedBars($im, $plus) { - $temp_text = $this->text . $this->keys[$this->checksumValue]; - $rememberX = $this->positionX; - $rememberH = $this->thickness; - - // We increase the bars - // First 2 Bars - $this->thickness = $this->thickness + intval($plus / $this->scale); - $this->positionX = 0; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - $this->positionX += 2; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - - // Attemping to increase the 2 following bars - $this->positionX += 1; - $temp_value = $this->findCode($temp_text[1]); - $this->drawChar($im, $temp_value, false); - - // Center Guard Bar - $this->positionX += 36; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - $this->positionX += 2; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - - // Attemping to increase the 2 last bars - $this->positionX += 37; - $temp_value = $this->findCode($temp_text[12]); - $this->drawChar($im, $temp_value, true); - - // Completly last bars - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - $this->positionX += 2; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - - $this->positionX = $rememberX; - $this->thickness = $rememberH; - } - - /** - * Adds the default label. - */ - protected function addDefaultLabel() { - if ($this->isDefaultEanLabelEnabled()) { - $this->processChecksum(); - $label = $this->getLabel(); - $font = $this->font; - - $this->labelLeft = new BCGLabel(substr($label, 0, 1), $font, BCGLabel::POSITION_LEFT, BCGLabel::ALIGN_BOTTOM); - $this->labelLeft->setSpacing(4 * $this->scale); - - $this->labelCenter1 = new BCGLabel(substr($label, 1, 5), $font, BCGLabel::POSITION_BOTTOM, BCGLabel::ALIGN_LEFT); - $labelCenter1Dimension = $this->labelCenter1->getDimension(); - $this->labelCenter1->setOffset(($this->scale * 44 - $labelCenter1Dimension[0]) / 2 + $this->scale * 6); - - $this->labelCenter2 = new BCGLabel(substr($label, 6, 5), $font, BCGLabel::POSITION_BOTTOM, BCGLabel::ALIGN_LEFT); - $this->labelCenter2->setOffset(($this->scale * 44 - $labelCenter1Dimension[0]) / 2 + $this->scale * 45); - - $this->labelRight = new BCGLabel($this->keys[$this->checksumValue], $font, BCGLabel::POSITION_RIGHT, BCGLabel::ALIGN_BOTTOM); - $this->labelRight->setSpacing(4 * $this->scale); - - if ($this->alignLabel) { - $labelDimension = $this->labelCenter1->getDimension(); - $this->labelLeft->setOffset($labelDimension[1]); - $this->labelRight->setOffset($labelDimension[1]); - } else { - $labelDimension = $this->labelLeft->getDimension(); - $this->labelLeft->setOffset($labelDimension[1] / 2); - $labelDimension = $this->labelLeft->getDimension(); - $this->labelRight->setOffset($labelDimension[1] / 2); - } - - $this->addLabel($this->labelLeft); - $this->addLabel($this->labelCenter1); - $this->addLabel($this->labelCenter2); - $this->addLabel($this->labelRight); - } - } - - /** - * Check correct length. - */ - protected function checkCorrectLength() { - // If we have 12 chars, just flush the last one without throwing anything - $c = strlen($this->text); - if ($c === 12) { - $this->text = substr($this->text, 0, 11); - } elseif ($c !== 11) { - throw new BCGParseException('upca', 'Must contain 11 digits, the 12th digit is automatically added.'); - } - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGupce.barcode.php b/niucloud/core/core/util/barcode/class/BCGupce.barcode.php deleted file mode 100644 index 5b349289..00000000 --- a/niucloud/core/core/util/barcode/class/BCGupce.barcode.php +++ /dev/null @@ -1,336 +0,0 @@ -keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); - - // Odd Parity starting with a space - // Even Parity is the inverse (0=0012) starting with a space - $this->code = array( - '2100', /* 0 */ - '1110', /* 1 */ - '1011', /* 2 */ - '0300', /* 3 */ - '0021', /* 4 */ - '0120', /* 5 */ - '0003', /* 6 */ - '0201', /* 7 */ - '0102', /* 8 */ - '2001' /* 9 */ - ); - - // Parity, 0=Odd, 1=Even for manufacturer code. Depending on 1st System Digit and Checksum - $this->codeParity = array( - array( - array(1, 1, 1, 0, 0, 0), /* 0,0 */ - array(1, 1, 0, 1, 0, 0), /* 0,1 */ - array(1, 1, 0, 0, 1, 0), /* 0,2 */ - array(1, 1, 0, 0, 0, 1), /* 0,3 */ - array(1, 0, 1, 1, 0, 0), /* 0,4 */ - array(1, 0, 0, 1, 1, 0), /* 0,5 */ - array(1, 0, 0, 0, 1, 1), /* 0,6 */ - array(1, 0, 1, 0, 1, 0), /* 0,7 */ - array(1, 0, 1, 0, 0, 1), /* 0,8 */ - array(1, 0, 0, 1, 0, 1) /* 0,9 */ - ), - array( - array(0, 0, 0, 1, 1, 1), /* 0,0 */ - array(0, 0, 1, 0, 1, 1), /* 0,1 */ - array(0, 0, 1, 1, 0, 1), /* 0,2 */ - array(0, 0, 1, 1, 1, 0), /* 0,3 */ - array(0, 1, 0, 0, 1, 1), /* 0,4 */ - array(0, 1, 1, 0, 0, 1), /* 0,5 */ - array(0, 1, 1, 1, 0, 0), /* 0,6 */ - array(0, 1, 0, 1, 0, 1), /* 0,7 */ - array(0, 1, 0, 1, 1, 0), /* 0,8 */ - array(0, 1, 1, 0, 1, 0) /* 0,9 */ - ) - ); - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - $this->calculateChecksum(); - - // Starting Code - $this->drawChar($im, '000', true); - $c = strlen($this->upce); - for ($i = 0; $i < $c; $i++) { - $this->drawChar($im, self::inverse($this->findCode($this->upce[$i]), $this->codeParity[intval($this->text[0])][$this->checksumValue][$i]), false); - } - - // Draw Center Guard Bar - $this->drawChar($im, '00000', false); - - // Draw Right Bar - $this->drawChar($im, '0', true); - $this->text = $this->text[0] . $this->upce; - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - - if ($this->isDefaultEanLabelEnabled()) { - $dimension = $this->labelCenter->getDimension(); - $this->drawExtendedBars($im, $dimension[1] - 2); - } - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $startlength = 3; - $centerlength = 5; - $textlength = 6 * 7; - $endlength = 1; - - $w += $startlength + $centerlength + $textlength + $endlength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Adds the default label. - */ - protected function addDefaultLabel() { - if ($this->isDefaultEanLabelEnabled()) { - $this->processChecksum(); - $font = $this->font; - - $this->labelLeft = new BCGLabel(substr($this->text, 0, 1), $font, BCGLabel::POSITION_LEFT, BCGLabel::ALIGN_BOTTOM); - $labelLeftDimension = $this->labelLeft->getDimension(); - $this->labelLeft->setSpacing(8); - $this->labelLeft->setOffset($labelLeftDimension[1] / 2); - - $this->labelCenter = new BCGLabel($this->upce, $font, BCGLabel::POSITION_BOTTOM, BCGLabel::ALIGN_LEFT); - $labelCenterDimension = $this->labelCenter->getDimension(); - $this->labelCenter->setOffset(($this->scale * 46 - $labelCenterDimension[0]) / 2 + $this->scale * 2); - - $this->labelRight = new BCGLabel($this->keys[$this->checksumValue], $font, BCGLabel::POSITION_RIGHT, BCGLabel::ALIGN_BOTTOM); - $labelRightDimension = $this->labelRight->getDimension(); - $this->labelRight->setSpacing(8); - $this->labelRight->setOffset($labelRightDimension[1] / 2); - - $this->addLabel($this->labelLeft); - $this->addLabel($this->labelCenter); - $this->addLabel($this->labelRight); - } - } - - /** - * Checks if the default ean label is enabled. - * - * @return bool - */ - protected function isDefaultEanLabelEnabled() { - $label = $this->getLabel(); - $font = $this->font; - return $label !== null && $label !== '' && $font !== null && $this->defaultLabel !== null; - } - - /** - * Validates the input. - */ - protected function validate() { - $c = strlen($this->text); - if ($c === 0) { - throw new BCGParseException('upce', 'No data has been entered.'); - } - - // Checking if all chars are allowed - for ($i = 0; $i < $c; $i++) { - if (array_search($this->text[$i], $this->keys) === false) { - throw new BCGParseException('upce', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } - } - - // Must contain 11 chars - // Must contain 6 chars (if starting with upce directly) - // First Chars must be 0 or 1 - if ($c !== 11 && $c !== 6) { - throw new BCGParseException('upce', 'You must provide a UPC-A (11 characters) or a UPC-E (6 characters).'); - } elseif ($this->text[0] !== '0' && $this->text[0] !== '1' && $c !== 6) { - throw new BCGParseException('upce', 'UPC-A must start with 0 or 1 to be converted to UPC-E.'); - } - - // Convert part - $this->upce = ''; - if ($c !== 6) { - // Checking if UPC-A is convertible - $temp1 = substr($this->text, 3, 3); - if ($temp1 === '000' || $temp1 === '100' || $temp1 === '200') { // manufacturer code ends with 100, 200 or 300 - if (substr($this->text, 6, 2) === '00') { // Product must start with 00 - $this->upce = substr($this->text, 1, 2) . substr($this->text, 8, 3) . substr($this->text, 3, 1); - } - } elseif (substr($this->text, 4, 2) === '00') { // manufacturer code ends with 00 - if (substr($this->text, 6, 3) === '000') { // Product must start with 000 - $this->upce = substr($this->text, 1, 3) . substr($this->text, 9, 2) . '3'; - } - } elseif (substr($this->text, 5, 1) === '0') { // manufacturer code ends with 0 - if (substr($this->text, 6, 4) === '0000') { // Product must start with 0000 - $this->upce = substr($this->text, 1, 4) . substr($this->text, 10, 1) . '4'; - } - } else { // No zero leading at manufacturer code - $temp2 = intval(substr($this->text, 10, 1)); - if (substr($this->text, 6, 4) === '0000' && $temp2 >= 5 && $temp2 <= 9) { // Product must start with 0000 and must end by 5, 6, 7, 8 or 9 - $this->upce = substr($this->text, 1, 5) . substr($this->text, 10, 1); - } - } - } else { - $this->upce = $this->text; - } - - if ($this->upce === '') { - throw new BCGParseException('upce', 'Your UPC-A can\'t be converted to UPC-E.'); - } - - if ($c === 6) { - $upca = ''; - - // We convert UPC-E to UPC-A to find the checksum - if ($this->text[5] === '0' || $this->text[5] === '1' || $this->text[5] === '2') { - $upca = substr($this->text, 0, 2) . $this->text[5] . '0000' . substr($this->text, 2, 3); - } elseif ($this->text[5] === '3') { - $upca = substr($this->text, 0, 3) . '00000' . substr($this->text, 3, 2); - } elseif ($this->text[5] === '4') { - $upca = substr($this->text, 0, 4) . '00000' . $this->text[4]; - } else { - $upca = substr($this->text, 0, 5) . '0000' . $this->text[5]; - } - - $this->text = '0' . $upca; - } - - parent::validate(); - } - - /** - * Overloaded method to calculate checksum. - */ - protected function calculateChecksum() { - // Calculating Checksum - // Consider the right-most digit of the message to be in an "odd" position, - // and assign odd/even to each character moving from right to left - // Odd Position = 3, Even Position = 1 - // Multiply it by the number - // Add all of that and do 10-(?mod10) - $odd = true; - $this->checksumValue = 0; - $c = strlen($this->text); - for ($i = $c; $i > 0; $i--) { - if ($odd === true) { - $multiplier = 3; - $odd = false; - } else { - $multiplier = 1; - $odd = true; - } - - if (!isset($this->keys[$this->text[$i - 1]])) { - return; - } - - $this->checksumValue += $this->keys[$this->text[$i - 1]] * $multiplier; - } - - $this->checksumValue = (10 - $this->checksumValue % 10) % 10; - } - - /** - * Overloaded method to display the checksum. - */ - protected function processChecksum() { - if ($this->checksumValue === false) { // Calculate the checksum only once - $this->calculateChecksum(); - } - - if ($this->checksumValue !== false) { - return $this->keys[$this->checksumValue]; - } - - return false; - } - - /** - * Draws the extended bars on the image. - * - * @param resource $im - * @param int $plus - */ - protected function drawExtendedBars($im, $plus) { - $rememberX = $this->positionX; - $rememberH = $this->thickness; - - // We increase the bars - $this->thickness = $this->thickness + intval($plus / $this->scale); - $this->positionX = 0; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - $this->positionX += 2; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - - // Last Bars - $this->positionX += 46; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - $this->positionX += 2; - $this->drawSingleBar($im, BCGBarcode::COLOR_FG); - - $this->positionX = $rememberX; - $this->thickness = $rememberH; - } - - /** - * Inverses the string when the $inverse parameter is equal to 1. - * - * @param string $text - * @param int $inverse - * @return string - */ - private static function inverse($text, $inverse = 1) { - if ($inverse === 1) { - $text = strrev($text); - } - - return $text; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGupcext2.barcode.php b/niucloud/core/core/util/barcode/class/BCGupcext2.barcode.php deleted file mode 100644 index 4399e0e6..00000000 --- a/niucloud/core/core/util/barcode/class/BCGupcext2.barcode.php +++ /dev/null @@ -1,138 +0,0 @@ -keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); - $this->code = array( - '2100', /* 0 */ - '1110', /* 1 */ - '1011', /* 2 */ - '0300', /* 3 */ - '0021', /* 4 */ - '0120', /* 5 */ - '0003', /* 6 */ - '0201', /* 7 */ - '0102', /* 8 */ - '2001' /* 9 */ - ); - - // Parity, 0=Odd, 1=Even. Depending on ?%4 - $this->codeParity = array( - array(0, 0), /* 0 */ - array(0, 1), /* 1 */ - array(1, 0), /* 2 */ - array(1, 1) /* 3 */ - ); - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - // Starting Code - $this->drawChar($im, '001', true); - - // Code - for ($i = 0; $i < 2; $i++) { - $this->drawChar($im, self::inverse($this->findCode($this->text[$i]), $this->codeParity[intval($this->text) % 4][$i]), false); - if ($i === 0) { - $this->drawChar($im, '00', false); // Inter-char - } - } - - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $startlength = 4; - $textlength = 2 * 7; - $intercharlength = 2; - - $w += $startlength + $textlength + $intercharlength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Adds the default label. - */ - protected function addDefaultLabel() { - parent::addDefaultLabel(); - - if ($this->defaultLabel !== null) { - $this->defaultLabel->setPosition(BCGLabel::POSITION_TOP); - } - } - - /** - * Validates the input. - */ - protected function validate() { - $c = strlen($this->text); - if ($c === 0) { - throw new BCGParseException('upcext2', 'No data has been entered.'); - } - - // Checking if all chars are allowed - for ($i = 0; $i < $c; $i++) { - if (array_search($this->text[$i], $this->keys) === false) { - throw new BCGParseException('upcext2', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } - } - - // Must contain 2 digits - if ($c !== 2) { - throw new BCGParseException('upcext2', 'Must contain 2 digits.'); - } - - parent::validate(); - } - - /** - * Inverses the string when the $inverse parameter is equal to 1. - * - * @param string $text - * @param int $inverse - * @return string - */ - private static function inverse($text, $inverse = 1) { - if ($inverse === 1) { - $text = strrev($text); - } - - return $text; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/BCGupcext5.barcode.php b/niucloud/core/core/util/barcode/class/BCGupcext5.barcode.php deleted file mode 100644 index cea96609..00000000 --- a/niucloud/core/core/util/barcode/class/BCGupcext5.barcode.php +++ /dev/null @@ -1,200 +0,0 @@ - No suggested Retail Price - * If 99991 -> Book Complimentary (normally free) - * If 90001 to 98999 -> Internal Purpose of Publisher - * If 99990 -> Used by the National Association of College Stores to mark used books - * If 0xxxx -> Price Expressed in British Pounds (xx.xx) - * If 5xxxx -> Price Expressed in U.S. dollars (US$xx.xx) - * - *-------------------------------------------------------------------- - * Copyright (C) Jean-Sebastien Goupil - * http://www.barcodephp.com - */ -include_once('BCGParseException.php'); -include_once('BCGBarcode1D.php'); -include_once('BCGLabel.php'); - -class BCGupcext5 extends BCGBarcode1D { - protected $codeParity = array(); - - /** - * Constructor. - */ - public function __construct() { - parent::__construct(); - - $this->keys = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'); - $this->code = array( - '2100', /* 0 */ - '1110', /* 1 */ - '1011', /* 2 */ - '0300', /* 3 */ - '0021', /* 4 */ - '0120', /* 5 */ - '0003', /* 6 */ - '0201', /* 7 */ - '0102', /* 8 */ - '2001' /* 9 */ - ); - - // Parity, 0=Odd, 1=Even. Depending Checksum - $this->codeParity = array( - array(1, 1, 0, 0, 0), /* 0 */ - array(1, 0, 1, 0, 0), /* 1 */ - array(1, 0, 0, 1, 0), /* 2 */ - array(1, 0, 0, 0, 1), /* 3 */ - array(0, 1, 1, 0, 0), /* 4 */ - array(0, 0, 1, 1, 0), /* 5 */ - array(0, 0, 0, 1, 1), /* 6 */ - array(0, 1, 0, 1, 0), /* 7 */ - array(0, 1, 0, 0, 1), /* 8 */ - array(0, 0, 1, 0, 1) /* 9 */ - ); - } - - /** - * Draws the barcode. - * - * @param resource $im - */ - public function draw($im) { - // Checksum - $this->calculateChecksum(); - - // Starting Code - $this->drawChar($im, '001', true); - - // Code - for ($i = 0; $i < 5; $i++) { - $this->drawChar($im, self::inverse($this->findCode($this->text[$i]), $this->codeParity[$this->checksumValue][$i]), false); - if ($i < 4) { - $this->drawChar($im, '00', false); // Inter-char - } - } - - $this->drawText($im, 0, 0, $this->positionX, $this->thickness); - } - - /** - * Returns the maximal size of a barcode. - * - * @param int $w - * @param int $h - * @return int[] - */ - public function getDimension($w, $h) { - $startlength = 4; - $textlength = 5 * 7; - $intercharlength = 2 * 4; - - $w += $startlength + $textlength + $intercharlength; - $h += $this->thickness; - return parent::getDimension($w, $h); - } - - /** - * Adds the default label. - */ - protected function addDefaultLabel() { - parent::addDefaultLabel(); - - if ($this->defaultLabel !== null) { - $this->defaultLabel->setPosition(BCGLabel::POSITION_TOP); - } - } - - /** - * Validates the input. - */ - protected function validate() { - $c = strlen($this->text); - if ($c === 0) { - throw new BCGParseException('upcext5', 'No data has been entered.'); - } - - // Checking if all chars are allowed - for ($i = 0; $i < $c; $i++) { - if (array_search($this->text[$i], $this->keys) === false) { - throw new BCGParseException('upcext5', 'The character \'' . $this->text[$i] . '\' is not allowed.'); - } - } - - // Must contain 5 digits - if ($c !== 5) { - throw new BCGParseException('upcext5', 'Must contain 5 digits.'); - } - - parent::validate(); - } - - /** - * Overloaded method to calculate checksum. - */ - protected function calculateChecksum() { - // Calculating Checksum - // Consider the right-most digit of the message to be in an "odd" position, - // and assign odd/even to each character moving from right to left - // Odd Position = 3, Even Position = 9 - // Multiply it by the number - // Add all of that and do ?mod10 - $odd = true; - $this->checksumValue = 0; - $c = strlen($this->text); - for ($i = $c; $i > 0; $i--) { - if ($odd === true) { - $multiplier = 3; - $odd = false; - } else { - $multiplier = 9; - $odd = true; - } - - if (!isset($this->keys[$this->text[$i - 1]])) { - return; - } - - $this->checksumValue += $this->keys[$this->text[$i - 1]] * $multiplier; - } - - $this->checksumValue = $this->checksumValue % 10; - } - - /** - * Overloaded method to display the checksum. - */ - protected function processChecksum() { - if ($this->checksumValue === false) { // Calculate the checksum only once - $this->calculateChecksum(); - } - - if ($this->checksumValue !== false) { - return $this->keys[$this->checksumValue]; - } - - return false; - } - - /** - * Inverses the string when the $inverse parameter is equal to 1. - * - * @param string $text - * @param int $inverse - * @return string - */ - private static function inverse($text, $inverse = 1) { - if ($inverse === 1) { - $text = strrev($text); - } - - return $text; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/JoinDraw.php b/niucloud/core/core/util/barcode/class/JoinDraw.php deleted file mode 100644 index 2d3c35fa..00000000 --- a/niucloud/core/core/util/barcode/class/JoinDraw.php +++ /dev/null @@ -1,194 +0,0 @@ -image1 = $image1->get_im(); - } else { - $this->image1 = $image1; - } - if ($image2 instanceof BCGDrawing) { - $this->image2 = $image2->get_im(); - } else { - $this->image2 = $image2; - } - - $this->background = $background; - $this->space = (int)$space; - $this->position = (int)$position; - $this->alignment = (int)$alignment; - - $this->createIm(); - } - - /** - * Destroys the image. - */ - public function __destruct() { - imagedestroy($this->im); - } - - /** - * Finds the position where the barcode should be aligned. - * - * @param int $size1 - * @param int $size2 - * @param int $ailgnment - * @return int - */ - private function findPosition($size1, $size2, $alignment) { - $rsize1 = max($size1, $size2); - $rsize2 = min($size1, $size2); - - if ($alignment === self::ALIGN_LEFT) { // Or TOP - return 0; - } elseif ($alignment === self::ALIGN_CENTER) { - return $rsize1 / 2 - $rsize2 / 2; - } else { // RIGHT or TOP - return $rsize1 - $rsize2; - } - } - - /** - * Change the alignments. - * - * @param int $alignment - * @return int - */ - private function changeAlignment($alignment) { - if ($alignment === 0) { - return 1; - } elseif ($alignment === 1) { - return 0; - } else { - return 2; - } - } - - /** - * Creates the image. - */ - private function createIm() { - $w1 = imagesx($this->image1); - $w2 = imagesx($this->image2); - $h1 = imagesy($this->image1); - $h2 = imagesy($this->image2); - - if ($this->position === self::POSITION_LEFT || $this->position === self::POSITION_RIGHT) { - $w = $w1 + $w2 + $this->space; - $h = max($h1, $h2); - } else { - $w = max($w1, $w2); - $h = $h1 + $h2 + $this->space; - } - - $this->im = imagecreatetruecolor($w, $h); - imagefill($this->im, 0, 0, $this->background->allocate($this->im)); - - // We start defining position of images - if ($this->position === self::POSITION_TOP) { - if ($w1 > $w2) { - $posX1 = 0; - $posX2 = $this->findPosition($w1, $w2, $this->alignment); - } else { - $a = $this->changeAlignment($this->alignment); - $posX1 = $this->findPosition($w1, $w2, $a); - $posX2 = 0; - } - - $posY2 = 0; - $posY1 = $h2 + $this->space; - } elseif ($this->position === self::POSITION_LEFT) { - if ($w1 > $w2) { - $posY1 = 0; - $posY2 = $this->findPosition($h1, $h2, $this->alignment); - } else { - $a = $this->changeAlignment($this->alignment); - $posY2 = 0; - $posY1 = $this->findPosition($h1, $h2, $a); - } - - $posX2 = 0; - $posX1 = $w2 + $this->space; - } elseif ($this->position === self::POSITION_BOTTOM) { - if ($w1 > $w2) { - $posX2 = $this->findPosition($w1, $w2, $this->alignment); - $posX1 = 0; - } else { - $a = $this->changeAlignment($this->alignment); - $posX2 = 0; - $posX1 = $this->findPosition($w1, $w2, $a); - } - - $posY1 = 0; - $posY2 = $h1 + $this->space; - } else { // defaults to RIGHT - if ($w1 > $w2) { - $posY2 = $this->findPosition($h1, $h2, $this->alignment); - $posY1 = 0; - } else { - $a = $this->changeAlignment($this->alignment); - $posY2 = 0; - $posY1 = $this->findPosition($h1, $h2, $a); - } - - $posX1 = 0; - $posX2 = $w1 + $this->space; - } - - imagecopy($this->im, $this->image1, $posX1, $posY1, 0, 0, $w1, $h1); - imagecopy($this->im, $this->image2, $posX2, $posY2, 0, 0, $w2, $h2); - } - - /** - * Returns the new $im created. - * - * @return resource - */ - public function get_im() { - return $this->im; - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/drawer/BCGDraw.php b/niucloud/core/core/util/barcode/class/drawer/BCGDraw.php deleted file mode 100644 index 2082b5da..00000000 --- a/niucloud/core/core/util/barcode/class/drawer/BCGDraw.php +++ /dev/null @@ -1,38 +0,0 @@ -im = $im; - } - - /** - * Sets the filename. - * - * @param string $filename - */ - public function setFilename($filename) { - $this->filename = $filename; - } - - /** - * Method needed to draw the image based on its specification (JPG, GIF, etc.). - */ - abstract public function draw(); -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/drawer/BCGDrawJPG.php b/niucloud/core/core/util/barcode/class/drawer/BCGDrawJPG.php deleted file mode 100644 index 2e2c9398..00000000 --- a/niucloud/core/core/util/barcode/class/drawer/BCGDrawJPG.php +++ /dev/null @@ -1,102 +0,0 @@ -dpi = max(1, $dpi); - } else { - $this->dpi = null; - } - } - - /** - * Sets the quality of the JPG. - * - * @param int $quality - */ - public function setQuality($quality) { - $this->quality = $quality; - } - - /** - * Draws the JPG on the screen or in a file. - */ - public function draw() { - ob_start(); - imagejpeg($this->im, null, $this->quality); - $bin = ob_get_contents(); - ob_end_clean(); - - $this->setInternalProperties($bin); - - if (empty($this->filename)) { - echo $bin; - } else { - file_put_contents($this->filename, $bin); - } - } - - private function setInternalProperties(&$bin) { - $this->internalSetDPI($bin); - $this->internalSetC($bin); - } - - private function internalSetDPI(&$bin) { - if ($this->dpi !== null) { - $bin = substr_replace($bin, pack("Cnn", 0x01, $this->dpi, $this->dpi), 13, 5); - } - } - - private function internalSetC(&$bin) { - if(strcmp(substr($bin, 0, 4), pack('H*', 'FFD8FFE0')) === 0) { - $offset = 4 + (ord($bin[4]) << 8 | ord($bin[5])); - $firstPart = substr($bin, 0, $offset); - $secondPart = substr($bin, $offset); - $cr = pack('H*', 'FFFE004447656E657261746564207769746820426172636F64652047656E657261746F7220666F722050485020687474703A2F2F7777772E626172636F64657068702E636F6D'); - $bin = $firstPart; - $bin .= $cr; - $bin .= $secondPart; - } - } -} -?> \ No newline at end of file diff --git a/niucloud/core/core/util/barcode/class/drawer/BCGDrawPNG.php b/niucloud/core/core/util/barcode/class/drawer/BCGDrawPNG.php deleted file mode 100644 index 5b65a3aa..00000000 --- a/niucloud/core/core/util/barcode/class/drawer/BCGDrawPNG.php +++ /dev/null @@ -1,202 +0,0 @@ -dpi = max(1, $dpi); - } else { - $this->dpi = null; - } - } - - /** - * Draws the PNG on the screen or in a file. - */ - public function draw() { - ob_start(); - imagepng($this->im); - $bin = ob_get_contents(); - ob_end_clean(); - - $this->setInternalProperties($bin); - - if (empty($this->filename)) { - echo $bin; - } else { - file_put_contents($this->filename, $bin); - } - } - - private function setInternalProperties(&$bin) { - // Scan all the ChunkType - if (strcmp(substr($bin, 0, 8), pack('H*', '89504E470D0A1A0A')) === 0) { - $chunks = $this->detectChunks($bin); - - $this->internalSetDPI($bin, $chunks); - $this->internalSetC($bin, $chunks); - } - } - - private function detectChunks($bin) { - $data = substr($bin, 8); - $chunks = array(); - $c = strlen($data); - - $offset = 0; - while ($offset < $c) { - $packed = unpack('Nsize/a4chunk', $data); - $size = $packed['size']; - $chunk = $packed['chunk']; - - $chunks[] = array('offset' => $offset + 8, 'size' => $size, 'chunk' => $chunk); - $jump = $size + 12; - $offset += $jump; - $data = substr($data, $jump); - } - - return $chunks; - } - - private function internalSetDPI(&$bin, &$chunks) { - if ($this->dpi !== null) { - $meters = (int)($this->dpi * 39.37007874); - - $found = -1; - $c = count($chunks); - for($i = 0; $i < $c; $i++) { - // We already have a pHYs - if($chunks[$i]['chunk'] === 'pHYs') { - $found = $i; - break; - } - } - - $data = 'pHYs' . pack('NNC', $meters, $meters, 0x01); - $crc = self::crc($data, 13); - $cr = pack('Na13N', 9, $data, $crc); - - // We didn't have a pHYs - if($found == -1) { - // Don't do anything if we have a bad PNG - if($c >= 2 && $chunks[0]['chunk'] === 'IHDR') { - array_splice($chunks, 1, 0, array(array('offset' => 33, 'size' => 9, 'chunk' => 'pHYs'))); - - // Push the data - for($i = 2; $i < $c; $i++) { - $chunks[$i]['offset'] += 21; - } - - $firstPart = substr($bin, 0, 33); - $secondPart = substr($bin, 33); - $bin = $firstPart; - $bin .= $cr; - $bin .= $secondPart; - } - } else { - $bin = substr_replace($bin, $cr, $chunks[$i]['offset'], 21); - } - } - } - - private function internalSetC(&$bin, &$chunks) { - if (count($chunks) >= 2 && $chunks[0]['chunk'] === 'IHDR') { - $firstPart = substr($bin, 0, 33); - $secondPart = substr($bin, 33); - $cr = pack('H*', '0000004C74455874436F707972696768740047656E657261746564207769746820426172636F64652047656E657261746F7220666F722050485020687474703A2F2F7777772E626172636F64657068702E636F6D597F70B8'); - $bin = $firstPart; - $bin .= $cr; - $bin .= $secondPart; - } - - // Chunks is dirty!! But we are done. - } - - private static $crc_table = array(); - private static $crc_table_computed = false; - - private static function make_crc_table() { - for ($n = 0; $n < 256; $n++) { - $c = $n; - for ($k = 0; $k < 8; $k++) { - if (($c & 1) == 1) { - $c = 0xedb88320 ^ (self::SHR($c, 1)); - } else { - $c = self::SHR($c, 1); - } - } - self::$crc_table[$n] = $c; - } - - self::$crc_table_computed = true; - } - - private static function SHR($x, $n) { - $mask = 0x40000000; - - if ($x < 0) { - $x &= 0x7FFFFFFF; - $mask = $mask >> ($n - 1); - return ($x >> $n) | $mask; - } - - return (int)$x >> (int)$n; - } - - private static function update_crc($crc, $buf, $len) { - $c = $crc; - - if (!self::$crc_table_computed) { - self::make_crc_table(); - } - - for ($n = 0; $n < $len; $n++) { - $c = self::$crc_table[($c ^ ord($buf[$n])) & 0xff] ^ (self::SHR($c, 8)); - } - - return $c; - } - - private static function crc($data, $len) { - return self::update_crc(-1, $data, $len) ^ -1; - } -} -?> diff --git a/niucloud/core/core/util/barcode/font/Arial.ttf b/niucloud/core/core/util/barcode/font/Arial.ttf deleted file mode 100644 index 886789b85b4b4e662519fcb7fe4d88ddf2205c5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 311636 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 VXQc0|TekeI1$m{%qWu+${|Acode = $code; - $this->secret = $secret; - }else{ - $auth_config = (new CoreNiucloudConfigService())->getNiucloudConfig(); - if($auth_config['auth_code'] || $auth_config['auth_secret']){ - $this->code = $auth_config['auth_code']; - $this->secret = $auth_config['auth_secret']; - }else{ - $this->code = config('niucloud.auth.code'); - $this->secret = config('niucloud.auth.secret'); - } - } - $this->access_token = $this->getAccessToken(); - $this->request = request(); - $this->developer_token = (new ConfigService())->getDeveloperToken()['token'] ?? ''; - } - - /** - * @param string $url - * @param array $data - * @return array|Response|object|ResponseInterface - * @throws GuzzleException - */ - public function httpPost(string $url, array $data = []) - { - return $this->request($url, 'POST', [ - 'form_params' => $data, - ]); - } - - /** - * @param string $url - * @param string $method - * @param array $options - * @param bool $returnRaw - * - * @return ResponseInterface - * @throws GuzzleException - */ - public function request(string $url, string $method = 'GET', array $options = [], bool $returnRaw = false) - { - if (empty($this->middlewares)) { - $this->registerHttpMiddlewares(); - } - $response = $this->toRequest($url, $method, $options); - return $response; - } - - /** - * Register Guzzle middlewares. - */ - protected function registerHttpMiddlewares() - { - // retry - $this->pushMiddleware($this->retryMiddleware(), 'retry'); - //header - $this->pushMiddleware($this->headerMiddleware(), 'header'); - // access token - $this->pushMiddleware($this->accessTokenMiddleware(), 'access_token'); - } - - /** - * @return callable - */ - protected function retryMiddleware() - { - return Middleware::retry( - function ( - $retries, - RequestInterface $request, - ResponseInterface $response = null - ) { - // Limit the number of retries to 2 重试次数,默认 1,指定当 http 请求失败时重试的次数。 - if ($retries < config('niucloud.http.max_retries', 1) && $response && $body = $response->getBody()) { - // Retry on server errors - $response = json_decode($body, true); - if (isset($response['code'])) { - if ($response['code'] != 1) { - if (in_array(abs($response['code']), [401], true)) { - $this->clearAccessToken(); - $this->refreshAccessToken(); - } else { - throw new NiucloudException($response['msg']); - } - } - return true; - } - } - return false; - }, - function () { - //重试延迟间隔(单位:ms),默认 500 - return abs(config('niucloud.http.retry_delay', 500)); - } - ); - } - - /** - * 表头属性 - * @return Closure - */ - public function headerMiddleware(){ - $developer_token = $this->developer_token; - - return function (callable $handler) use ($developer_token) { - return function (RequestInterface $request, array $options) use ($handler, $developer_token) { - $domain = request()->domain(true); - $domain = str_replace('http://', '', $domain); - $domain = str_replace('https://', '', $domain); - $request = $request->withHeader('Referer', $domain); - $request = $request->withHeader('developer-token', $developer_token); - $options['verify'] = config('niucloud.http.verify', true); - return $handler($request, $options); - }; - }; - } - - - /** - * @param string $url - * @param array $query - * @return array|object|Response|ResponseInterface - * @throws GuzzleException - */ - public function httpGet(string $url, array $query = []) - { - return $this->request($url, 'GET', [ - 'query' => $query, - ]); - } - - /** - * @return Closure - */ - protected function accessTokenMiddleware() - { - return function (callable $handler) { - return function (RequestInterface $request, array $options) use ($handler) { - if ($this->access_token) { - $request = $this->applyToRequest($request, $options); - } - return $handler($request, $options); - }; - }; - } - - /** - * @param RequestInterface $request - * @param array $requestOptions - * @return RequestInterface - */ - public function applyToRequest(RequestInterface $request, array $requestOptions = []): RequestInterface - { - return $request->withHeader($this->access_token_key, $this->access_token); - } - - /** - * @param string $url - * @param array $data - * @param array $query - * @return array|Response|object|ResponseInterface - * @throws GuzzleException - */ - public function httpPostJson(string $url, array $data = [], array $query = []) - { - return $this->request($url, 'POST', ['query' => $query, 'json' => $data]); - } - - /** - * @param string $url - * @param array $files - * @param array $form - * @param array $query - * @return array|Response|object|ResponseInterface - * @throws GuzzleException - */ - public function httpUpload(string $url, array $files = [], array $form = [], array $query = []) - { - $multipart = []; - $headers = []; - - if (isset($form['filename'])) { - $headers = [ - 'Content-Disposition' => 'form-data; name="media"; filename="' . $form['filename'] . '"' - ]; - } - - foreach ($files as $name => $path) { - $multipart[] = [ - 'name' => $name, - 'contents' => fopen($path, 'r'), - 'headers' => $headers - ]; - } - - foreach ($form as $name => $contents) { - $multipart[] = compact('name', 'contents'); - } - - return $this->request( - $url, - 'POST', - ['query' => $query, 'multipart' => $multipart, 'connect_timeout' => 30, 'timeout' => 30, 'read_timeout' => 30] - ); - } - - /** - * @param string $url - * @param string $method - * @param array $options - * @throws GuzzleException - */ - public function requestRaw(string $url, string $method = 'GET', array $options = []) - { - return Response::buildFromPsrResponse($this->request($url, $method, $options, true)); - } - - /** - * 下载文件 - * @param string $url - * @param array $query - * @param string $absolute_path - * @return string - * @throws GuzzleException - */ - public function download(string $url, array $query = [], string $absolute_path = '') - { - // 打开即将下载的本地文件,在该文件上打开一个流 - $resource = fopen($absolute_path, 'w'); - $res = $this->request($url, 'GET', ['sink' => $absolute_path, 'query' => $query]); - // 关闭一个已打开的文件指针 - fclose($resource); - return $absolute_path; - } - - public function getDomain($is_filter = true){ - $domain = request()->domain(true); - if($is_filter){ - $domain = str_replace('http://', '', $domain); - $domain = str_replace('https://', '', $domain); - } - return $domain; - } -} diff --git a/niucloud/core/core/util/niucloud/CloudService.php b/niucloud/core/core/util/niucloud/CloudService.php deleted file mode 100644 index e9323cb5..00000000 --- a/niucloud/core/core/util/niucloud/CloudService.php +++ /dev/null @@ -1,37 +0,0 @@ -baseUri = 'http://' . gethostbyname('oss.niucloud.com') . ':8000/'; - } - - public function httpPost(string $url, array $options = []) { - return $this->toRequest($url, 'POST', $options); - } - - public function httpGet(string $url, array $options = []) { - return $this->toRequest($url, 'GET', $options); - } - - public function request(string $method, string $url, array $options = []) { - return (new Client(['base_uri' => $this->baseUri ]))->request($method, $url, $options); - } - - public function getUrl(string $url) { - return $this->baseUri . $url; - } -} diff --git a/niucloud/core/core/util/niucloud/http/AccessToken.php b/niucloud/core/core/util/niucloud/http/AccessToken.php deleted file mode 100644 index c0315b3e..00000000 --- a/niucloud/core/core/util/niucloud/http/AccessToken.php +++ /dev/null @@ -1,73 +0,0 @@ -access_token = ''; - Cache::delete($this->access_token_cache); - return $this; - } - /** - * 设置access_token - * @param $access_token - * @return $this - */ - public function setAccessToken($access_token) - { - $this->access_token = $access_token; - Cache::set($this->access_token_cache, $access_token, 7200); - return $this; - } - /** - * @return mixed - */ - public function getAccessToken() - { - if (empty($this->access_token)) { - $this->access_token = Cache::get($this->access_token_cache, ''); - } - return $this->access_token; - } - - /** - * 刷新access_token - * @return void - * @throws GuzzleException - */ - public function refreshAccessToken() - { - $access_token_info = $this->httpGet('auth', ['code' => $this->code, 'secret' => $this->secret, 'token' => $this->createToken(), 'product_key' => self::PRODUCT, 'redirect_uri' => $this->getDomain(false)]); - if (isset($access_token_info['code']) && $access_token_info['code'] != 1) throw new NiucloudException($access_token_info['msg']); - $this->setAccessToken($access_token_info['data']['token']); - } - -} diff --git a/niucloud/core/core/util/niucloud/http/HasHttpRequests.php b/niucloud/core/core/util/niucloud/http/HasHttpRequests.php deleted file mode 100644 index e10925e3..00000000 --- a/niucloud/core/core/util/niucloud/http/HasHttpRequests.php +++ /dev/null @@ -1,183 +0,0 @@ - [ - CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, - ], - ]; - /** - * @var ClientInterface - */ - protected $httpClient; - /** - * @var array - */ - protected array $middlewares = []; - /** - * @var HandlerStack - */ - protected $handlerStack; - - /** - * @param array $defaults - * @return void - */ - public static function setDefaultOptions(array $defaults = []) - { - self::$defaults = $defaults; - } - - /** - * @return array - */ - public static function getDefaultOptions(): array - { - return self::$defaults; - } - - /** - * @param callable $middleware - * @param string|null $name - * @return $this - */ - public function pushMiddleware(callable $middleware, string $name = null) - { - if (!is_null($name)) { - $this->middlewares[$name] = $middleware; - } else { - $this->middlewares[] = $middleware; - } - - return $this; - } - - /** - * @return array - */ - public function getMiddlewares(): array - { - return $this->middlewares; - } - - /** - * @param $url - * @param string $method - * @param array $options - * @return ResponseInterface - * @throws GuzzleException - */ - public function toRequest($url, string $method = 'GET', array $options = []) - { - $method = strtoupper($method); - - $options = array_merge(self::$defaults, $options, ['handler' => $this->getHandlerStack()]); - - $options = $this->fixJsonIssue($options); - - if (property_exists($this, 'baseUri') && !is_null($this->baseUri)) { - $options['base_uri'] = $this->baseUri; - } - $options['connect_timeout'] = config('niucloud.http.connect_timeout', 3); - $response = $this->getHttpClient()->request($method, $url, $options); - $response->getBody()->rewind(); - return json_decode($response->getBody()->getContents(), true); - } - - /** - * @return HandlerStack - */ - public function getHandlerStack(): HandlerStack - { - if ($this->handlerStack) { - return $this->handlerStack; - } - - $this->handlerStack = HandlerStack::create($this->getGuzzleHandler()); - - foreach ($this->middlewares as $name => $middleware) { - $this->handlerStack->push($middleware, $name); - } - - return $this->handlerStack; - } - - /** - * @param HandlerStack $handlerStack - * - * @return $this - */ - public function setHandlerStack(HandlerStack $handlerStack) - { - $this->handlerStack = $handlerStack; - - return $this; - } - - /** - * @return callable - */ - protected function getGuzzleHandler() - { - return choose_handler(); - } - - /** - * @param array $options - * @return array - */ - protected function fixJsonIssue(array $options): array - { - if (isset($options['json']) && is_array($options['json'])) { - $options['headers'] = array_merge($options['headers'] ?? [], ['Content-Type' => 'application/json']); - - if (empty($options['json'])) { - $options['body'] = \GuzzleHttp\json_encode($options['json'], JSON_FORCE_OBJECT); - } else { - $options['body'] = \GuzzleHttp\json_encode($options['json'], JSON_UNESCAPED_UNICODE); - } - - unset($options['json']); - } - - return $options; - } - - /** - * @return ClientInterface - */ - public function getHttpClient(): ClientInterface - { - if (!($this->httpClient instanceof ClientInterface)) { - $this->httpClient = new Client(['handler' => HandlerStack::create($this->getGuzzleHandler())]); - } - - return $this->httpClient; - } - - /** - * @param ClientInterface $httpClient - * @return $this - */ - public function setHttpClient(ClientInterface $httpClient) - { - $this->httpClient = $httpClient; - - return $this; - } -} diff --git a/niucloud/core/core/util/niucloud/http/Response.php b/niucloud/core/core/util/niucloud/http/Response.php deleted file mode 100644 index 81e1182c..00000000 --- a/niucloud/core/core/util/niucloud/http/Response.php +++ /dev/null @@ -1,95 +0,0 @@ -getStatusCode(), - $response->getHeaders(), - $response->getBody(), - $response->getProtocolVersion(), - $response->getReasonPhrase() - ); - } - - /** - * @return object - */ - public function toObject() - { - return json_decode($this->toJson()); - } - - /** - * Build to json. - * - * @return string - */ - public function toJson() - { - return json_encode($this->toArray()); - } - - /** - * Build to array. - * - * @return array - */ - public function toArray() - { - $content = $this->removeControlCharacters($this->getBodyContents()); - - if (false !== stripos($this->getHeaderLine('Content-Type'), 'xml') || 0 === stripos($content, 'getBody()->rewind(); - $contents = $this->getBody()->getContents(); - $this->getBody()->rewind(); - - return $contents; - } - - /** - * @return string - */ - public function __toString() - { - return $this->getBodyContents(); - } -} diff --git a/niucloud/core/core/util/niucloud/http/Token.php b/niucloud/core/core/util/niucloud/http/Token.php deleted file mode 100644 index bb06d51c..00000000 --- a/niucloud/core/core/util/niucloud/http/Token.php +++ /dev/null @@ -1,81 +0,0 @@ -request->get('signature') !== $this->signature([ - $this->getToken(), - $this->request->get('timestamp'), - $this->request->get('nonce'), - ])) { - throw new NiucloudException('Invalid request signature.'); - } - return true; - } - - /** - * 生成临时证书 - * @param array $params - * @return string - */ - protected function signature(array $params) - { - sort($params, SORT_STRING); - - return sha1(implode($params)); - } - - /** - * 获取TOKEN - * @return void - */ - public function getToken(){ - return Cache::get($this->token_cache, ''); - } - - /** - * 新创建一个token(todo 临时) - * @return void - */ - public function createToken(){ - //根据code和secret生成token - $token = md5(serialize( - [ - 'timestamp' => time(), - 'code' => $this->code, - 'secret' => $this->secret, - 'nonce' => mt_rand(0, 100) - ] - )); - $this->clearToken(); - Cache::set($this->token_cache, $token, 3600); - return $token; - } - - /** - * @return $this - */ - public function clearToken() - { - $this->access_token = ''; - Cache::delete($this->token_cache); - return $this; - } -} diff --git a/niucloud/core/core/util/niucloud/support/XML.php b/niucloud/core/core/util/niucloud/support/XML.php deleted file mode 100644 index d0485bea..00000000 --- a/niucloud/core/core/util/niucloud/support/XML.php +++ /dev/null @@ -1,155 +0,0 @@ - $value) { - $res = self::normalize($value); - if (('@attributes' === $key) && ($key)) { - $result = $res; - } else { - $result[$key] = $res; - } - } - } else { - $result = $obj; - } - - return $result; - } - - /** - * Delete invalid characters in XML. - * - * @see https://www.w3.org/TR/2008/REC-xml-20081126/#charsets - XML charset range - * @see http://php.net/manual/en/regexp.reference.escape.php - escape in UTF-8 mode - * - * @param string $xml - * - * @return string - */ - public static function sanitize($xml) - { - return preg_replace('/[^\x{9}\x{A}\x{D}\x{20}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]+/u', '', $xml); - } - - /** - * XML encode. - * - * @param mixed $data - * @param string $root - * @param string $item - * @param string $attr - * @param string $id - * - * @return string - */ - public static function build( - $data, - $root = 'xml', - $item = 'item', - $attr = '', - $id = 'id' - ) - { - if (is_array($attr)) { - $_attr = []; - - foreach ($attr as $key => $value) { - $_attr[] = "{$key}=\"{$value}\""; - } - - $attr = implode(' ', $_attr); - } - - $attr = trim($attr); - $attr = empty($attr) ? '' : " {$attr}"; - $xml = "<{$root}{$attr}>"; - $xml .= self::data2Xml($data, $item, $id); - $xml .= ""; - - return $xml; - } - - /** - * Array to XML. - * - * @param array $data - * @param string $item - * @param string $id - * - * @return string - */ - protected static function data2Xml($data, $item = 'item', $id = 'id') - { - $xml = $attr = ''; - - foreach ($data as $key => $val) { - if (is_numeric($key)) { - $id && $attr = " {$id}=\"{$key}\""; - $key = $item; - } - - $xml .= "<{$key}{$attr}>"; - - if ((is_array($val) || is_object($val))) { - $xml .= self::data2Xml((array)$val, $item, $id); - } else { - $xml .= is_numeric($val) ? $val : self::cdata($val); - } - - $xml .= ""; - } - - return $xml; - } - - /** - * Build CDATA. - * - * @param string $string - * - * @return string - */ - public static function cdata($string) - { - return sprintf('', $string); - } -}