diff --git a/app/admin/controller/Index.php b/app/admin/controller/Index.php index 0cc744b..a5fa097 100644 --- a/app/admin/controller/Index.php +++ b/app/admin/controller/Index.php @@ -51,6 +51,12 @@ class Index extends AuthController $this->assign("friend_link_count", $FriendLinkCount); $messageFormCount = MessageForm::counts(new MessageForm()); $this->assign("message_form_count", $messageFormCount); + $data =[ + "page"=> 0 , + "limit" => 5 + ]; + $articleList = Document::systemPage($data)['data']; + $this->assign("article_list", $articleList); return $this->fetch(); } diff --git a/app/admin/view/index/main.html b/app/admin/view/index/main.html index 2374d95..3167ad8 100644 --- a/app/admin/view/index/main.html +++ b/app/admin/view/index/main.html @@ -69,6 +69,40 @@ +
+
+
+
+

项目信息

+
+
+
+ + + + + + + + + + + {volist name="article_list" id="vo"} + + + + + + + {/volist} + +
#文章标题文章分类发布时间
{$vo.id}{$vo.title}{$vo.category_title}{$vo.create_time}
+
+
+
+
+ +
diff --git a/app/common/model/Document.php b/app/common/model/Document.php index e5b383d..cdfb1f7 100644 --- a/app/common/model/Document.php +++ b/app/common/model/Document.php @@ -33,10 +33,10 @@ class Document extends BaseModel { $model = new self; $model = $model->where("type", "=", $where['type'] ?? Data::DOCUMENT_TYPE_ARTICLE); - if ($where['title'] != '') $model = $model->where("title", "like", "%$where[title]%"); - if ($where['start_time'] != '') $model = $model->where("create_time", ">", strtotime($where['start_time'] . " 00:00:00")); - if ($where['end_time'] != '') $model = $model->where("create_time", "<", strtotime($where['end_time'] . " 23:59:59")); - if ($where['status'] != '') $model = $model->where("status", $where['status']); + if (!empty($where['title'])) $model = $model->where("title", "like", "%$where[title]%"); + if (!empty($where['start_time'])) $model = $model->where("create_time", ">", strtotime($where['start_time'] . " 00:00:00")); + if (!empty($where['end_time'])) $model = $model->where("create_time", "<", strtotime($where['end_time'] . " 23:59:59")); + if (!empty($where['status'])) $model = $model->where("status", $where['status']); $model = $model->order("sort desc")->order("id desc"); $count = self::counts($model); if ($where['page'] && $where['limit']) $model = $model->page((int)$where['page'], (int)$where['limit']); diff --git a/vendor/bin/var-dump-server b/vendor/bin/var-dump-server index 527f3ed..c52c772 100644 --- a/vendor/bin/var-dump-server +++ b/vendor/bin/var-dump-server @@ -108,7 +108,10 @@ if (PHP_VERSION_ID < 80000) { } } - if (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) { + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { include("phpvfscomposer://" . __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server'); exit(0); } diff --git a/vendor/bin/var-dump-server.bat b/vendor/bin/var-dump-server.bat index c3c7476..94333da 100644 --- a/vendor/bin/var-dump-server.bat +++ b/vendor/bin/var-dump-server.bat @@ -1,5 +1,5 @@ @ECHO OFF setlocal DISABLEDELAYEDEXPANSION SET BIN_TARGET=%~dp0/var-dump-server -SET COMPOSER_BIN_DIR=%~dp0 +SET COMPOSER_RUNTIME_BIN_DIR=%~dp0 php "%BIN_TARGET%" %* diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 6dc14fe..f39169b 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -9,7 +9,7 @@ return array( 'think\\view\\driver\\' => array($vendorDir . '/topthink/think-view/src'), 'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'), 'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'), - 'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-template/src', $vendorDir . '/topthink/think-orm/src'), + 'think\\' => array($vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/think-template/src'), 'app\\' => array($baseDir . '/app'), 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), 'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'), diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index bc17c4e..4a0b0ca 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -81,8 +81,8 @@ class ComposerStaticInit4b57298e8d0e895486f3307a354a7e1a array ( 0 => __DIR__ . '/..' . '/topthink/framework/src/think', 1 => __DIR__ . '/..' . '/topthink/think-helper/src', - 2 => __DIR__ . '/..' . '/topthink/think-template/src', - 3 => __DIR__ . '/..' . '/topthink/think-orm/src', + 2 => __DIR__ . '/..' . '/topthink/think-orm/src', + 3 => __DIR__ . '/..' . '/topthink/think-template/src', ), 'app\\' => array ( diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 65e20e0..fd2eb61 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -915,17 +915,17 @@ }, { "name": "symfony/http-foundation", - "version": "v5.4.10", - "version_normalized": "5.4.10.0", + "version": "v5.4.12", + "version_normalized": "5.4.12.0", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "e7793b7906f72a8cc51054fbca9dcff7a8af1c1e" + "reference": "f4bfe9611b113b15d98a43da68ec9b5a00d56791" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e7793b7906f72a8cc51054fbca9dcff7a8af1c1e", - "reference": "e7793b7906f72a8cc51054fbca9dcff7a8af1c1e", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f4bfe9611b113b15d98a43da68ec9b5a00d56791", + "reference": "f4bfe9611b113b15d98a43da68ec9b5a00d56791", "shasum": "", "mirrors": [ { @@ -943,13 +943,16 @@ "require-dev": { "predis/predis": "~1.0", "symfony/cache": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", "symfony/expression-language": "^4.4|^5.0|^6.0", - "symfony/mime": "^4.4|^5.0|^6.0" + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", + "symfony/mime": "^4.4|^5.0|^6.0", + "symfony/rate-limiter": "^5.2|^6.0" }, "suggest": { "symfony/mime": "To use the file extension guesser" }, - "time": "2022-06-19T13:13:40+00:00", + "time": "2022-08-19T07:33:17+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -977,7 +980,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.4.10" + "source": "https://github.com/symfony/http-foundation/tree/v5.4.12" }, "funding": [ { @@ -1266,17 +1269,17 @@ }, { "name": "symfony/var-dumper", - "version": "v4.4.42", - "version_normalized": "4.4.42.0", + "version": "v4.4.44", + "version_normalized": "4.4.44.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "742aab50ad097bcb62d91fccb613f66b8047d2ca" + "reference": "f19951007dae942cc79b979c1fe26bfdfbeb54ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/742aab50ad097bcb62d91fccb613f66b8047d2ca", - "reference": "742aab50ad097bcb62d91fccb613f66b8047d2ca", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/f19951007dae942cc79b979c1fe26bfdfbeb54ed", + "reference": "f19951007dae942cc79b979c1fe26bfdfbeb54ed", "shasum": "", "mirrors": [ { @@ -1306,7 +1309,7 @@ "ext-intl": "To show region name in time zone dump", "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" }, - "time": "2022-05-21T10:00:54+00:00", + "time": "2022-07-20T09:59:04+00:00", "bin": [ "Resources/bin/var-dump-server" ], @@ -1344,7 +1347,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v4.4.42" + "source": "https://github.com/symfony/var-dumper/tree/v4.4.44" }, "funding": [ { @@ -1364,17 +1367,17 @@ }, { "name": "topthink/framework", - "version": "v6.0.12", - "version_normalized": "6.0.12.0", + "version": "v6.0.13", + "version_normalized": "6.0.13.0", "source": { "type": "git", "url": "https://github.com/top-think/framework.git", - "reference": "e478316ac843c1a884a3b3a7a94db17c4001ff5c" + "reference": "126d5b2cbacb73d6e2a85cbc7a2c6ee59d0b3fa6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/top-think/framework/zipball/e478316ac843c1a884a3b3a7a94db17c4001ff5c", - "reference": "e478316ac843c1a884a3b3a7a94db17c4001ff5c", + "url": "https://api.github.com/repos/top-think/framework/zipball/126d5b2cbacb73d6e2a85cbc7a2c6ee59d0b3fa6", + "reference": "126d5b2cbacb73d6e2a85cbc7a2c6ee59d0b3fa6", "shasum": "", "mirrors": [ { @@ -1402,7 +1405,7 @@ "mockery/mockery": "^1.2", "phpunit/phpunit": "^7.0" }, - "time": "2022-01-21T06:31:07+00:00", + "time": "2022-07-15T02:52:08+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1434,7 +1437,7 @@ ], "support": { "issues": "https://github.com/top-think/framework/issues", - "source": "https://github.com/top-think/framework/tree/v6.0.12" + "source": "https://github.com/top-think/framework/tree/v6.0.13" }, "install-path": "../topthink/framework" }, @@ -1614,17 +1617,17 @@ }, { "name": "topthink/think-orm", - "version": "v2.0.53", - "version_normalized": "2.0.53.0", + "version": "v2.0.54", + "version_normalized": "2.0.54.0", "source": { "type": "git", "url": "https://github.com/top-think/think-orm.git", - "reference": "06783eda65547a70ea686360a897759e1f873fff" + "reference": "97b061b47616301ff29fbd4c35ed9184e1162e4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/top-think/think-orm/zipball/06783eda65547a70ea686360a897759e1f873fff", - "reference": "06783eda65547a70ea686360a897759e1f873fff", + "url": "https://api.github.com/repos/top-think/think-orm/zipball/97b061b47616301ff29fbd4c35ed9184e1162e4e", + "reference": "97b061b47616301ff29fbd4c35ed9184e1162e4e", "shasum": "", "mirrors": [ { @@ -1637,14 +1640,14 @@ "ext-json": "*", "ext-pdo": "*", "php": ">=7.1.0", - "psr/log": "~1.0", - "psr/simple-cache": "^1.0", + "psr/log": "^1.0|^2.0", + "psr/simple-cache": "^1.0|^2.0", "topthink/think-helper": "^3.1" }, "require-dev": { "phpunit/phpunit": "^7|^8|^9.5" }, - "time": "2022-02-28T14:54:22+00:00", + "time": "2022-07-05T05:25:51+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1672,7 +1675,7 @@ ], "support": { "issues": "https://github.com/top-think/think-orm/issues", - "source": "https://github.com/top-think/think-orm/tree/v2.0.53" + "source": "https://github.com/top-think/think-orm/tree/v2.0.54" }, "install-path": "../topthink/think-orm" }, diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 4458ba7..767c1a5 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'topthink/think', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'dc0fcfd1eb5f19c42b2ec51208d3bca840538c92', + 'reference' => 'ecdf50d35553ba71e48f82e41d38feb090fd0f7b', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -128,9 +128,9 @@ 'dev_requirement' => false, ), 'symfony/http-foundation' => array( - 'pretty_version' => 'v5.4.10', - 'version' => '5.4.10.0', - 'reference' => 'e7793b7906f72a8cc51054fbca9dcff7a8af1c1e', + 'pretty_version' => 'v5.4.12', + 'version' => '5.4.12.0', + 'reference' => 'f4bfe9611b113b15d98a43da68ec9b5a00d56791', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-foundation', 'aliases' => array(), @@ -164,18 +164,18 @@ 'dev_requirement' => false, ), 'symfony/var-dumper' => array( - 'pretty_version' => 'v4.4.42', - 'version' => '4.4.42.0', - 'reference' => '742aab50ad097bcb62d91fccb613f66b8047d2ca', + 'pretty_version' => 'v4.4.44', + 'version' => '4.4.44.0', + 'reference' => 'f19951007dae942cc79b979c1fe26bfdfbeb54ed', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-dumper', 'aliases' => array(), 'dev_requirement' => true, ), 'topthink/framework' => array( - 'pretty_version' => 'v6.0.12', - 'version' => '6.0.12.0', - 'reference' => 'e478316ac843c1a884a3b3a7a94db17c4001ff5c', + 'pretty_version' => 'v6.0.13', + 'version' => '6.0.13.0', + 'reference' => '126d5b2cbacb73d6e2a85cbc7a2c6ee59d0b3fa6', 'type' => 'library', 'install_path' => __DIR__ . '/../topthink/framework', 'aliases' => array(), @@ -184,7 +184,7 @@ 'topthink/think' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'dc0fcfd1eb5f19c42b2ec51208d3bca840538c92', + 'reference' => 'ecdf50d35553ba71e48f82e41d38feb090fd0f7b', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -218,9 +218,9 @@ 'dev_requirement' => false, ), 'topthink/think-orm' => array( - 'pretty_version' => 'v2.0.53', - 'version' => '2.0.53.0', - 'reference' => '06783eda65547a70ea686360a897759e1f873fff', + 'pretty_version' => 'v2.0.54', + 'version' => '2.0.54.0', + 'reference' => '97b061b47616301ff29fbd4c35ed9184e1162e4e', 'type' => 'library', 'install_path' => __DIR__ . '/../topthink/think-orm', 'aliases' => array(), diff --git a/vendor/services.php b/vendor/services.php index 82b4c38..3b59f21 100644 --- a/vendor/services.php +++ b/vendor/services.php @@ -1,5 +1,5 @@ 'think\\captcha\\CaptchaService', diff --git a/vendor/symfony/http-foundation/BinaryFileResponse.php b/vendor/symfony/http-foundation/BinaryFileResponse.php index 4769cab..beb0eda 100644 --- a/vendor/symfony/http-foundation/BinaryFileResponse.php +++ b/vendor/symfony/http-foundation/BinaryFileResponse.php @@ -34,6 +34,7 @@ class BinaryFileResponse extends Response protected $offset = 0; protected $maxlen = -1; protected $deleteFileAfterSend = false; + protected $chunkSize = 8 * 1024; /** * @param \SplFileInfo|string $file The file to stream @@ -125,6 +126,22 @@ class BinaryFileResponse extends Response return $this->file; } + /** + * Sets the response stream chunk size. + * + * @return $this + */ + public function setChunkSize(int $chunkSize): self + { + if ($chunkSize < 1 || $chunkSize > \PHP_INT_MAX) { + throw new \LogicException('The chunk size of a BinaryFileResponse cannot be less than 1 or greater than PHP_INT_MAX.'); + } + + $this->chunkSize = $chunkSize; + + return $this; + } + /** * Automatically sets the Last-Modified header according the file modification date. * @@ -306,7 +323,23 @@ class BinaryFileResponse extends Response $out = fopen('php://output', 'w'); $file = fopen($this->file->getPathname(), 'r'); - stream_copy_to_stream($file, $out, $this->maxlen, $this->offset); + ignore_user_abort(true); + + if (0 !== $this->offset) { + fseek($file, $this->offset); + } + + $length = $this->maxlen; + while ($length && !feof($file)) { + $read = ($length > $this->chunkSize) ? $this->chunkSize : $length; + $length -= $read; + + stream_copy_to_stream($file, $out, $read); + + if (connection_aborted()) { + break; + } + } fclose($out); fclose($file); diff --git a/vendor/symfony/http-foundation/File/UploadedFile.php b/vendor/symfony/http-foundation/File/UploadedFile.php index cf50a02..fcc6299 100644 --- a/vendor/symfony/http-foundation/File/UploadedFile.php +++ b/vendor/symfony/http-foundation/File/UploadedFile.php @@ -223,8 +223,8 @@ class UploadedFile extends File */ public static function getMaxFilesize() { - $sizePostMax = self::parseFilesize(ini_get('post_max_size')); - $sizeUploadMax = self::parseFilesize(ini_get('upload_max_filesize')); + $sizePostMax = self::parseFilesize(\ini_get('post_max_size')); + $sizeUploadMax = self::parseFilesize(\ini_get('upload_max_filesize')); return min($sizePostMax ?: \PHP_INT_MAX, $sizeUploadMax ?: \PHP_INT_MAX); } @@ -253,8 +253,11 @@ class UploadedFile extends File switch (substr($size, -1)) { case 't': $max *= 1024; + // no break case 'g': $max *= 1024; + // no break case 'm': $max *= 1024; + // no break case 'k': $max *= 1024; } diff --git a/vendor/symfony/http-foundation/InputBag.php b/vendor/symfony/http-foundation/InputBag.php index b36001d..a9d3cd8 100644 --- a/vendor/symfony/http-foundation/InputBag.php +++ b/vendor/symfony/http-foundation/InputBag.php @@ -29,14 +29,14 @@ final class InputBag extends ParameterBag */ public function get(string $key, $default = null) { - if (null !== $default && !is_scalar($default) && !(\is_object($default) && method_exists($default, '__toString'))) { + if (null !== $default && !\is_scalar($default) && !(\is_object($default) && method_exists($default, '__toString'))) { trigger_deprecation('symfony/http-foundation', '5.1', 'Passing a non-scalar value as 2nd argument to "%s()" is deprecated, pass a scalar or null instead.', __METHOD__); } $value = parent::get($key, $this); - if (null !== $value && $this !== $value && !is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) { - trigger_deprecation('symfony/http-foundation', '5.1', 'Retrieving a non-string value from "%s()" is deprecated, and will throw a "%s" exception in Symfony 6.0, use "%s::all($key)" instead.', __METHOD__, BadRequestException::class, __CLASS__); + if (null !== $value && $this !== $value && !\is_scalar($value) && !(\is_object($value) && method_exists($value, '__toString'))) { + trigger_deprecation('symfony/http-foundation', '5.1', 'Retrieving a non-scalar value from "%s()" is deprecated, and will throw a "%s" exception in Symfony 6.0, use "%s::all($key)" instead.', __METHOD__, BadRequestException::class, __CLASS__); } return $this === $value ? $default : $value; @@ -76,7 +76,7 @@ final class InputBag extends ParameterBag */ public function set(string $key, $value) { - if (null !== $value && !is_scalar($value) && !\is_array($value) && !method_exists($value, '__toString')) { + if (null !== $value && !\is_scalar($value) && !\is_array($value) && !method_exists($value, '__toString')) { trigger_deprecation('symfony/http-foundation', '5.1', 'Passing "%s" as a 2nd Argument to "%s()" is deprecated, pass a scalar, array, or null instead.', get_debug_type($value), __METHOD__); } diff --git a/vendor/symfony/http-foundation/ParameterBag.php b/vendor/symfony/http-foundation/ParameterBag.php index 7d051ab..e1f89d6 100644 --- a/vendor/symfony/http-foundation/ParameterBag.php +++ b/vendor/symfony/http-foundation/ParameterBag.php @@ -39,7 +39,7 @@ class ParameterBag implements \IteratorAggregate, \Countable * * @return array */ - public function all(/*string $key = null*/) + public function all(/* string $key = null */) { $key = \func_num_args() > 0 ? func_get_arg(0) : null; diff --git a/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php b/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php index c91d614..a6dd993 100644 --- a/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php +++ b/vendor/symfony/http-foundation/RateLimiter/AbstractRequestRateLimiter.php @@ -35,9 +35,7 @@ abstract class AbstractRequestRateLimiter implements RequestRateLimiterInterface foreach ($limiters as $limiter) { $rateLimit = $limiter->consume(1); - if (null === $minimalRateLimit || $rateLimit->getRemainingTokens() < $minimalRateLimit->getRemainingTokens()) { - $minimalRateLimit = $rateLimit; - } + $minimalRateLimit = $minimalRateLimit ? self::getMinimalRateLimit($minimalRateLimit, $rateLimit) : $rateLimit; } return $minimalRateLimit; @@ -54,4 +52,20 @@ abstract class AbstractRequestRateLimiter implements RequestRateLimiterInterface * @return LimiterInterface[] a set of limiters using keys extracted from the request */ abstract protected function getLimiters(Request $request): array; + + private static function getMinimalRateLimit(RateLimit $first, RateLimit $second): RateLimit + { + if ($first->isAccepted() !== $second->isAccepted()) { + return $first->isAccepted() ? $second : $first; + } + + $firstRemainingTokens = $first->getRemainingTokens(); + $secondRemainingTokens = $second->getRemainingTokens(); + + if ($firstRemainingTokens === $secondRemainingTokens) { + return $first->getRetryAfter() < $second->getRetryAfter() ? $second : $first; + } + + return $firstRemainingTokens > $secondRemainingTokens ? $second : $first; + } } diff --git a/vendor/symfony/http-foundation/Request.php b/vendor/symfony/http-foundation/Request.php index d112b1f..65f30a1 100644 --- a/vendor/symfony/http-foundation/Request.php +++ b/vendor/symfony/http-foundation/Request.php @@ -562,7 +562,7 @@ class Request $request = ['g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE]; - $requestOrder = ini_get('request_order') ?: ini_get('variables_order'); + $requestOrder = \ini_get('request_order') ?: \ini_get('variables_order'); $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp'; $_REQUEST = [[]]; diff --git a/vendor/symfony/http-foundation/Response.php b/vendor/symfony/http-foundation/Response.php index def7f8e..88635bb 100644 --- a/vendor/symfony/http-foundation/Response.php +++ b/vendor/symfony/http-foundation/Response.php @@ -72,7 +72,7 @@ class Response public const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585 public const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585 public const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; // RFC6585 - public const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; + public const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; // RFC7725 public const HTTP_INTERNAL_SERVER_ERROR = 500; public const HTTP_NOT_IMPLEMENTED = 501; public const HTTP_BAD_GATEWAY = 502; @@ -1245,6 +1245,7 @@ class Response while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || ($s['flags'] & $flags) === $flags : $s['del'])) { if ($flush) { ob_end_flush(); + flush(); } else { ob_end_clean(); } diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php index bc7b944..35d7b4b 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php @@ -35,8 +35,8 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess public function open($savePath, $sessionName) { $this->sessionName = $sessionName; - if (!headers_sent() && !ini_get('session.cache_limiter') && '0' !== ini_get('session.cache_limiter')) { - header(sprintf('Cache-Control: max-age=%d, private, must-revalidate', 60 * (int) ini_get('session.cache_expire'))); + if (!headers_sent() && !\ini_get('session.cache_limiter') && '0' !== \ini_get('session.cache_limiter')) { + header(sprintf('Cache-Control: max-age=%d, private, must-revalidate', 60 * (int) \ini_get('session.cache_expire'))); } return true; @@ -126,7 +126,7 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess #[\ReturnTypeWillChange] public function destroy($sessionId) { - if (!headers_sent() && filter_var(ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN)) { + if (!headers_sent() && filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN)) { if (!$this->sessionName) { throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', static::class)); } @@ -141,7 +141,7 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess */ if (null === $cookie || isset($_COOKIE[$this->sessionName])) { if (\PHP_VERSION_ID < 70300) { - setcookie($this->sessionName, '', 0, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), filter_var(ini_get('session.cookie_secure'), \FILTER_VALIDATE_BOOLEAN), filter_var(ini_get('session.cookie_httponly'), \FILTER_VALIDATE_BOOLEAN)); + setcookie($this->sessionName, '', 0, \ini_get('session.cookie_path'), \ini_get('session.cookie_domain'), filter_var(\ini_get('session.cookie_secure'), \FILTER_VALIDATE_BOOLEAN), filter_var(\ini_get('session.cookie_httponly'), \FILTER_VALIDATE_BOOLEAN)); } else { $params = session_get_cookie_params(); unset($params['lifetime']); diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php index a5a78eb..9cb841a 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -77,7 +77,7 @@ class MemcachedSessionHandler extends AbstractSessionHandler #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { - $this->memcached->touch($this->prefix.$sessionId, time() + (int) ($this->ttl ?? ini_get('session.gc_maxlifetime'))); + $this->memcached->touch($this->prefix.$sessionId, time() + (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime'))); return true; } @@ -87,7 +87,7 @@ class MemcachedSessionHandler extends AbstractSessionHandler */ protected function doWrite(string $sessionId, string $data) { - return $this->memcached->set($this->prefix.$sessionId, $data, time() + (int) ($this->ttl ?? ini_get('session.gc_maxlifetime'))); + return $this->memcached->set($this->prefix.$sessionId, $data, time() + (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime'))); } /** diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php index 8384e79..ef8f719 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -121,7 +121,7 @@ class MongoDbSessionHandler extends AbstractSessionHandler */ protected function doWrite(string $sessionId, string $data) { - $expiry = new UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000); + $expiry = new UTCDateTime((time() + (int) \ini_get('session.gc_maxlifetime')) * 1000); $fields = [ $this->options['time_field'] => new UTCDateTime(), @@ -144,7 +144,7 @@ class MongoDbSessionHandler extends AbstractSessionHandler #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { - $expiry = new UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000); + $expiry = new UTCDateTime((time() + (int) \ini_get('session.gc_maxlifetime')) * 1000); $this->getCollection()->updateOne( [$this->options['id_field'] => $sessionId], diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php index effc9db..1ca4bfe 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php @@ -31,7 +31,7 @@ class NativeFileSessionHandler extends \SessionHandler public function __construct(string $savePath = null) { if (null === $savePath) { - $savePath = ini_get('session.save_path'); + $savePath = \ini_get('session.save_path'); } $baseDir = $savePath; diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php index 067bfcb..24c9894 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php @@ -344,7 +344,7 @@ class PdoSessionHandler extends AbstractSessionHandler */ protected function doWrite(string $sessionId, string $data) { - $maxlifetime = (int) ini_get('session.gc_maxlifetime'); + $maxlifetime = (int) \ini_get('session.gc_maxlifetime'); try { // We use a single MERGE SQL query when supported by the database. @@ -391,7 +391,7 @@ class PdoSessionHandler extends AbstractSessionHandler #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { - $expiry = time() + (int) ini_get('session.gc_maxlifetime'); + $expiry = time() + (int) \ini_get('session.gc_maxlifetime'); try { $updateStmt = $this->pdo->prepare( @@ -687,7 +687,7 @@ class PdoSessionHandler extends AbstractSessionHandler throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.'); } - if (!filter_var(ini_get('session.use_strict_mode'), \FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { + if (!filter_var(\ini_get('session.use_strict_mode'), \FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { // In strict mode, session fixation is not possible: new sessions always start with a unique // random id, so that concurrency is not possible and this code path can be skipped. // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block @@ -935,7 +935,7 @@ class PdoSessionHandler extends AbstractSessionHandler protected function getConnection() { if (null === $this->pdo) { - $this->connect($this->dsn ?: ini_get('session.save_path')); + $this->connect($this->dsn ?: \ini_get('session.save_path')); } return $this->pdo; diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php index 9573b31..31954e6 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php @@ -79,7 +79,7 @@ class RedisSessionHandler extends AbstractSessionHandler */ protected function doWrite(string $sessionId, string $data): bool { - $result = $this->redis->setEx($this->prefix.$sessionId, (int) ($this->ttl ?? ini_get('session.gc_maxlifetime')), $data); + $result = $this->redis->setEx($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime')), $data); return $result && !$result instanceof ErrorInterface; } @@ -132,6 +132,6 @@ class RedisSessionHandler extends AbstractSessionHandler #[\ReturnTypeWillChange] public function updateTimestamp($sessionId, $data) { - return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ($this->ttl ?? ini_get('session.gc_maxlifetime'))); + return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ($this->ttl ?? \ini_get('session.gc_maxlifetime'))); } } diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php index 0461e99..f7c385f 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php @@ -30,6 +30,16 @@ class StrictSessionHandler extends AbstractSessionHandler $this->handler = $handler; } + /** + * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. + * + * @internal + */ + public function isWrapper(): bool + { + return $this->handler instanceof \SessionHandler; + } + /** * @return bool */ diff --git a/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php b/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php index 1bfce55..595a9e2 100644 --- a/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php +++ b/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php @@ -162,6 +162,6 @@ class MetadataBag implements SessionBagInterface { $timeStamp = time(); $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; - $this->meta[self::LIFETIME] = $lifetime ?? (int) ini_get('session.cookie_lifetime'); + $this->meta[self::LIFETIME] = $lifetime ?? (int) \ini_get('session.cookie_lifetime'); } } diff --git a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php index 4440dcc..a50c827 100644 --- a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php +++ b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php @@ -141,12 +141,42 @@ class NativeSessionStorage implements SessionStorageInterface throw new \RuntimeException('Failed to start the session: already started by PHP.'); } - if (filter_var(ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) { + if (filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) { throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line)); } $sessionId = $_COOKIE[session_name()] ?? null; - if ($sessionId && $this->saveHandler instanceof AbstractProxy && 'files' === $this->saveHandler->getSaveHandlerName() && !preg_match('/^[a-zA-Z0-9,-]{22,}$/', $sessionId)) { + /* + * Explanation of the session ID regular expression: `/^[a-zA-Z0-9,-]{22,250}$/`. + * + * ---------- Part 1 + * + * The part `[a-zA-Z0-9,-]` is related to the PHP ini directive `session.sid_bits_per_character` defined as 6. + * See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-bits-per-character. + * Allowed values are integers such as: + * - 4 for range `a-f0-9` + * - 5 for range `a-v0-9` + * - 6 for range `a-zA-Z0-9,-` + * + * ---------- Part 2 + * + * The part `{22,250}` is related to the PHP ini directive `session.sid_length`. + * See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-length. + * Allowed values are integers between 22 and 256, but we use 250 for the max. + * + * Where does the 250 come from? + * - The length of Windows and Linux filenames is limited to 255 bytes. Then the max must not exceed 255. + * - The session filename prefix is `sess_`, a 5 bytes string. Then the max must not exceed 255 - 5 = 250. + * + * ---------- Conclusion + * + * The parts 1 and 2 prevent the warning below: + * `PHP Warning: SessionHandler::read(): Session ID is too long or contains illegal characters. Only the A-Z, a-z, 0-9, "-", and "," characters are allowed.` + * + * The part 2 prevents the warning below: + * `PHP Warning: SessionHandler::read(): open(filepath, O_RDWR) failed: No such file or directory (2).` + */ + if ($sessionId && $this->saveHandler instanceof AbstractProxy && 'files' === $this->saveHandler->getSaveHandlerName() && !preg_match('/^[a-zA-Z0-9,-]{22,250}$/', $sessionId)) { // the session ID in the header is invalid, create a new one session_id(session_create_id()); } @@ -214,7 +244,7 @@ class NativeSessionStorage implements SessionStorageInterface return false; } - if (null !== $lifetime && $lifetime != ini_get('session.cookie_lifetime')) { + if (null !== $lifetime && $lifetime != \ini_get('session.cookie_lifetime')) { $this->save(); ini_set('session.cookie_lifetime', $lifetime); $this->start(); @@ -249,7 +279,7 @@ class NativeSessionStorage implements SessionStorageInterface unset($_SESSION[$key]); } } - if ([$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) { + if ($_SESSION && [$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) { unset($_SESSION[$key]); } diff --git a/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php b/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php index 9b0cdeb..0defa4a 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php +++ b/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php @@ -11,6 +11,8 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; + /** * @author Drak */ @@ -22,7 +24,7 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf { $this->handler = $handler; $this->wrapper = $handler instanceof \SessionHandler; - $this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') : 'user'; + $this->saveHandlerName = $this->wrapper || ($handler instanceof StrictSessionHandler && $handler->isWrapper()) ? \ini_get('session.save_handler') : 'user'; } /** diff --git a/vendor/symfony/http-foundation/composer.json b/vendor/symfony/http-foundation/composer.json index d54bbfd..cb8d59f 100644 --- a/vendor/symfony/http-foundation/composer.json +++ b/vendor/symfony/http-foundation/composer.json @@ -24,8 +24,11 @@ "require-dev": { "predis/predis": "~1.0", "symfony/cache": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", "symfony/mime": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^4.4|^5.0|^6.0" + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/rate-limiter": "^5.2|^6.0" }, "suggest" : { "symfony/mime": "To use the file extension guesser" diff --git a/vendor/symfony/var-dumper/Caster/ArgsStub.php b/vendor/symfony/var-dumper/Caster/ArgsStub.php index f8b485b..b3f7bbe 100644 --- a/vendor/symfony/var-dumper/Caster/ArgsStub.php +++ b/vendor/symfony/var-dumper/Caster/ArgsStub.php @@ -28,7 +28,7 @@ class ArgsStub extends EnumStub $values = []; foreach ($args as $k => $v) { - $values[$k] = !is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v; + $values[$k] = !\is_scalar($v) && !$v instanceof Stub ? new CutStub($v) : $v; } if (null === $params) { parent::__construct($values, false); diff --git a/vendor/symfony/var-dumper/Caster/IntlCaster.php b/vendor/symfony/var-dumper/Caster/IntlCaster.php index d7099cb..581324d 100644 --- a/vendor/symfony/var-dumper/Caster/IntlCaster.php +++ b/vendor/symfony/var-dumper/Caster/IntlCaster.php @@ -102,7 +102,7 @@ class IntlCaster 'SIGNIFICANT_DIGIT_SYMBOL' => $c->getSymbol(\NumberFormatter::SIGNIFICANT_DIGIT_SYMBOL), 'MONETARY_GROUPING_SEPARATOR_SYMBOL' => $c->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL), ] - ), + ), ]; return self::castError($c, $a); diff --git a/vendor/symfony/var-dumper/Dumper/AbstractDumper.php b/vendor/symfony/var-dumper/Dumper/AbstractDumper.php index 2d3bb01..4185329 100644 --- a/vendor/symfony/var-dumper/Dumper/AbstractDumper.php +++ b/vendor/symfony/var-dumper/Dumper/AbstractDumper.php @@ -45,7 +45,7 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface public function __construct($output = null, string $charset = null, int $flags = 0) { $this->flags = $flags; - $this->setCharset($charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8'); + $this->setCharset($charset ?: \ini_get('php.output_encoding') ?: \ini_get('default_charset') ?: 'UTF-8'); $this->decimalPoint = \PHP_VERSION_ID >= 80000 ? '.' : localeconv()['decimal_point']; $this->setOutput($output ?: static::$defaultOutput); if (!$output && \is_string(static::$defaultOutput)) { diff --git a/vendor/symfony/var-dumper/Dumper/CliDumper.php b/vendor/symfony/var-dumper/Dumper/CliDumper.php index b3d9e25..e3861cd 100644 --- a/vendor/symfony/var-dumper/Dumper/CliDumper.php +++ b/vendor/symfony/var-dumper/Dumper/CliDumper.php @@ -83,7 +83,7 @@ class CliDumper extends AbstractDumper ]); } - $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l'; + $this->displayOptions['fileLinkFormat'] = \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format') ?: 'file://%f#L%l'; } /** diff --git a/vendor/symfony/var-dumper/Dumper/HtmlDumper.php b/vendor/symfony/var-dumper/Dumper/HtmlDumper.php index 7fe31ef..9b57f90 100644 --- a/vendor/symfony/var-dumper/Dumper/HtmlDumper.php +++ b/vendor/symfony/var-dumper/Dumper/HtmlDumper.php @@ -81,7 +81,7 @@ class HtmlDumper extends CliDumper { AbstractDumper::__construct($output, $charset, $flags); $this->dumpId = 'sf-dump-'.mt_rand(); - $this->displayOptions['fileLinkFormat'] = ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + $this->displayOptions['fileLinkFormat'] = \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); $this->styles = static::$themes['dark'] ?? self::$themes['dark']; } @@ -882,7 +882,7 @@ EOHTML } if ('const' === $style && isset($attr['value'])) { - $style .= sprintf(' title="%s"', esc(is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value']))); + $style .= sprintf(' title="%s"', esc(\is_scalar($attr['value']) ? $attr['value'] : json_encode($attr['value']))); } elseif ('public' === $style) { $style .= sprintf(' title="%s"', empty($attr['dynamic']) ? 'Public property' : 'Runtime added dynamic property'); } elseif ('str' === $style && 1 < $attr['length']) { diff --git a/vendor/topthink/framework/.gitignore b/vendor/topthink/framework/.gitignore index b267fba..b2fd3b9 100644 --- a/vendor/topthink/framework/.gitignore +++ b/vendor/topthink/framework/.gitignore @@ -4,4 +4,7 @@ composer.lock .DS_Store Thumbs.db /.idea -/.vscode \ No newline at end of file +/.vscode +/.settings +/.buildpath +/.project \ No newline at end of file diff --git a/vendor/topthink/framework/src/helper.php b/vendor/topthink/framework/src/helper.php index e436e14..caba0ae 100644 --- a/vendor/topthink/framework/src/helper.php +++ b/vendor/topthink/framework/src/helper.php @@ -58,10 +58,11 @@ if (!function_exists('abort')) { if (!function_exists('app')) { /** * 快速获取容器中的实例 支持依赖注入 - * @param string $name 类名或标识 默认获取当前应用实例 - * @param array $args 参数 - * @param bool $newInstance 是否每次创建新的实例 - * @return object|App + * @template T + * @param string|class-string $name 类名或标识 默认获取当前应用实例 + * @param array $args 参数 + * @param bool $newInstance 是否每次创建新的实例 + * @return T|object|App */ function app(string $name = '', array $args = [], bool $newInstance = false) { diff --git a/vendor/topthink/framework/src/think/App.php b/vendor/topthink/framework/src/think/App.php index 073a41a..b189cd9 100644 --- a/vendor/topthink/framework/src/think/App.php +++ b/vendor/topthink/framework/src/think/App.php @@ -39,7 +39,7 @@ use think\initializer\RegisterService; */ class App extends Container { - const VERSION = '6.0.12LTS'; + const VERSION = '6.0.13LTS'; /** * 应用调试模式 diff --git a/vendor/topthink/framework/src/think/Container.php b/vendor/topthink/framework/src/think/Container.php index e3a4341..60b4b35 100644 --- a/vendor/topthink/framework/src/think/Container.php +++ b/vendor/topthink/framework/src/think/Container.php @@ -108,11 +108,11 @@ class Container implements ContainerInterface, ArrayAccess, IteratorAggregate, C /** * 获取容器中的对象实例 不存在则创建 - * @access public - * @param string $abstract 类名或者标识 - * @param array|true $vars 变量 - * @param bool $newInstance 是否每次创建新的实例 - * @return object + * @template T + * @param string|class-string $abstract 类名或者标识 + * @param array $vars 变量 + * @param bool $newInstance 是否每次创建新的实例 + * @return T|object */ public static function pull(string $abstract, array $vars = [], bool $newInstance = false) { @@ -121,9 +121,9 @@ class Container implements ContainerInterface, ArrayAccess, IteratorAggregate, C /** * 获取容器中的对象实例 - * @access public - * @param string $abstract 类名或者标识 - * @return object + * @template T + * @param string|class-string $abstract 类名或者标识 + * @return T|object */ public function get($abstract) { @@ -232,11 +232,11 @@ class Container implements ContainerInterface, ArrayAccess, IteratorAggregate, C /** * 创建类的实例 已经存在则直接获取 - * @access public - * @param string $abstract 类名或者标识 - * @param array $vars 变量 - * @param bool $newInstance 是否每次创建新的实例 - * @return mixed + * @template T + * @param string|class-string $abstract 类名或者标识 + * @param array $vars 变量 + * @param bool $newInstance 是否每次创建新的实例 + * @return T|object */ public function make(string $abstract, array $vars = [], bool $newInstance = false) { diff --git a/vendor/topthink/framework/src/think/Lang.php b/vendor/topthink/framework/src/think/Lang.php index 0226f81..5f16c46 100644 --- a/vendor/topthink/framework/src/think/Lang.php +++ b/vendor/topthink/framework/src/think/Lang.php @@ -129,6 +129,8 @@ class Lang return; } + $this->setLangSet($langset); + // 加载系统语言包 $this->load([ $this->app->getThinkPath() . 'lang' . DIRECTORY_SEPARATOR . $langset . '.php', diff --git a/vendor/topthink/framework/src/think/Request.php b/vendor/topthink/framework/src/think/Request.php index fe9938d..99f4f80 100644 --- a/vendor/topthink/framework/src/think/Request.php +++ b/vendor/topthink/framework/src/think/Request.php @@ -1237,7 +1237,7 @@ class Request implements ArrayAccess * @access public * @param string $name header名称 * @param string $default 默认值 - * @return string|array + * @return string|array|null */ public function header(string $name = '', string $default = null) { @@ -1416,6 +1416,10 @@ class Request implements ArrayAccess foreach ($filters as $filter) { if (is_callable($filter)) { // 调用函数或者方法过滤 + if (is_null($value)) { + continue; + } + $value = call_user_func($filter, $value); } elseif (is_scalar($value)) { if (is_string($filter) && false !== strpos($filter, '/')) { @@ -1490,7 +1494,7 @@ class Request implements ArrayAccess if (is_int($key)) { $default = null; $key = $val; - if (!isset($data[$key])) { + if (!key_exists($key, $data)) { continue; } } else { diff --git a/vendor/topthink/framework/src/think/Route.php b/vendor/topthink/framework/src/think/Route.php index a3acf85..e45cb33 100644 --- a/vendor/topthink/framework/src/think/Route.php +++ b/vendor/topthink/framework/src/think/Route.php @@ -167,6 +167,8 @@ class Route } $this->config = array_merge($this->config, $this->app->config->get('route')); + + $this->init(); } protected function init() @@ -630,6 +632,18 @@ class Route return $this->rule($rule, $route, 'PATCH'); } + /** + * 注册HEAD路由 + * @access public + * @param string $rule 路由规则 + * @param mixed $route 路由地址 + * @return RuleItem + */ + public function head(string $rule, $route): RuleItem + { + return $this->rule($rule, $route, 'HEAD'); + } + /** * 注册OPTIONS路由 * @access public @@ -752,7 +766,6 @@ class Route { $this->request = $request; $this->host = $this->request->host(true); - $this->init(); if ($withRoute) { //加载路由 diff --git a/vendor/topthink/framework/src/think/cache/Driver.php b/vendor/topthink/framework/src/think/cache/Driver.php index 37ffbc9..7dc0d30 100644 --- a/vendor/topthink/framework/src/think/cache/Driver.php +++ b/vendor/topthink/framework/src/think/cache/Driver.php @@ -153,7 +153,9 @@ abstract class Driver implements CacheInterface, CacheHandlerInterface public function remember(string $name, $value, $expire = null) { if ($this->has($name)) { - return $this->get($name); + if (($hit = $this->get($name)) !== null) { + return $hit; + } } $time = time(); diff --git a/vendor/topthink/framework/src/think/console/output/driver/Console.php b/vendor/topthink/framework/src/think/console/output/driver/Console.php index 31bdf1f..3061f55 100644 --- a/vendor/topthink/framework/src/think/console/output/driver/Console.php +++ b/vendor/topthink/framework/src/think/console/output/driver/Console.php @@ -214,12 +214,12 @@ class Console /** * 获取终端模式 - * @return string x 或 null + * @return string x */ private function getMode() { if (!function_exists('proc_open')) { - return; + return ''; } $descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']]; @@ -234,7 +234,8 @@ class Console return $matches[2] . 'x' . $matches[1]; } } - return; + + return ''; } private function stringWidth(string $string): int diff --git a/vendor/topthink/framework/src/think/facade/Route.php b/vendor/topthink/framework/src/think/facade/Route.php index 5a5b955..37504ce 100644 --- a/vendor/topthink/framework/src/think/facade/Route.php +++ b/vendor/topthink/framework/src/think/facade/Route.php @@ -56,6 +56,7 @@ use think\route\Url as UrlBuild; * @method static RuleItem put(string $rule, mixed $route) 注册PUT路由 * @method static RuleItem delete(string $rule, mixed $route) 注册DELETE路由 * @method static RuleItem patch(string $rule, mixed $route) 注册PATCH路由 + * @method static RuleItem head(string $rule, mixed $route) 注册HEAD路由 * @method static RuleItem options(string $rule, mixed $route) 注册OPTIONS路由 * @method static Resource resource(string $rule, string $route) 注册资源路由 * @method static RuleItem view(string $rule, string $template = '', array $vars = []) 注册视图路由 diff --git a/vendor/topthink/framework/src/think/filesystem/driver/Local.php b/vendor/topthink/framework/src/think/filesystem/driver/Local.php index 31172d0..5749335 100644 --- a/vendor/topthink/framework/src/think/filesystem/driver/Local.php +++ b/vendor/topthink/framework/src/think/filesystem/driver/Local.php @@ -42,8 +42,15 @@ class Local extends Driver ); } + /** + * 获取文件访问地址 + * @param string $path 文件路径 + * @return string + */ public function url(string $path): string { + $path = str_replace('\\', '/', $path); + if (isset($this->config['url'])) { return $this->concatPathToUrl($this->config['url'], $path); } diff --git a/vendor/topthink/framework/src/think/response/Redirect.php b/vendor/topthink/framework/src/think/response/Redirect.php index 1f38764..ee067be 100644 --- a/vendor/topthink/framework/src/think/response/Redirect.php +++ b/vendor/topthink/framework/src/think/response/Redirect.php @@ -74,9 +74,9 @@ class Redirect extends Response * @access public * @return $this */ - public function remember() + public function remember($complete = false) { - $this->session->set('redirect_url', $this->request->url()); + $this->session->set('redirect_url', $this->request->url($complete)); return $this; } diff --git a/vendor/topthink/framework/src/think/route/Dispatch.php b/vendor/topthink/framework/src/think/route/Dispatch.php index 0599dc1..58666b5 100644 --- a/vendor/topthink/framework/src/think/route/Dispatch.php +++ b/vendor/topthink/framework/src/think/route/Dispatch.php @@ -96,7 +96,7 @@ abstract class Dispatch if ($data instanceof Response) { $response = $data; } elseif ($data instanceof ResponseInterface) { - $response = Response::create($data->getBody()->getContents(), 'html', $data->getStatusCode()); + $response = Response::create((string) $data->getBody(), 'html', $data->getStatusCode()); foreach ($data->getHeaders() as $header => $values) { $response->header([$header => implode(", ", $values)]); diff --git a/vendor/topthink/framework/src/tpl/think_exception.tpl b/vendor/topthink/framework/src/tpl/think_exception.tpl index 7766caf..6ea9677 100644 --- a/vendor/topthink/framework/src/tpl/think_exception.tpl +++ b/vendor/topthink/framework/src/tpl/think_exception.tpl @@ -492,7 +492,7 @@ if (!function_exists('echo_value')) { } })(); - $.getScript('//cdn.bootcss.com/prettify/r298/prettify.min.js', function(){ + $.getScript('//cdn.bootcdn.net/ajax/libs/prettify/r298/prettify.min.js', function(){ prettyPrint(); }); })(); diff --git a/vendor/topthink/think-orm/composer.json b/vendor/topthink/think-orm/composer.json index 5e86ac8..097d924 100644 --- a/vendor/topthink/think-orm/composer.json +++ b/vendor/topthink/think-orm/composer.json @@ -16,8 +16,8 @@ "php": ">=7.1.0", "ext-json": "*", "ext-pdo": "*", - "psr/simple-cache": "^1.0", - "psr/log": "~1.0", + "psr/simple-cache": "^1.0|^2.0", + "psr/log": "^1.0|^2.0", "topthink/think-helper":"^3.1" }, "require-dev": { diff --git a/vendor/topthink/think-orm/src/db/BaseQuery.php b/vendor/topthink/think-orm/src/db/BaseQuery.php index d472590..d05905c 100644 --- a/vendor/topthink/think-orm/src/db/BaseQuery.php +++ b/vendor/topthink/think-orm/src/db/BaseQuery.php @@ -628,7 +628,7 @@ abstract class BaseQuery if (!isset($total) && !$simple) { $options = $this->getOptions(); - unset($this->options['order'], $this->options['limit'], $this->options['page'], $this->options['field']); + unset($this->options['order'], $this->options['cache'], $this->options['limit'], $this->options['page'], $this->options['field']); $bind = $this->bind; $total = $this->count(); @@ -705,7 +705,7 @@ abstract class BaseQuery ->limit(1) ->find(); - $result = $data[$key]; + $result = $data[$key] ?? 0; if (is_numeric($result)) { $lastId = 'asc' == $sort ? ($result - 1) + ($page - 1) * $listRows : ($result + 1) - ($page - 1) * $listRows; diff --git a/vendor/topthink/think-orm/src/db/PDOConnection.php b/vendor/topthink/think-orm/src/db/PDOConnection.php index 77a0b01..1748d20 100644 --- a/vendor/topthink/think-orm/src/db/PDOConnection.php +++ b/vendor/topthink/think-orm/src/db/PDOConnection.php @@ -1274,7 +1274,7 @@ abstract class PDOConnection extends Connection $type = is_array($val) ? $val[1] : PDO::PARAM_STR; if (self::PARAM_FLOAT == $type || PDO::PARAM_STR == $type) { - $value = '\'' . addcslashes($value, "'") . '\''; + $value = '\'' . addslashes($value) . '\''; } elseif (PDO::PARAM_INT == $type && '' === $value) { $value = '0'; } diff --git a/vendor/topthink/think-orm/src/db/builder/Oracle.php b/vendor/topthink/think-orm/src/db/builder/Oracle.php index 77ad3c8..38feb5d 100644 --- a/vendor/topthink/think-orm/src/db/builder/Oracle.php +++ b/vendor/topthink/think-orm/src/db/builder/Oracle.php @@ -12,6 +12,8 @@ namespace think\db\builder; use think\db\Builder; use think\db\Query; +use think\db\exception\DbException as Exception; +use think\db\Raw; /** * Oracle数据库驱动 @@ -64,19 +66,51 @@ class Oracle extends Builder /** * 字段和表名处理 * @access public - * @param Query $query 查询对象 - * @param string $key - * @param string $strict + * @param Query $query 查询对象 + * @param string $key + * @param bool $strict * @return string + * @throws Exception */ public function parseKey(Query $query, $key, bool $strict = false): string { + if (is_int($key)) { + return (string) $key; + } elseif ($key instanceof Raw) { + return $this->parseRaw($query, $key); + } + $key = trim($key); if (strpos($key, '->') && false === strpos($key, '(')) { // JSON字段支持 [$field, $name] = explode($key, '->'); $key = $field . '."' . $name . '"'; + } elseif (strpos($key, '.') && !preg_match('/[,\'\"\(\)\[\s]/', $key)) { + [$table, $key] = explode('.', $key, 2); + + $alias = $query->getOptions('alias'); + + if ('__TABLE__' == $table) { + $table = $query->getOptions('table'); + $table = is_array($table) ? array_shift($table) : $table; + } + + if (isset($alias[$table])) { + $table = $alias[$table]; + } + } + + if ($strict && !preg_match('/^[\w\.\*]+$/', $key)) { + throw new Exception('not support data:' . $key); + } + + if ('*' != $key && !preg_match('/[,\'\"\*\(\)\[.\s]/', $key)) { + $key = '"' . $key . '"'; + } + + if (isset($table)) { + $key = '"' . $table . '".' . $key; } return $key; diff --git a/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php b/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php index dabfb92..0eab363 100644 --- a/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php +++ b/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php @@ -12,6 +12,7 @@ declare (strict_types = 1); namespace think\db\concern; +use think\db\exception\DbException; use think\db\Raw; /** @@ -42,6 +43,11 @@ trait AggregateQuery { if (!empty($this->options['group'])) { // 支持GROUP + + if (!preg_match('/^[\w\.\*]+$/', $field)) { + throw new DbException('not support data:' . $field); + } + $options = $this->getOptions(); $subSql = $this->options($options) ->field('count(' . $field . ') AS think_count') diff --git a/vendor/topthink/think-orm/src/db/connector/Oracle.php b/vendor/topthink/think-orm/src/db/connector/Oracle.php index 236d8bf..c8e957a 100644 --- a/vendor/topthink/think-orm/src/db/connector/Oracle.php +++ b/vendor/topthink/think-orm/src/db/connector/Oracle.php @@ -51,7 +51,7 @@ class Oracle extends PDOConnection public function getFields(string $tableName): array { [$tableName] = explode(' ', $tableName); - $sql = "select a.column_name,data_type,DECODE (nullable, 'Y', 0, 1) notnull,data_default, DECODE (A .column_name,b.column_name,1,0) pk from all_tab_columns a,(select column_name from all_constraints c, all_cons_columns col where c.constraint_name = col.constraint_name and c.constraint_type = 'P' and c.table_name = '" . strtoupper($tableName) . "' ) b where table_name = '" . strtoupper($tableName) . "' and a.column_name = b.column_name (+)"; + $sql = "select a.column_name,data_type,DECODE (nullable, 'Y', 0, 1) notnull,data_default, DECODE (A .column_name,b.column_name,1,0) pk from all_tab_columns a,(select column_name from all_constraints c, all_cons_columns col where c.constraint_name = col.constraint_name and c.constraint_type = 'P' and c.table_name = '" . $tableName . "' ) b where table_name = '" . $tableName . "' and a.column_name = b.column_name (+)"; $pdo = $this->getPDOStatement($sql); $result = $pdo->fetchAll(PDO::FETCH_ASSOC); @@ -98,16 +98,18 @@ class Oracle extends PDOConnection /** * 获取最近插入的ID * @access public - * @param BaseQuery $query 查询对象 - * @param string $sequence 自增序列名 + * @param BaseQuery $query 查询对象 + * @param string|null $sequence 自增序列名 * @return mixed */ public function getLastInsID(BaseQuery $query, string $sequence = null) { - $pdo = $this->linkID->query("select {$sequence}.currval as id from dual"); - $result = $pdo->fetchColumn(); + if(!is_null($sequence)) { + $pdo = $this->linkID->query("select {$sequence}.currval as id from dual"); + $result = $pdo->fetchColumn(); + } - return $result; + return $result ?? null; } protected function supportSavepoint(): bool diff --git a/vendor/topthink/think-orm/src/db/connector/Sqlsrv.php b/vendor/topthink/think-orm/src/db/connector/Sqlsrv.php index 10d944f..aee3343 100644 --- a/vendor/topthink/think-orm/src/db/connector/Sqlsrv.php +++ b/vendor/topthink/think-orm/src/db/connector/Sqlsrv.php @@ -44,6 +44,10 @@ class Sqlsrv extends PDOConnection $dsn .= ',' . $config['hostport']; } + if (!empty($config['trust_server_certificate'])) { + $dsn .= ';TrustServerCertificate=' . $config['trust_server_certificate']; + } + return $dsn; } diff --git a/vendor/topthink/think-orm/src/model/Collection.php b/vendor/topthink/think-orm/src/model/Collection.php index 9d31e20..079e856 100644 --- a/vendor/topthink/think-orm/src/model/Collection.php +++ b/vendor/topthink/think-orm/src/model/Collection.php @@ -81,12 +81,13 @@ class Collection extends BaseCollection * 设置需要隐藏的输出属性 * @access public * @param array $hidden 属性列表 + * @param bool $merge 是否合并 * @return $this */ - public function hidden(array $hidden) + public function hidden(array $hidden, bool $merge = false) { - $this->each(function (Model $model) use ($hidden) { - $model->hidden($hidden); + $this->each(function (Model $model) use ($hidden, $merge) { + $model->hidden($hidden, $merge); }); return $this; @@ -96,12 +97,13 @@ class Collection extends BaseCollection * 设置需要输出的属性 * @access public * @param array $visible + * @param bool $merge 是否合并 * @return $this */ - public function visible(array $visible) + public function visible(array $visible, bool $merge = false) { - $this->each(function (Model $model) use ($visible) { - $model->visible($visible); + $this->each(function (Model $model) use ($visible, $merge) { + $model->visible($visible, $merge); }); return $this; @@ -111,12 +113,13 @@ class Collection extends BaseCollection * 设置需要追加的输出属性 * @access public * @param array $append 属性列表 + * @param bool $merge 是否合并 * @return $this */ - public function append(array $append) + public function append(array $append, bool $merge = false) { - $this->each(function (Model $model) use ($append) { - $model->append($append); + $this->each(function (Model $model) use ($append, $merge) { + $model->append($append, $merge); }); return $this; diff --git a/vendor/topthink/think-orm/src/model/Pivot.php b/vendor/topthink/think-orm/src/model/Pivot.php index 893c01b..ac16d9e 100644 --- a/vendor/topthink/think-orm/src/model/Pivot.php +++ b/vendor/topthink/think-orm/src/model/Pivot.php @@ -35,9 +35,9 @@ class Pivot extends Model /** * 架构函数 * @access public - * @param array $data 数据 - * @param Model $parent 上级模型 - * @param string $table 中间数据表名 + * @param array $data 数据 + * @param Model|null $parent 上级模型 + * @param string $table 中间数据表名 */ public function __construct(array $data = [], Model $parent = null, string $table = '') { @@ -50,4 +50,21 @@ class Pivot extends Model parent::__construct($data); } + /** + * 创建新的模型实例 + * @access public + * @param array $data 数据 + * @param mixed $where 更新条件 + * @param array $options 参数 + * @return Model + */ + public function newInstance(array $data = [], $where = null, array $options = []): Model + { + $model = parent::newInstance($data, $where, $options); + + $model->parent = $this->parent; + $model->name = $this->name; + + return $model; + } } diff --git a/vendor/topthink/think-orm/src/model/concern/Conversion.php b/vendor/topthink/think-orm/src/model/concern/Conversion.php index 22d6256..b584ba9 100644 --- a/vendor/topthink/think-orm/src/model/concern/Conversion.php +++ b/vendor/topthink/think-orm/src/model/concern/Conversion.php @@ -82,11 +82,16 @@ trait Conversion * 设置需要附加的输出属性 * @access public * @param array $append 属性列表 + * @param bool $merge 是否合并 * @return $this */ - public function append(array $append = []) + public function append(array $append = [], bool $merge = false) { - $this->append = $append; + if ($merge) { + $this->append = array_merge($this->append, $append); + } else { + $this->append = $append; + } return $this; } @@ -147,11 +152,16 @@ trait Conversion * 设置需要隐藏的输出属性 * @access public * @param array $hidden 属性列表 + * @param bool $merge 是否合并 * @return $this */ - public function hidden(array $hidden = []) + public function hidden(array $hidden = [], bool $merge = false) { - $this->hidden = $hidden; + if ($merge) { + $this->hidden = array_merge($this->hidden, $hidden); + } else { + $this->hidden = $hidden; + } return $this; } @@ -160,11 +170,16 @@ trait Conversion * 设置需要输出的属性 * @access public * @param array $visible + * @param bool $merge 是否合并 * @return $this */ - public function visible(array $visible = []) + public function visible(array $visible = [], bool $merge = false) { - $this->visible = $visible; + if ($merge) { + $this->visible = array_merge($this->visible, $visible); + } else { + $this->visible = $visible; + } return $this; } diff --git a/vendor/topthink/think-orm/src/model/relation/BelongsTo.php b/vendor/topthink/think-orm/src/model/relation/BelongsTo.php index 0802b11..dd54f52 100644 --- a/vendor/topthink/think-orm/src/model/relation/BelongsTo.php +++ b/vendor/topthink/think-orm/src/model/relation/BelongsTo.php @@ -241,6 +241,7 @@ class BelongsTo extends OneToOne if (!empty($this->bindAttr)) { // 绑定关联属性 $this->bindAttr($result, $relationModel); + $result->hidden([$relation]); } } } @@ -282,6 +283,7 @@ class BelongsTo extends OneToOne if (!empty($this->bindAttr)) { // 绑定关联属性 $this->bindAttr($result, $relationModel); + $result->hidden([$relation]); } } diff --git a/vendor/topthink/think-orm/src/model/relation/BelongsToMany.php b/vendor/topthink/think-orm/src/model/relation/BelongsToMany.php index 9890906..6049f01 100644 --- a/vendor/topthink/think-orm/src/model/relation/BelongsToMany.php +++ b/vendor/topthink/think-orm/src/model/relation/BelongsToMany.php @@ -157,7 +157,12 @@ class BelongsToMany extends Relation } } - $result->setRelation($this->pivotDataName, $this->newPivot($pivot)); + $pivotData = $this->pivot->newInstance($pivot, [ + [$this->localKey, '=', $this->parent->getKey(), null], + [$this->foreignKey, '=', $result->getKey(), null], + ]); + + $result->setRelation($this->pivotDataName, $pivotData); return $pivot; } diff --git a/vendor/topthink/think-orm/src/model/relation/HasOne.php b/vendor/topthink/think-orm/src/model/relation/HasOne.php index 269f0d7..43f220c 100644 --- a/vendor/topthink/think-orm/src/model/relation/HasOne.php +++ b/vendor/topthink/think-orm/src/model/relation/HasOne.php @@ -240,6 +240,7 @@ class HasOne extends OneToOne if (!empty($this->bindAttr)) { // 绑定关联属性 $this->bindAttr($result, $relationModel); + $result->hidden([$relation]); } } } @@ -281,6 +282,7 @@ class HasOne extends OneToOne if (!empty($this->bindAttr)) { // 绑定关联属性 $this->bindAttr($result, $relationModel); + $result->hidden([$relation]); } } diff --git a/vendor/topthink/think-orm/src/model/relation/MorphMany.php b/vendor/topthink/think-orm/src/model/relation/MorphMany.php index 82910cb..39209ae 100644 --- a/vendor/topthink/think-orm/src/model/relation/MorphMany.php +++ b/vendor/topthink/think-orm/src/model/relation/MorphMany.php @@ -30,6 +30,7 @@ class MorphMany extends Relation * @var string */ protected $morphKey; + /** * 多态字段名 * @var string @@ -331,6 +332,33 @@ class MorphMany extends Relation return empty($result) ? false : $result; } + /** + * 获取多态关联外键 + * @return string + */ + public function getMorphKey() + { + return $this->morphKey; + } + + /** + * 获取多态字段名 + * @return string + */ + public function getMorphType() + { + return $this->morphType; + } + + /** + * 获取多态类型 + * @return string + */ + public function getType() + { + return $this->type; + } + /** * 执行基础查询(仅执行一次) * @access protected diff --git a/vendor/topthink/think-orm/src/model/relation/MorphTo.php b/vendor/topthink/think-orm/src/model/relation/MorphTo.php index 986380e..f53fe4f 100644 --- a/vendor/topthink/think-orm/src/model/relation/MorphTo.php +++ b/vendor/topthink/think-orm/src/model/relation/MorphTo.php @@ -208,6 +208,9 @@ class MorphTo extends Relation // 多态类型映射 $model = $this->parseModel($key); $obj = new $model; + if (!\is_null($closure)) { + $obj = $closure($obj); + } $pk = $obj->getPk(); $list = $obj->with($subRelation) ->cache($cache[0] ?? false, $cache[1] ?? null, $cache[2] ?? null) diff --git a/vendor/topthink/think-orm/src/model/relation/MorphToMany.php b/vendor/topthink/think-orm/src/model/relation/MorphToMany.php index 32f853f..c566488 100644 --- a/vendor/topthink/think-orm/src/model/relation/MorphToMany.php +++ b/vendor/topthink/think-orm/src/model/relation/MorphToMany.php @@ -24,6 +24,13 @@ use think\model\Pivot; class MorphToMany extends BelongsToMany { + /** + * 多态关系的模型名映射别名的数组 + * + * @var array + */ + protected static $morphMap = []; + /** * 多态字段名 * @var string @@ -58,6 +65,9 @@ class MorphToMany extends BelongsToMany $this->morphType = $morphType; $this->inverse = $inverse; $this->morphClass = $inverse ? $model : get_class($parent); + if (isset(static::$morphMap[$this->morphClass])) { + $this->morphClass = static::$morphMap[$this->morphClass]; + } $foreignKey = $inverse ? $morphKey : $localKey; $localKey = $inverse ? $localKey : $morphKey; @@ -460,4 +470,21 @@ class MorphToMany extends BelongsToMany } } + /** + * 设置或获取多态关系的模型名映射别名的数组 + * + * @param array|null $map + * @param bool $merge + * @return array + */ + public static function morphMap(array $map = null, $merge = true): array + { + if (is_array($map)) { + static::$morphMap = $merge && static::$morphMap + ? $map + static::$morphMap : $map; + } + + return static::$morphMap; + } + } diff --git a/vendor/topthink/think-orm/src/model/relation/OneToOne.php b/vendor/topthink/think-orm/src/model/relation/OneToOne.php index d47d7f3..ba51753 100644 --- a/vendor/topthink/think-orm/src/model/relation/OneToOne.php +++ b/vendor/topthink/think-orm/src/model/relation/OneToOne.php @@ -186,18 +186,30 @@ abstract class OneToOne extends Relation * @return Model|false */ public function save($data, bool $replace = true) + { + $model = $this->make(); + + return $model->replace($replace)->save($data) ? $model : false; + } + + /** + * 创建关联对象实例 + * @param array|Model $data + * @return Model + */ + public function make($data = []): Model { if ($data instanceof Model) { $data = $data->getData(); } - $model = new $this->model; // 保存关联表数据 $data[$this->foreignKey] = $this->parent->{$this->localKey}; - return $model->replace($replace)->save($data) ? $model : false; + return new $this->model($data); } + /** * 绑定关联表的属性到父模型属性 * @access public