init
This commit is contained in:
commit
a7683eaf40
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/.idea
|
||||
/.vscode
|
||||
/vendor
|
||||
*.log
|
||||
.env
|
||||
/tests/tmp
|
||||
/tests/.phpunit.result.cache
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 walkor<walkor@workerman.net> and contributors (see https://github.com/walkor/webman/contributors)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
59
README.md
Normal file
59
README.md
Normal file
@ -0,0 +1,59 @@
|
||||
<div style="padding:18px;max-width: 1024px;margin:0 auto;background-color:#fff;color:#333">
|
||||
<h1>webman</h1>
|
||||
|
||||
基于<a href="https://www.workerman.net" target="__blank">workerman</a>开发的超高性能PHP框架
|
||||
|
||||
|
||||
<h1>学习</h1>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/webman" target="__blank">主页 / Home page</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/doc/webman" target="__blank">文档 / Document</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/doc/webman/install.html" target="__blank">安装 / Install</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/questions" target="__blank">问答 / Questions</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/apps" target="__blank">市场 / Apps</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/sponsor" target="__blank">赞助 / Sponsors</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.workerman.net/doc/webman/thanks.html" target="__blank">致谢 / Thanks</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div style="float:left;padding-bottom:30px;">
|
||||
|
||||
<h1>赞助商</h1>
|
||||
|
||||
<h4>特别赞助</h4>
|
||||
<a href="https://www.crmeb.com/?form=workerman" target="__blank">
|
||||
<img src="https://www.workerman.net/img/sponsors/6429/20230719111500.svg" width="200">
|
||||
</a>
|
||||
|
||||
<h4>铂金赞助</h4>
|
||||
<a href="https://www.fadetask.com/?from=workerman" target="__blank"><img src="https://www.workerman.net/img/sponsors/1/20230719084316.png" width="200"></a>
|
||||
<a href="https://www.yilianyun.net/?from=workerman" target="__blank" style="margin-left:20px;"><img src="https://www.workerman.net/img/sponsors/6218/20230720114049.png" width="200"></a>
|
||||
|
||||
<h4>金牌赞助</h4>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div style="clear: both">
|
||||
<h1>LICENSE</h1>
|
||||
The webman is open-sourced software licensed under the MIT.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
123
app/Pusher.php
Normal file
123
app/Pusher.php
Normal file
@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace app;
|
||||
|
||||
use Workerman\Connection\TcpConnection;
|
||||
use IFlytek\Xfyun\Speech\ChatClient;
|
||||
use WebSocket\Client;
|
||||
use Workerman\Connection\AsyncTcpConnection;
|
||||
|
||||
class Pusher
|
||||
{
|
||||
private $app_id = '2eda6c2e';
|
||||
|
||||
private $api_key = '12ec1f9d113932575fc4b114a2f60ffd';
|
||||
|
||||
private $api_secret = 'MDEyMzE5YTc5YmQ5NjMwOTU1MWY4N2Y2';
|
||||
|
||||
public function onConnect(TcpConnection $connection)
|
||||
{
|
||||
echo "onConnect\n";
|
||||
}
|
||||
|
||||
public function onWebSocketConnect(TcpConnection $connection, $http_buffer)
|
||||
{
|
||||
echo "onWebSocketConnect\n";
|
||||
}
|
||||
|
||||
public function onMessage(TcpConnection $connection, $data)
|
||||
{
|
||||
if ($data != '') {
|
||||
$uri = $this->assembleAuthUrl('ws://spark-api.xf-yun.com/v2.1/chat');
|
||||
$con = new AsyncTcpConnection($uri);
|
||||
$con->onWebSocketConnect = function (AsyncTcpConnection $con,$data) {
|
||||
$res = $this->getBody($this->app_id,$data);
|
||||
$con->send($res);
|
||||
};
|
||||
// $con->onMessage = function (TcpConnection $connection, $res) {
|
||||
// // var_dump($res);
|
||||
// // $con->send($res);
|
||||
// $connection->send($res);
|
||||
|
||||
// };
|
||||
$con->connect();
|
||||
}
|
||||
}
|
||||
|
||||
public function onClose(TcpConnection $connection)
|
||||
{
|
||||
echo "onClose\n";
|
||||
}
|
||||
|
||||
function getBody($appid, $question)
|
||||
{
|
||||
$header = array(
|
||||
"app_id" => $appid,
|
||||
"uid" => "1"
|
||||
);
|
||||
|
||||
$parameter = array(
|
||||
"chat" => array(
|
||||
"domain" => "generalv2",
|
||||
"temperature" => 0.5,
|
||||
"max_tokens" => 1024
|
||||
)
|
||||
);
|
||||
|
||||
$payload = array(
|
||||
"message" => array(
|
||||
"text" => array(
|
||||
array("role" => "user", "content" => $question)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$json_string = json_encode(array(
|
||||
"header" => $header,
|
||||
"parameter" => $parameter,
|
||||
"payload" => $payload
|
||||
));
|
||||
|
||||
return $json_string;
|
||||
}
|
||||
|
||||
function assembleAuthUrl($addr, $method = 'GET')
|
||||
{
|
||||
$apiKey = $this->api_key;
|
||||
$apiSecret = $this->api_secret;
|
||||
if ($apiKey == "" && $apiSecret == "") { // 不鉴权
|
||||
return $addr;
|
||||
}
|
||||
|
||||
$ul = parse_url($addr); // 解析地址
|
||||
if ($ul === false) { // 地址不对,也不鉴权
|
||||
return $addr;
|
||||
}
|
||||
// // $date = date(DATE_RFC1123); // 获取当前时间并格式化为RFC1123格式的字符串
|
||||
$timestamp = time();
|
||||
$rfc1123_format = gmdate("D, d M Y H:i:s \G\M\T", $timestamp);
|
||||
// $rfc1123_format = "Mon, 31 Jul 2023 08:24:03 GMT";
|
||||
|
||||
// 参与签名的字段 host, date, request-line
|
||||
$signString = array("host: " . $ul["host"], "date: " . $rfc1123_format, $method . " " . $ul["path"] . " HTTP/1.1");
|
||||
// 对签名字符串进行排序,确保顺序一致
|
||||
// ksort($signString);
|
||||
// 将签名字符串拼接成一个字符串
|
||||
$sgin = implode("\n", $signString);
|
||||
|
||||
// 对签名字符串进行HMAC-SHA256加密,得到签名结果
|
||||
$sha = hash_hmac('sha256', $sgin, $apiSecret, true);
|
||||
|
||||
$signature_sha_base64 = base64_encode($sha);
|
||||
|
||||
// 将API密钥、算法、头部信息和签名结果拼接成一个授权URL
|
||||
$authUrl = "api_key=\"$apiKey\",algorithm=\"hmac-sha256\",headers=\"host date request-line\",signature=\"$signature_sha_base64\"";
|
||||
// 对授权URL进行Base64编码,并添加到原始地址后面作为查询参数
|
||||
$authAddr = $addr . '?' . http_build_query(array(
|
||||
'host' => $ul['host'],
|
||||
'date' => $rfc1123_format,
|
||||
'authorization' => base64_encode($authUrl),
|
||||
));
|
||||
return $authAddr;
|
||||
}
|
||||
}
|
29
app/controller/IndexController.php
Normal file
29
app/controller/IndexController.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace app\controller;
|
||||
|
||||
use support\Request;
|
||||
use Workerman\Protocols\Websocket;
|
||||
|
||||
class IndexController
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
static $readme;
|
||||
if (!$readme) {
|
||||
$readme = file_get_contents(base_path('README.md'));
|
||||
}
|
||||
return $readme;
|
||||
}
|
||||
|
||||
public function view(Request $request)
|
||||
{
|
||||
return view('index/view', ['name' => 'webman']);
|
||||
}
|
||||
|
||||
public function json(Request $request)
|
||||
{
|
||||
return json(['code' => 0, 'msg' => 'ok']);
|
||||
}
|
||||
|
||||
}
|
41
app/extend/IFlytek/Xfyun/Core/Config/ConfigInterface.php
Normal file
41
app/extend/IFlytek/Xfyun/Core/Config/ConfigInterface.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Core\Config;
|
||||
|
||||
/**
|
||||
* 配置类接口
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
interface ConfigInterface
|
||||
{
|
||||
/**
|
||||
* 返回配置内容的json形式
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toJson();
|
||||
|
||||
/**
|
||||
* 返回配置内容的数组形式
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray();
|
||||
}
|
53
app/extend/IFlytek/Xfyun/Core/Handler/Guzzle7HttpHandler.php
Normal file
53
app/extend/IFlytek/Xfyun/Core/Handler/Guzzle7HttpHandler.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Core\Handler;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
/**
|
||||
* GuzzleHttp-7处理类
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class Guzzle7HttpHandler{
|
||||
/**
|
||||
* @var ClientInterface
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* @param ClientInterface $client
|
||||
*/
|
||||
public function __construct(ClientInterface $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* 接收Psr-7的request对象和请求参数,返回Psr-7的response对象
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @param array $options
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function __invoke(RequestInterface $request, array $options = [])
|
||||
{
|
||||
return $this->client->send($request, $options);
|
||||
}
|
||||
}
|
45
app/extend/IFlytek/Xfyun/Core/Handler/HttpHandlerFactory.php
Normal file
45
app/extend/IFlytek/Xfyun/Core/Handler/HttpHandlerFactory.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Core\Handler;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\ClientInterface;
|
||||
|
||||
/**
|
||||
* HttpHandler工厂类
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class HttpHandlerFactory
|
||||
{
|
||||
/**
|
||||
* 根据安装的GuzzleHttp版本获取默认的处理类
|
||||
*
|
||||
* @param ClientInterface $client
|
||||
* @return Guzzle6HttpHandler|Guzzle7HttpHandler
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function build(ClientInterface $client = null)
|
||||
{
|
||||
$client = $client ?: new Client();
|
||||
|
||||
return new Guzzle7HttpHandler($client);
|
||||
|
||||
}
|
||||
}
|
126
app/extend/IFlytek/Xfyun/Core/Handler/WsHandler.php
Normal file
126
app/extend/IFlytek/Xfyun/Core/Handler/WsHandler.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Core\Handler;
|
||||
|
||||
use IFlytek\Xfyun\Core\Traits\JsonTrait;
|
||||
use WebSocket\Client;
|
||||
use WebSocket\Exception;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use Psr\Log\{LoggerAwareInterface, LoggerInterface, NullLogger};
|
||||
|
||||
/**
|
||||
* WebSocket处理类
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class WsHandler implements LoggerAwareInterface
|
||||
{
|
||||
use JsonTrait;
|
||||
|
||||
/**
|
||||
* @var WebSocket\Client ws client
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* @var string 发送的字符串
|
||||
*/
|
||||
private $input;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface or null 日志处理
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
public function __construct($uri, $input, $timeout = 300, $logger = null)
|
||||
{
|
||||
$this->client = new Client($uri);
|
||||
$this->client->setTimeout($timeout);
|
||||
$this->input = $input;
|
||||
$this->logger = $logger ?: new NullLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送并等待获取返回
|
||||
*
|
||||
* 这是一个同步阻塞的过程,调用将持续到结果返回或者出现超时
|
||||
*/
|
||||
public function sendAndReceive()
|
||||
{
|
||||
$result = '';
|
||||
try {
|
||||
$this->logger->info("Start to send data, input: {$this->input}");
|
||||
$this->client->send($this->input);
|
||||
$printSid = true;
|
||||
while (true) {
|
||||
$message = $this->jsonDecode($this->client->receive());
|
||||
if ($message->code !== 0) {
|
||||
throw new \Exception(json_encode($message));
|
||||
}
|
||||
if ($printSid) {
|
||||
$this->logger->info("Receiving data, sid-[{$message->sid}]");
|
||||
$printSid = false;
|
||||
}
|
||||
switch ($message->data->status) {
|
||||
case 1:
|
||||
$result .= base64_decode($message->data->audio);
|
||||
break;
|
||||
case 2:
|
||||
$result .= base64_decode($message->data->audio);
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
$this->logger->info("Receive data successfully, total length: " . strlen($result));
|
||||
return new Response(200, [], $result);
|
||||
} catch (Exception $ex) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
public function send($message = null)
|
||||
{
|
||||
try {
|
||||
if (empty($message)) {
|
||||
if (!empty($this->input)) {
|
||||
$message = $this->input;
|
||||
} else {
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
return $this->client->send($message);
|
||||
} catch (Exception $ex) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
public function receive()
|
||||
{
|
||||
try {
|
||||
return $this->client->receive();
|
||||
} catch (Exception $ex) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
public function setLogger(LoggerInterface $logger = null)
|
||||
{
|
||||
$this->logger = $logger ?: new NullLogger();
|
||||
}
|
||||
|
||||
}
|
163
app/extend/IFlytek/Xfyun/Core/HttpClient.php
Normal file
163
app/extend/IFlytek/Xfyun/Core/HttpClient.php
Normal file
@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Core;
|
||||
|
||||
/**
|
||||
* Http客户端
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
|
||||
use Exception;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use IFlytek\Xfyun\Core\Handler\Guzzle7HttpHandler;
|
||||
use IFlytek\Xfyun\Core\Traits\SignTrait;
|
||||
use IFlytek\Xfyun\Core\Traits\DecideRetryTrait;
|
||||
use IFlytek\Xfyun\Core\Handler\HttpHandlerFactory;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use GuzzleHttp\Psr7\Utils;
|
||||
|
||||
class HttpClient
|
||||
{
|
||||
use SignTrait;
|
||||
use DecideRetryTrait;
|
||||
|
||||
const MAX_DELAY_MICROSECONDS = 60000000;
|
||||
|
||||
/**
|
||||
* @var Guzzle7HttpHandler
|
||||
*/
|
||||
private $httpHandler;
|
||||
|
||||
/**
|
||||
* @var array 要添加的头部信息
|
||||
*/
|
||||
private $httpHeaders;
|
||||
|
||||
/**
|
||||
* @var int 超时时间
|
||||
*/
|
||||
private $requestTimeout;
|
||||
|
||||
/**
|
||||
* @var int 重试次数
|
||||
*/
|
||||
private $retries;
|
||||
|
||||
/**
|
||||
* @var int 重试次数
|
||||
*/
|
||||
private $decideRetryFunction;
|
||||
|
||||
/**
|
||||
* @var int 重试次数
|
||||
*/
|
||||
private $delayFunction;
|
||||
|
||||
/**
|
||||
* @var int 重试次数
|
||||
*/
|
||||
private $calcDelayFunction;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$config += [
|
||||
'httpHandler' => null,
|
||||
'httpHeaders' => [],
|
||||
'requestTimeout' => 3000,
|
||||
'retries' => 3,
|
||||
'decideRetryFunction' => null,
|
||||
'delayFunction' => null,
|
||||
'calcDelayFunction' => null
|
||||
];
|
||||
$this->httpHandler = $config['httpHandler'] ?: HttpHandlerFactory::build();
|
||||
$this->httpHeaders = $config['httpHeaders'];
|
||||
$this->retries = $config['retries'];
|
||||
$this->decideRetryFunction = $config['decideRetryFunction'] ?: $this->getDecideRetryFunction();
|
||||
$this->calcDelayFunction = $config['calcDelayFunction'] ?: [$this, 'calculateDelay'];
|
||||
$this->delayFunction = $config['delayFunction'] ?: static function ($delay) {
|
||||
usleep($delay);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送请求,并接受返回
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @param array $options 请求的配置参数
|
||||
* @return Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function sendAndReceive(RequestInterface $request, array $options = [])
|
||||
{
|
||||
try {
|
||||
$delayFunction = $this->delayFunction;
|
||||
$calcDelayFunction = $this->calcDelayFunction;
|
||||
$retryAttempt = 0;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
return call_user_func_array($this->httpHandler, [$this->applyHeaders($request), $options]);
|
||||
} catch (Exception $exception) {
|
||||
if ($this->decideRetryFunction) {
|
||||
if (!call_user_func($this->decideRetryFunction, $exception)) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
if ($retryAttempt >= $this->retries) {
|
||||
break;
|
||||
}
|
||||
|
||||
$delayFunction($calcDelayFunction($retryAttempt));
|
||||
$retryAttempt++;
|
||||
}
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
} catch (Exception $ex) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将头部信息添加到请求对象中
|
||||
*
|
||||
* @param $request 请求对象
|
||||
* @return RequestInterface
|
||||
*/
|
||||
private function applyHeaders($request)
|
||||
{
|
||||
return Utils::modifyRequest($request, ['set_headers' => $this->httpHeaders]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据重试次数计算下次重试延迟时间
|
||||
*
|
||||
* @param int $attempt 重试次数
|
||||
* @return int
|
||||
*/
|
||||
public static function calculateDelay($attempt)
|
||||
{
|
||||
return min(
|
||||
mt_rand(0, 1000000) + (pow(2, $attempt) * 1000000),
|
||||
self::MAX_DELAY_MICROSECONDS
|
||||
);
|
||||
}
|
||||
}
|
45
app/extend/IFlytek/Xfyun/Core/Traits/ArrayTrait.php
Normal file
45
app/extend/IFlytek/Xfyun/Core/Traits/ArrayTrait.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Core\Traits;
|
||||
|
||||
/**
|
||||
* 数组处理
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
trait ArrayTrait
|
||||
{
|
||||
/**
|
||||
* 递归移除数组中的null项
|
||||
*
|
||||
* @param array $array
|
||||
* @return array
|
||||
*/
|
||||
private static function removeNull($array)
|
||||
{
|
||||
foreach ($array as $key => $item) {
|
||||
if (is_array($item)) {
|
||||
$array[$key] = self::removeNull($item);
|
||||
} else if (is_null($item)) {
|
||||
unset($array[$key]);
|
||||
}
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
}
|
96
app/extend/IFlytek/Xfyun/Core/Traits/DecideRetryTrait.php
Normal file
96
app/extend/IFlytek/Xfyun/Core/Traits/DecideRetryTrait.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Core\Traits;
|
||||
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
|
||||
/**
|
||||
* 提供一个方法,决定是否进行重试
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
trait DecideRetryTrait
|
||||
{
|
||||
use JsonTrait;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $httpRetryCodes = [
|
||||
500,
|
||||
502,
|
||||
503
|
||||
];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $httpRetryMessages = [
|
||||
'retry later'
|
||||
];
|
||||
|
||||
/**
|
||||
* 返回一个callable变量,作用是决定是否重试
|
||||
*
|
||||
* @param bool $shouldRetryMessages 是否要根据message决定重试与否
|
||||
* @return callable
|
||||
*/
|
||||
private function getDecideRetryFunction($shouldRetryMessages = true)
|
||||
{
|
||||
$httpRetryCodes = $this->httpRetryCodes;
|
||||
$httpRetryMessages = $this->httpRetryMessages;
|
||||
|
||||
return function (\Exception $ex) use ($httpRetryCodes, $httpRetryMessages, $shouldRetryMessages) {
|
||||
$statusCode = $ex->getCode();
|
||||
|
||||
if (in_array($statusCode, $httpRetryCodes)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$shouldRetryMessages) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$message = ($ex instanceof RequestException && $ex->hasResponse())
|
||||
? (string) $ex->getResponse()->getBody()
|
||||
: $ex->getMessage();
|
||||
|
||||
try {
|
||||
$message = $this->jsonDecode(
|
||||
$message,
|
||||
true
|
||||
);
|
||||
} catch (\InvalidArgumentException $ex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($message['errors'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($message['errors'] as $error) {
|
||||
if (in_array($error['reason'], $httpRetryMessages)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
68
app/extend/IFlytek/Xfyun/Core/Traits/JsonTrait.php
Normal file
68
app/extend/IFlytek/Xfyun/Core/Traits/JsonTrait.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace Iflytek\Xfyun\Core\Traits;
|
||||
|
||||
/**
|
||||
* 提供对原生json_encode和json_decode的封装,以便在发生错误时抛出一个异常
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
trait JsonTrait
|
||||
{
|
||||
/**
|
||||
* @param string $json 待解码的字符串
|
||||
* @param bool $assoc 是否返回数组
|
||||
* @param int $depth 递归深度
|
||||
* @param int $options json_decode的配置
|
||||
* @return mixed
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private static function jsonDecode($json, $assoc = false, $options = 0, $depth = 512)
|
||||
{
|
||||
$data = json_decode($json, $assoc, $depth, $options);
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new \InvalidArgumentException(
|
||||
'json_decode error: ' . json_last_error_msg()
|
||||
);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value 待编码的变量
|
||||
* @param int $options json_decode的配置
|
||||
* @param int $depth 递归深度
|
||||
* @return string
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
private static function jsonEncode($value, $options = 0, $depth = 512)
|
||||
{
|
||||
$json = json_encode($value, $options, $depth);
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new \InvalidArgumentException(
|
||||
'json_encode error: ' . json_last_error_msg()
|
||||
);
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
}
|
93
app/extend/IFlytek/Xfyun/Core/Traits/SignTrait.php
Normal file
93
app/extend/IFlytek/Xfyun/Core/Traits/SignTrait.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Core\Traits;
|
||||
|
||||
/**
|
||||
* 提供平台的签名方法
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
trait SignTrait
|
||||
{
|
||||
|
||||
/**
|
||||
* 根据secret对uri进行签名,返回签名后的uri
|
||||
*
|
||||
* @param string $uri 待签名的uri
|
||||
* @param array $secret 秘钥信息
|
||||
* @return string
|
||||
*/
|
||||
private static function signUriV1($uri, $secret)
|
||||
{
|
||||
$apiKey = $secret['apiKey'];
|
||||
$apiSecret = $secret['apiSecret'];
|
||||
$host = $secret['host'];
|
||||
$request_line = $secret['requestLine'];
|
||||
$date = empty($secret['date']) ? gmdate ('D, d M Y H:i:s \G\M\T', time()) : $secret['date'];
|
||||
$signature_origin = "host: $host\ndate: $date\n$request_line";
|
||||
$signature_sha = hash_hmac('sha256', $signature_origin, $apiSecret, true);
|
||||
$signature = base64_encode($signature_sha);
|
||||
|
||||
$authrization = base64_encode("api_key=\"$apiKey\",algorithm=\"hmac-sha256\",headers=\"host date request-line\",signature=\"$signature\"");
|
||||
$uri = $uri . '?' . http_build_query([
|
||||
'host' => $host,
|
||||
'date' => $date,
|
||||
'authorization' => $authrization
|
||||
]);
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据所提供信息返回签名
|
||||
*
|
||||
* @param string $appId appid
|
||||
* @param string $secretKey secretKey
|
||||
* @param string $timestamp 时间戳,不传的话使用系统时间
|
||||
* @return string
|
||||
*/
|
||||
public static function signV1($appId, $secretKey, $timestamp = null)
|
||||
{
|
||||
$timestamp = $timestamp ?: time();
|
||||
$baseString = $appId . $timestamp;
|
||||
$signa_origin = hash_hmac('sha1', md5($baseString), $secretKey, true);
|
||||
return base64_encode($signa_origin);
|
||||
}
|
||||
|
||||
/**
|
||||
* https调用的鉴权参数构造
|
||||
*
|
||||
* @param string $appId appId
|
||||
* @param string $apiKey apiKey
|
||||
* @param string $curTime curTime
|
||||
* @param string $param param
|
||||
* @return array
|
||||
*/
|
||||
public static function signV2($appId, $apiKey, $param, $curTime = null)
|
||||
{
|
||||
if (empty($curTime)) {
|
||||
$curTime = time();
|
||||
}
|
||||
return [
|
||||
'X-Appid' => $appId,
|
||||
'X-CurTime' => $curTime,
|
||||
'X-Param' => base64_encode($param),
|
||||
'X-CheckSum' => md5($apiKey . $curTime . base64_encode($param))
|
||||
];
|
||||
}
|
||||
}
|
70
app/extend/IFlytek/Xfyun/Core/WsClient.php
Normal file
70
app/extend/IFlytek/Xfyun/Core/WsClient.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Core;
|
||||
|
||||
/**
|
||||
* WebSocket客户端
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class WsClient
|
||||
{
|
||||
/** @var WsHandler */
|
||||
private $handler;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$config += [
|
||||
'handler' => null,
|
||||
];
|
||||
$this->handler = $config['handler'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送请求,并接受返回
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function sendAndReceive()
|
||||
{
|
||||
try {
|
||||
return call_user_func_array([$this->handler, 'sendAndReceive'], []);
|
||||
} catch (\Exception $ex) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
public function send($message = null)
|
||||
{
|
||||
try {
|
||||
return call_user_func_array([$this->handler, 'send'], [$message]);
|
||||
} catch (\Exception $ex) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
public function receive()
|
||||
{
|
||||
try {
|
||||
return call_user_func_array([$this->handler, 'receive'], []);
|
||||
} catch (\Exception $ex) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
}
|
84
app/extend/IFlytek/Xfyun/Speech/ChatClient.php
Normal file
84
app/extend/IFlytek/Xfyun/Speech/ChatClient.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2022 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace extend\IFlytek\Xfyun\Speech;
|
||||
|
||||
|
||||
/**
|
||||
* chat户端
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class ChatClient
|
||||
{
|
||||
|
||||
protected $appId;
|
||||
protected $apiKey;
|
||||
protected $apiSecret;
|
||||
protected $uid;
|
||||
protected $resId;
|
||||
protected $requestConfig;
|
||||
protected $client;
|
||||
|
||||
public function __construct($appId, $apiKey, $apiSecret, $uid = null, $resId = null, $requestConfig = [])
|
||||
{
|
||||
$this->appId = $appId;
|
||||
$this->apiKey = $apiKey;
|
||||
$this->apiSecret = $apiSecret;
|
||||
$this->uid = $uid;
|
||||
$this->resId = $resId;
|
||||
}
|
||||
|
||||
function assembleAuthUrl($addr,$method='GET') {
|
||||
$apiKey=$this->apiKey;
|
||||
$apiSecret=$this->apiSecret;
|
||||
if ($apiKey == "" && $apiSecret == "") { // 不鉴权
|
||||
return $addr;
|
||||
}
|
||||
|
||||
$ul = parse_url($addr); // 解析地址
|
||||
if ($ul === false) { // 地址不对,也不鉴权
|
||||
return $addr;
|
||||
}
|
||||
// // $date = date(DATE_RFC1123); // 获取当前时间并格式化为RFC1123格式的字符串
|
||||
$timestamp = time();
|
||||
$rfc1123_format = gmdate("D, d M Y H:i:s \G\M\T", $timestamp);
|
||||
// $rfc1123_format = "Mon, 31 Jul 2023 08:24:03 GMT";
|
||||
|
||||
// 参与签名的字段 host, date, request-line
|
||||
$signString = array("host: " . $ul["host"], "date: " . $rfc1123_format, $method . " " . $ul["path"] . " HTTP/1.1");
|
||||
// 对签名字符串进行排序,确保顺序一致
|
||||
// ksort($signString);
|
||||
// 将签名字符串拼接成一个字符串
|
||||
$sgin = implode("\n", $signString);
|
||||
|
||||
// 对签名字符串进行HMAC-SHA256加密,得到签名结果
|
||||
$sha = hash_hmac('sha256', $sgin, $apiSecret,true);
|
||||
|
||||
$signature_sha_base64 = base64_encode($sha);
|
||||
|
||||
// 将API密钥、算法、头部信息和签名结果拼接成一个授权URL
|
||||
$authUrl = "api_key=\"$apiKey\",algorithm=\"hmac-sha256\",headers=\"host date request-line\",signature=\"$signature_sha_base64\"";
|
||||
// 对授权URL进行Base64编码,并添加到原始地址后面作为查询参数
|
||||
$authAddr = $addr . '?' . http_build_query(array(
|
||||
'host' => $ul['host'],
|
||||
'date' => $rfc1123_format,
|
||||
'authorization' => base64_encode($authUrl),
|
||||
));
|
||||
return $authAddr;
|
||||
}
|
||||
}
|
110
app/extend/IFlytek/Xfyun/Speech/Config/IgrConfig.php
Normal file
110
app/extend/IFlytek/Xfyun/Speech/Config/IgrConfig.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Config;
|
||||
|
||||
use IFlytek\Xfyun\Core\Traits\ArrayTrait;
|
||||
use IFlytek\Xfyun\Core\Traits\JsonTrait;
|
||||
use IFlytek\Xfyun\Core\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* 性别年龄识别配置参数类
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class IgrConfig implements ConfigInterface
|
||||
{
|
||||
use ArrayTrait;
|
||||
use JsonTrait;
|
||||
|
||||
/**
|
||||
* @var string 引擎类型
|
||||
* 仅支持igr
|
||||
*/
|
||||
private $ent;
|
||||
|
||||
/**
|
||||
* @var string 音频格式
|
||||
* raw:原生音频数据pcm格式
|
||||
* speex:speex格式(rate需设置为8000)
|
||||
* speex-wb:宽频speex格式(rate需设置为16000)
|
||||
* amr:amr格式(rate需设置为8000)
|
||||
* amr-wb:宽频amr格式(rate需设置为16000)
|
||||
* 默认raw
|
||||
*/
|
||||
private $aue;
|
||||
|
||||
/**
|
||||
* @var int 音频采样率
|
||||
* 16000/8000
|
||||
* 默认16000
|
||||
*/
|
||||
private $rate;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$config += [
|
||||
'aue' => 'raw',
|
||||
'rate' => 16000
|
||||
];
|
||||
|
||||
$this->ent = 'igr';
|
||||
$this->aue = $config['aue'];
|
||||
$this->rate = $config['rate'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 去除null项后返回数组形式
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->removeNull([
|
||||
'ent' => $this->ent,
|
||||
'aue' => $this->aue,
|
||||
'rate' => $this->rate
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回toArray的Json格式
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toJson()
|
||||
{
|
||||
return $this->jsonEncode($this->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAue()
|
||||
{
|
||||
return $this->aue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getRate()
|
||||
{
|
||||
return $this->rate;
|
||||
}
|
||||
}
|
265
app/extend/IFlytek/Xfyun/Speech/Config/IseConfig.php
Normal file
265
app/extend/IFlytek/Xfyun/Speech/Config/IseConfig.php
Normal file
@ -0,0 +1,265 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Config;
|
||||
|
||||
use IFlytek\Xfyun\Core\Traits\ArrayTrait;
|
||||
use IFlytek\Xfyun\Core\Traits\JsonTrait;
|
||||
use IFlytek\Xfyun\Core\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* 语音评测配置参数类
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class IseConfig implements ConfigInterface
|
||||
{
|
||||
use ArrayTrait;
|
||||
use JsonTrait;
|
||||
|
||||
/**
|
||||
* @var string 服务类型指定
|
||||
* ise: 开放评测
|
||||
* 默认'ise'
|
||||
*/
|
||||
private $sub;
|
||||
|
||||
/**
|
||||
* @var string 评测语种
|
||||
* 中文:cn_vip,英文:en_vip
|
||||
* 默认'cn_vip'
|
||||
*/
|
||||
private $ent;
|
||||
|
||||
/**
|
||||
* @var string 评测题型
|
||||
* 中文题型:
|
||||
* read_syllable(单字朗读,汉语专有)
|
||||
* read_word(词语朗读)
|
||||
* read_sentence(句子朗读)
|
||||
* read_chapter(篇章朗读)
|
||||
* 英文题型:
|
||||
* read_word(词语朗读)
|
||||
* read_sentence(句子朗读)
|
||||
* read_chapter(篇章朗读)
|
||||
* simple_expression(英文情景反应)
|
||||
* read_choice(英文选择题)
|
||||
* topic(英文自由题)
|
||||
* retell(英文复述题)
|
||||
* picture_talk(英文看图说话)
|
||||
* oral_translation(英文口头翻译)
|
||||
* 默认read_sentence
|
||||
*/
|
||||
private $category;
|
||||
|
||||
/**
|
||||
* @var int 上传音频时来区分音频的状态
|
||||
* 1/2/4
|
||||
* 默认1
|
||||
*/
|
||||
private $aus;
|
||||
|
||||
/**
|
||||
* @var string 用来区分数据上传阶段
|
||||
* ssb:参数上传阶段
|
||||
* ttp:文本上传阶段(ttp_skip=true时该阶段可以跳过,直接使用text字段中的文本)
|
||||
* auw:音频上传阶段
|
||||
* 必传
|
||||
*/
|
||||
private $cmd;
|
||||
|
||||
/**
|
||||
* @var string 待评测文本
|
||||
* 需要加utf8bom头:'\uFEFF' + text
|
||||
*/
|
||||
private $text;
|
||||
|
||||
/**
|
||||
* @var string 带评测文本编码
|
||||
* utf-8/gbk
|
||||
* 默认utf-8
|
||||
*/
|
||||
private $tte;
|
||||
|
||||
/**
|
||||
* @var boolean 跳过ttp直接使用text中的文本进行评测
|
||||
* true/false
|
||||
* 默认true
|
||||
*/
|
||||
private $ttpSkip;
|
||||
|
||||
/**
|
||||
* @var string 拓展能力(生效条件ise_unite="1", rst="entirety")
|
||||
* 多维度分信息显示(准确度分、流畅度分、完整度打分):extra_ability值为multi_dimension,字词句篇均适用,如选多个能力,用分号;隔开。例如:extra_ability=syll_phone_err_msg;pitch;multi_dimension
|
||||
* 单词基频信息显示(基频开始值、结束值):extra_ability值为pitch ,仅适用于单词和句子题型
|
||||
* 音素错误信息显示(声韵、调型是否正确):extra_ability值为syll_phone_err_msg,字词句篇均适用,如选多个能力,用分号;隔开。例如:extra_ability=syll_phone_err_msg;pitch;multi_dimension
|
||||
*/
|
||||
private $extraAbility;
|
||||
|
||||
/**
|
||||
* @var string 音频格式
|
||||
* raw: 未压缩的pcm格式音频或wav(如果用wav格式音频,建议去掉头部)
|
||||
* lame: mp3格式音频
|
||||
* speex-wb;7: 讯飞定制speex格式音频
|
||||
* 默认speex-wb
|
||||
*/
|
||||
private $aue;
|
||||
|
||||
/**
|
||||
* @var string 音频采样率
|
||||
* 默认 audio/L16;rate=16000
|
||||
*/
|
||||
private $auf;
|
||||
|
||||
/**
|
||||
* @var string 返回结果格式
|
||||
* utf8/gbk
|
||||
* 默认utf8
|
||||
*/
|
||||
private $rstcd;
|
||||
|
||||
/**
|
||||
* @var string 评测人群指定
|
||||
* adult(成人群体,不设置群体参数时默认为成人)
|
||||
* youth(中学群体)
|
||||
* pupil(小学群体,中文句、篇题型设置此参数值会有accuracy_score得分的返回)
|
||||
* 默认adult
|
||||
*/
|
||||
private $group;
|
||||
|
||||
/**
|
||||
* @var string 设置评测的打分及检错松严门限(仅中文引擎支持)
|
||||
* easy:容易
|
||||
* common:普通
|
||||
* hard:困难
|
||||
*/
|
||||
private $checkType;
|
||||
|
||||
/**
|
||||
* @var string 设置评测的学段参数 (仅中文题型:中小学的句子、篇章题型支持)
|
||||
* junior(1,2年级)
|
||||
* middle(3,4年级)
|
||||
* senior(5,6年级)
|
||||
*/
|
||||
private $grade;
|
||||
|
||||
/**
|
||||
* @var string 评测返回结果与分制控制(评测返回结果与分制控制也会受到ise_unite与plev参数的影响)
|
||||
* 完整:entirety(默认值)
|
||||
* 中文百分制推荐传参(rst="entirety"且ise_unite="1"且配合extra_ability参数使用)
|
||||
* 英文百分制推荐传参(rst="entirety"且ise_unite="1"且配合extra_ability参数使用)
|
||||
* 精简:plain(评测返回结果将只有总分)
|
||||
*/
|
||||
private $rst;
|
||||
|
||||
/**
|
||||
* @var string 返回结果控制
|
||||
* 0:不控制(默认值)
|
||||
* 1:控制(extra_ability参数将影响全维度等信息的返回)
|
||||
*/
|
||||
private $iseUnite;
|
||||
|
||||
/**
|
||||
* @var string 在rst="entirety"(默认值)且ise_unite="0"(默认值)的情况下plev的取值不同对返回结果有影响。
|
||||
* plev:0(给出全部信息,汉语包含rec_node_type、perr_msg、fluency_score、phone_score信息的返回;英文包含accuracy_score、serr_msg、 syll_accent、fluency_score、standard_score、pitch信息的返回)
|
||||
*/
|
||||
private $plev;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$config += [
|
||||
'ent' => 'cn_vip',
|
||||
'category' => 'read_sentence',
|
||||
'aus' => 1,
|
||||
'cmd' => 'ssb',
|
||||
'text' => '',
|
||||
'tte' => 'utf-8',
|
||||
'ttp_skip' => true,
|
||||
'extra_ability' => null,
|
||||
'aue' => 'raw',
|
||||
'rstcd' => 'utf8',
|
||||
'group' => 'adult',
|
||||
'check_type' => 'common',
|
||||
'grade' => 'middle',
|
||||
'rst' => 'entirety',
|
||||
'ise_unite' => '0',
|
||||
'plev' => '0'
|
||||
];
|
||||
|
||||
$this->sub = 'ise';
|
||||
$this->ent = $config['ent'];
|
||||
$this->category = $config['category'];
|
||||
$this->aus = $config['aus'];
|
||||
$this->cmd = $config['cmd'];
|
||||
$this->text = chr(239) . chr(187) . chr(191) . $config['text'];
|
||||
$this->tte = $config['tte'];
|
||||
$this->ttpSkip = $config['ttp_skip'];
|
||||
$this->extraAbility = $config['extra_ability'];
|
||||
$this->aue = $config['aue'];
|
||||
$this->rstcd = $config['rstcd'];
|
||||
$this->group = $config['group'];
|
||||
$this->checkType = $config['check_type'];
|
||||
$this->grade = $config['grade'];
|
||||
$this->rst = $config['rst'];
|
||||
$this->iseUnite = $config['ise_unite'];
|
||||
$this->plev = $config['plev'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 去除null项后返回数组形式
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->removeNull([
|
||||
'sub' => $this->sub,
|
||||
'ent' => $this->ent,
|
||||
'category' => $this->category,
|
||||
'aus' => $this->aus,
|
||||
'cmd' => $this->cmd,
|
||||
'text' => $this->text,
|
||||
'tte' => $this->tte,
|
||||
'ttp_skip' => $this->ttpSkip,
|
||||
'extra_ability' => $this->extraAbility,
|
||||
'aue' => $this->aue,
|
||||
'rstcd' => $this->rstcd,
|
||||
'group' => $this->group,
|
||||
'check_type' => $this->checkType,
|
||||
'grade' => $this->grade,
|
||||
'rst' => $this->rst,
|
||||
'ise_unite' => $this->iseUnite,
|
||||
'plev' => $this->plev
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回toArray的Json格式
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toJson()
|
||||
{
|
||||
return $this->jsonEncode($this->toArray());
|
||||
}
|
||||
|
||||
public function setText($text)
|
||||
{
|
||||
$this->text = chr(239) . chr(187) . chr(191) . $text;
|
||||
}
|
||||
}
|
142
app/extend/IFlytek/Xfyun/Speech/Config/LfasrConfig.php
Normal file
142
app/extend/IFlytek/Xfyun/Speech/Config/LfasrConfig.php
Normal file
@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Config;
|
||||
|
||||
use IFlytek\Xfyun\Core\Traits\ArrayTrait;
|
||||
use IFlytek\Xfyun\Core\Traits\JsonTrait;
|
||||
use IFlytek\Xfyun\Core\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* 语音转写配置参数类
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class LfasrConfig implements ConfigInterface
|
||||
{
|
||||
use ArrayTrait;
|
||||
use JsonTrait;
|
||||
|
||||
/**
|
||||
* @var string 转写类型
|
||||
* 0: (标准版,格式: wav,flac,opus,mp3,m4a)
|
||||
* 默认: 0
|
||||
*/
|
||||
private $lfasrType;
|
||||
|
||||
/**
|
||||
* @var string 转写结果是否包含分词信息
|
||||
* false或true
|
||||
* 默认false
|
||||
*/
|
||||
private $hasParticiple;
|
||||
|
||||
/**
|
||||
* @var string 转写结果中最大的候选词个数
|
||||
* 0-5
|
||||
* 默认0
|
||||
*/
|
||||
private $maxAlternatives;
|
||||
|
||||
/**
|
||||
* @var string 发音人个数
|
||||
* 0-10
|
||||
* 默认2
|
||||
*/
|
||||
private $speakerNumber;
|
||||
|
||||
/**
|
||||
* @var string 是否包含发音人分离信息
|
||||
* false或true
|
||||
* 默认false
|
||||
*/
|
||||
private $hasSeperate;
|
||||
|
||||
/**
|
||||
* @var string 角色分离类型
|
||||
* 1: 通用角色分离;2: 电话信道角色分离(适用于speaker_number为2的说话场景)
|
||||
* 默认1,该字段只有在开通了角色分离功能的前提下才会生效,正确传入该参数后角色分离效果会有所提升。
|
||||
*/
|
||||
private $roleType;
|
||||
|
||||
/**
|
||||
* @var string 语种
|
||||
* cn: 中英文&中文;en: 英文(英文不支持热词)
|
||||
* 默认cn
|
||||
*/
|
||||
private $language;
|
||||
|
||||
/**
|
||||
* @var string 垂直领域个性化参数
|
||||
* court: 法院; edu: 教育; finance: 金融; medical: 医疗; tech: 科技;
|
||||
* 默认通用
|
||||
*/
|
||||
private $pd;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$config += [
|
||||
'lfasr_type' => '0',
|
||||
'has_participle' => 'false',
|
||||
'max_alternatives' => '0',
|
||||
'speaker_number' => '2',
|
||||
'has_seperate' => 'false',
|
||||
'role_type' => '1',
|
||||
'language' => 'cn',
|
||||
'pd' => null
|
||||
];
|
||||
|
||||
$this->lfasrType = $config['lfasr_type'];
|
||||
$this->hasParticiple = $config['has_participle'];
|
||||
$this->maxAlternatives = $config['max_alternatives'];
|
||||
$this->speakerNumber = $config['speaker_number'];
|
||||
$this->hasSeperate = $config['has_seperate'];
|
||||
$this->roleType = $config['role_type'];
|
||||
$this->language = $config['language'];
|
||||
$this->pd = $config['pd'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 去除null项后返回数组形式
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->removeNull([
|
||||
'lfasr_type' => $this->lfasrType,
|
||||
'has_participle' => $this->hasParticiple,
|
||||
'max_alternatives' => $this->maxAlternatives,
|
||||
'speaker_number' => $this->speakerNumber,
|
||||
'has_seperate' => $this->hasSeperate,
|
||||
'role_type' => $this->roleType,
|
||||
'language' => $this->language,
|
||||
'pd' => $this->pd
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回toArray的Json格式
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toJson()
|
||||
{
|
||||
return $this->jsonEncode($this->toArray());
|
||||
}
|
||||
}
|
76
app/extend/IFlytek/Xfyun/Speech/Config/TcConfig.php
Normal file
76
app/extend/IFlytek/Xfyun/Speech/Config/TcConfig.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Config;
|
||||
|
||||
use IFlytek\Xfyun\Core\Traits\ArrayTrait;
|
||||
use IFlytek\Xfyun\Core\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* 文本纠错配置参数类
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class TcConfig implements ConfigInterface
|
||||
{
|
||||
use ArrayTrait;
|
||||
|
||||
private $resultEncoding;
|
||||
private $resultCompress;
|
||||
private $resultFormat;
|
||||
|
||||
private $inputEncoding;
|
||||
private $inputCompress;
|
||||
private $inputFormat;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$config += [
|
||||
'resultEncoding' => 'utf8',
|
||||
'resultCompress' => 'raw',
|
||||
'resultFormat' => 'json',
|
||||
'inputEncoding' => 'utf8',
|
||||
'inputCompress' => 'raw',
|
||||
'inputFormat' => 'json'
|
||||
];
|
||||
|
||||
$this->resultEncoding = $config['resultEncoding'];
|
||||
$this->resultCompress = $config['resultCompress'];
|
||||
$this->resultFormat = $config['resultFormat'];
|
||||
$this->inputEncoding = $config['inputEncoding'];
|
||||
$this->inputCompress = $config['inputCompress'];
|
||||
$this->inputFormat = $config['inputFormat'];
|
||||
}
|
||||
|
||||
public function toJson()
|
||||
{
|
||||
// TODO: Implement toJson() method.
|
||||
}
|
||||
|
||||
public function toArray()
|
||||
{
|
||||
return self::removeNull([
|
||||
'resultEncoding' => $this->resultEncoding,
|
||||
'resultCompress' => $this->resultCompress,
|
||||
'resultFormat' => $this->resultFormat,
|
||||
'inputEncoding' => $this->inputEncoding,
|
||||
'inputCompress' => $this->inputCompress,
|
||||
'inputFormat' => $this->inputFormat
|
||||
]);
|
||||
}
|
||||
}
|
191
app/extend/IFlytek/Xfyun/Speech/Config/TtsConfig.php
Normal file
191
app/extend/IFlytek/Xfyun/Speech/Config/TtsConfig.php
Normal file
@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Config;
|
||||
|
||||
use IFlytek\Xfyun\Core\Traits\ArrayTrait;
|
||||
use IFlytek\Xfyun\Core\Traits\JsonTrait;
|
||||
use IFlytek\Xfyun\Core\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* 语音合成配置参数类
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class TtsConfig implements ConfigInterface
|
||||
{
|
||||
use ArrayTrait;
|
||||
use JsonTrait;
|
||||
|
||||
/**
|
||||
* @var string 音频编码(必填)
|
||||
* raw:未压缩的pcm
|
||||
* lame:mp3 (当aue=lame时需传参sfl=1)
|
||||
* speex-org-wb;7: 标准开源speex(for speex_wideband,即16k)数字代表指定压缩等级(默认等级为8)
|
||||
* speex-org-nb;7: 标准开源speex(for speex_narrowband,即8k)数字代表指定压缩等级(默认等级为8)
|
||||
* speex;7:压缩格式,压缩等级1~10,默认为7(8k讯飞定制speex)
|
||||
* speex-wb;7:压缩格式,压缩等级1~10,默认为7(16k讯飞定制speex)
|
||||
* 本sdk将默认采用raw格式
|
||||
*/
|
||||
private $aue;
|
||||
|
||||
/**
|
||||
* @var int 开启流式返回
|
||||
* 需要配合aue=lame使用,开启流式返回mp3格式音频取值:1
|
||||
*/
|
||||
private $sfl;
|
||||
|
||||
/**
|
||||
* @var string 音频采样率
|
||||
* audio/L16;rate=8000: 合成8K的音频
|
||||
* audio/L16;rate=16000: 合成16K的音频
|
||||
* auf不传值: 合成16K的音频
|
||||
*/
|
||||
private $auf;
|
||||
|
||||
/**
|
||||
* @var string 发音人(必填)
|
||||
* 可选值: 请到控制台添加试用或购买
|
||||
* 默认xiaoyan
|
||||
*/
|
||||
private $vcn;
|
||||
|
||||
/**
|
||||
* @var int 语速
|
||||
* 可选值: 0-100
|
||||
* 默认为50
|
||||
*/
|
||||
private $speed;
|
||||
|
||||
/**
|
||||
* @var int 音量
|
||||
* 可选值: 0-100
|
||||
* 默认为50
|
||||
*/
|
||||
private $volume;
|
||||
|
||||
/**
|
||||
* @var int 音高
|
||||
* 可选值: 0-100
|
||||
* 默认为50
|
||||
*/
|
||||
private $pitch;
|
||||
|
||||
/**
|
||||
* @var int 合成音频的背景音
|
||||
* 0: 无背景音; 1: 有背景音
|
||||
* 默认0
|
||||
*/
|
||||
private $bgs;
|
||||
|
||||
/**
|
||||
* @var string 文本编码格式
|
||||
* GB2312|GBK|BIG5|UNICODE|GB18030|UTF8
|
||||
* 默认UTF-8
|
||||
*/
|
||||
private $tte;
|
||||
|
||||
/**
|
||||
* @var string 设置英文发音方式
|
||||
* 0: 自动判断处理,如果不确定将按照英文词语拼写处理
|
||||
* 1: 所有英文按字母发音
|
||||
* 2: 自动判断处理,如果不确定将按照字母朗读
|
||||
* 默认2
|
||||
*/
|
||||
private $reg;
|
||||
|
||||
/**
|
||||
* @var string 合成音频数字发音方式
|
||||
* 0: 自动判断
|
||||
* 1: 完全数值
|
||||
* 2: 完全字符串
|
||||
* 3: 字符串优先
|
||||
* 默认0
|
||||
*/
|
||||
private $rdn;
|
||||
|
||||
/**
|
||||
* @var string 自定义发音人引擎
|
||||
* 默认传 ptts
|
||||
*/
|
||||
private $ent;
|
||||
|
||||
public function __construct($config = [])
|
||||
{
|
||||
$config += [
|
||||
'aue' => 'lame',
|
||||
'sfl' => 1,
|
||||
'auf' => null,
|
||||
'vcn' => 'xiaoyan',
|
||||
'speed' => 50,
|
||||
'volume' => 50,
|
||||
'pitch' => 50,
|
||||
'bgs' => 0,
|
||||
'tte' => 'UTF8',
|
||||
'reg' => '2',
|
||||
'rdn' => '0',
|
||||
'ent' => ''
|
||||
];
|
||||
|
||||
$this->aue = $config['aue'];
|
||||
$this->sfl = $config['sfl'];
|
||||
$this->auf = $config['auf'];
|
||||
$this->vcn = $config['vcn'];
|
||||
$this->speed = $config['speed'];
|
||||
$this->volume = $config['volume'];
|
||||
$this->pitch = $config['pitch'];
|
||||
$this->bgs = $config['bgs'];
|
||||
$this->tte = $config['tte'];
|
||||
$this->reg = $config['reg'];
|
||||
$this->rdn = $config['rdn'];
|
||||
$this->ent = $config['ent'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 去除null项后返回数组形式
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
return $this->removeNull([
|
||||
'aue' => $this->aue,
|
||||
'sfl' => $this->sfl,
|
||||
'auf' => $this->auf,
|
||||
'vcn' => $this->vcn,
|
||||
'speed' => $this->speed,
|
||||
'volume' => $this->volume,
|
||||
'pitch' => $this->pitch,
|
||||
'bgs' => $this->bgs,
|
||||
'tte' => $this->tte,
|
||||
'reg' => $this->reg,
|
||||
'rdn' => $this->rdn,
|
||||
'ent' => $this->ent
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回toArray的Json格式
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toJson()
|
||||
{
|
||||
return $this->jsonEncode($this->toArray());
|
||||
}
|
||||
}
|
30
app/extend/IFlytek/Xfyun/Speech/Constants/ChatConstants.php
Normal file
30
app/extend/IFlytek/Xfyun/Speech/Constants/ChatConstants.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Constants;
|
||||
|
||||
/**
|
||||
* 星火
|
||||
*
|
||||
* @author
|
||||
*/
|
||||
class ChatConstants
|
||||
{
|
||||
const URI = 'wss://spark-api.xf-yun.com/v2.1/chat';
|
||||
const REQUEST_LINE = 'POST wss://spark-api.xf-yun.com/v2.1/chat HTTP/1.1';
|
||||
|
||||
}
|
31
app/extend/IFlytek/Xfyun/Speech/Constants/IgrConstants.php
Normal file
31
app/extend/IFlytek/Xfyun/Speech/Constants/IgrConstants.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Constants;
|
||||
|
||||
/**
|
||||
* 性别年龄识别常量
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class IgrConstants
|
||||
{
|
||||
const URI = 'wss://ws-api.xfyun.cn/v2/igr';
|
||||
const HOST = 'ws-api.xfyun.cn';
|
||||
const REQUEST_LINE = 'GET /v2/igr HTTP/1.1';
|
||||
const FRAME_SIZE = 1280;
|
||||
}
|
31
app/extend/IFlytek/Xfyun/Speech/Constants/IseConstants.php
Normal file
31
app/extend/IFlytek/Xfyun/Speech/Constants/IseConstants.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Constants;
|
||||
|
||||
/**
|
||||
* 语音评测常量
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class IseConstants
|
||||
{
|
||||
const URI = 'wss://ise-api.xfyun.cn/v2/open-ise';
|
||||
const HOST = 'ise-api.xfyun.cn';
|
||||
const REQUEST_LINE = 'GET /v2/open-ise HTTP/1.1';
|
||||
const FRAME_SIZE = 1280;
|
||||
}
|
34
app/extend/IFlytek/Xfyun/Speech/Constants/LfasrConstants.php
Normal file
34
app/extend/IFlytek/Xfyun/Speech/Constants/LfasrConstants.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Constants;
|
||||
|
||||
/**
|
||||
* 语音转写常量
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class LfasrConstants
|
||||
{
|
||||
const URI_PREPARE = 'https://raasr.xfyun.cn/api/prepare';
|
||||
const URI_UPLOAD = 'https://raasr.xfyun.cn/api/upload';
|
||||
const URI_MERGE = 'https://raasr.xfyun.cn/api/merge';
|
||||
const URI_GET_PROGRESS = 'https://raasr.xfyun.cn/api/getProgress';
|
||||
const URI_GET_RESULT = 'https://raasr.xfyun.cn/api/getResult';
|
||||
const SLICE_PIECE_SIZE = 1024 * 1024 * 10;
|
||||
const ORIGIN_SLICE_ID = 'aaaaaaaaaa';
|
||||
}
|
31
app/extend/IFlytek/Xfyun/Speech/Constants/TcConstants.php
Normal file
31
app/extend/IFlytek/Xfyun/Speech/Constants/TcConstants.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Constants;
|
||||
|
||||
/**
|
||||
* 文本纠错常量
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class TcConstants
|
||||
{
|
||||
const URI = 'https://api.xf-yun.com/v1/private/s9a87e3ec';
|
||||
const LIST_UPLOAD_URI = 'https://evo-gen.xfyun.cn/individuation/gen/upload';
|
||||
const HOST = 'api.xf-yun.com';
|
||||
const REQUEST_LINE = 'POST /v1/private/s9a87e3ec HTTP/1.1';
|
||||
}
|
30
app/extend/IFlytek/Xfyun/Speech/Constants/TtsConstants.php
Normal file
30
app/extend/IFlytek/Xfyun/Speech/Constants/TtsConstants.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Constants;
|
||||
|
||||
/**
|
||||
* 语音合成常量
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class TtsConstants
|
||||
{
|
||||
const URI = 'wss://tts-api.xfyun.cn/v2/tts';
|
||||
const HOST = 'tts-api.xfyun.cn';
|
||||
const REQUEST_LINE = 'GET /v2/tts HTTP/1.1';
|
||||
}
|
62
app/extend/IFlytek/Xfyun/Speech/Helper/SliceIdGenerator.php
Normal file
62
app/extend/IFlytek/Xfyun/Speech/Helper/SliceIdGenerator.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Helper;
|
||||
|
||||
use IFlytek\Xfyun\Speech\Constants\LfasrConstants;
|
||||
|
||||
/**
|
||||
* 转写切片ID生成类
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class SliceIdGenerator
|
||||
{
|
||||
/**
|
||||
* @var string 当前切片ID
|
||||
*/
|
||||
private $id;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->id = LfasrConstants::ORIGIN_SLICE_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前切片ID,并生成下一个切片ID,赋值给对象的当前ID
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
$currentId = $this->id;
|
||||
$nextId = $currentId;
|
||||
$pos = strlen($currentId) - 1;
|
||||
while ($pos >= 0) {
|
||||
$charAtPos = $nextId[$pos];
|
||||
if ($charAtPos != 'z') {
|
||||
$nextId = substr($nextId, 0, $pos) . chr((ord($charAtPos) + 1)) . substr($nextId, $pos + 1);
|
||||
break;
|
||||
} else {
|
||||
$nextId = substr($nextId, 0, $pos) . 'a';
|
||||
$pos = $pos - 1;
|
||||
}
|
||||
}
|
||||
$this->id = $nextId;
|
||||
return $currentId;
|
||||
}
|
||||
}
|
111
app/extend/IFlytek/Xfyun/Speech/IgrClient.php
Normal file
111
app/extend/IFlytek/Xfyun/Speech/IgrClient.php
Normal file
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech;
|
||||
|
||||
use Exception;
|
||||
use IFlytek\Xfyun\Speech\Config\IgrConfig;
|
||||
use IFlytek\Xfyun\Speech\Constants\IgrConstants;
|
||||
use IFlytek\Xfyun\Speech\Traits\IgrTrait;
|
||||
use IFlytek\Xfyun\Core\Handler\WsHandler;
|
||||
use IFlytek\Xfyun\Core\WsClient;
|
||||
use IFlytek\Xfyun\Core\Traits\SignTrait;
|
||||
use GuzzleHttp\Psr7\Stream;
|
||||
|
||||
/**
|
||||
* 性别年龄识别客户端
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class IgrClient
|
||||
{
|
||||
use SignTrait;
|
||||
use IgrTrait;
|
||||
|
||||
/**
|
||||
* @var string app_id
|
||||
*/
|
||||
protected $appId;
|
||||
|
||||
/**
|
||||
* @var string api_key
|
||||
*/
|
||||
protected $apiKey;
|
||||
|
||||
/**
|
||||
* @var string api_secret
|
||||
*/
|
||||
protected $apiSecret;
|
||||
|
||||
/**
|
||||
* @var IgrConfig
|
||||
*/
|
||||
protected $requestConfig;
|
||||
|
||||
public function __construct($appId, $apiKey, $apiSecret, $requestConfig = [])
|
||||
{
|
||||
$this->appId = $appId;
|
||||
$this->apiKey = $apiKey;
|
||||
$this->apiSecret = $apiSecret;
|
||||
$this->requestConfig = new IgrConfig($requestConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求并返回结果
|
||||
*
|
||||
* @param string $audioPath 待识别音频路径
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function request($audioPath)
|
||||
{
|
||||
$ttsHandler = new WsHandler(
|
||||
$this->signUriV1(IgrConstants::URI, [
|
||||
'appId' => $this->appId,
|
||||
'apiKey' => $this->apiKey,
|
||||
'apiSecret' => $this->apiSecret,
|
||||
'host' => IgrConstants::HOST,
|
||||
'requestLine' => IgrConstants::REQUEST_LINE,
|
||||
]),
|
||||
null
|
||||
);
|
||||
$client = new WsClient([
|
||||
'handler' => $ttsHandler
|
||||
]);
|
||||
|
||||
// 音频上传
|
||||
$frameNum = ceil(fileSize($audioPath) / IgrConstants::FRAME_SIZE);
|
||||
$fileStream = new Stream(fopen($audioPath, 'r'));
|
||||
// 发送第一帧
|
||||
$client->send($this->generateAudioInput($fileStream->read(IgrConstants::FRAME_SIZE), true, false));
|
||||
|
||||
// 发送中间帧
|
||||
for ($i = 1; $i < $frameNum; $i++) {
|
||||
$client->send($this->generateAudioInput($fileStream->read(IgrConstants::FRAME_SIZE), false, false));
|
||||
usleep(4000);
|
||||
}
|
||||
// 发送最后一帧
|
||||
$client->send($this->generateAudioInput('', false, true));
|
||||
|
||||
// 接受数据
|
||||
$message = $this->jsonDecode($client->receive(), true);
|
||||
if ($message['code'] !== 0) {
|
||||
throw new Exception(json_encode($message));
|
||||
}
|
||||
return $message['data'];
|
||||
}
|
||||
}
|
126
app/extend/IFlytek/Xfyun/Speech/IseClient.php
Normal file
126
app/extend/IFlytek/Xfyun/Speech/IseClient.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech;
|
||||
|
||||
use IFlytek\Xfyun\Speech\Config\IseConfig;
|
||||
use IFlytek\Xfyun\Speech\Constants\IseConstants;
|
||||
use IFlytek\Xfyun\Speech\Traits\IseTrait;
|
||||
use IFlytek\Xfyun\Core\Handler\WsHandler;
|
||||
use IFlytek\Xfyun\Core\WsClient;
|
||||
use IFlytek\Xfyun\Core\Traits\SignTrait;
|
||||
use GuzzleHttp\Psr7\Stream;
|
||||
|
||||
/**
|
||||
* 语音评测客户端
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class IseClient
|
||||
{
|
||||
use SignTrait;
|
||||
use IseTrait;
|
||||
|
||||
/**
|
||||
* @var string app_id
|
||||
*/
|
||||
protected $appId;
|
||||
|
||||
/**
|
||||
* @var string api_key
|
||||
*/
|
||||
protected $apiKey;
|
||||
|
||||
/**
|
||||
* @var string api_secret
|
||||
*/
|
||||
protected $apiSecret;
|
||||
|
||||
/**
|
||||
* @var array 评测参数配置
|
||||
*/
|
||||
protected $requestConfig;
|
||||
|
||||
public function __construct($appId, $apiKey, $apiSecret, $requestConfig = [])
|
||||
{
|
||||
$this->appId = $appId;
|
||||
$this->apiKey = $apiKey;
|
||||
$this->apiSecret = $apiSecret;
|
||||
$this->requestConfig = new IseConfig($requestConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求评测,并返回结果(xml格式)
|
||||
*
|
||||
* @param string $audioPath 待评测音频路径
|
||||
* @param string $text 待评测文本
|
||||
* @return string
|
||||
*/
|
||||
public function request($audioPath, $text = null)
|
||||
{
|
||||
$ttsHandler = new WsHandler(
|
||||
$this->signUriV1(IseConstants::URI, [
|
||||
'appId' => $this->appId,
|
||||
'apiKey' => $this->apiKey,
|
||||
'apiSecret' => $this->apiSecret,
|
||||
'host' => IseConstants::HOST,
|
||||
'requestLine' => IseConstants::REQUEST_LINE,
|
||||
]),
|
||||
null
|
||||
);
|
||||
$client = new WsClient([
|
||||
'handler' => $ttsHandler
|
||||
]);
|
||||
|
||||
// 参数上传
|
||||
if (!empty($text)) {
|
||||
$this->requestConfig->setText($text);
|
||||
}
|
||||
$client->send($this->generateParamsInput($this->appId, $this->requestConfig->toArray()));
|
||||
|
||||
// 音频上传
|
||||
$frameSize = ceil(fileSize($audioPath) / IseConstants::FRAME_SIZE);
|
||||
$fileStream = new Stream(fopen($audioPath, 'r'));
|
||||
// 发送第一帧
|
||||
$result = $client->send($this->generateAudioInput($fileStream->read(IseConstants::FRAME_SIZE), true, false));
|
||||
// 发送中间帧
|
||||
for ($i = 1; $i < $frameSize - 1; $i++) {
|
||||
$client->send($this->generateAudioInput($fileStream->read(IseConstants::FRAME_SIZE), false, false));
|
||||
usleep(4000);
|
||||
}
|
||||
// 发送最后一帧
|
||||
$client->send($this->generateAudioInput($fileStream->read(IseConstants::FRAME_SIZE), false, true));
|
||||
|
||||
// 接受数据
|
||||
$result = '';
|
||||
while (true) {
|
||||
$message = $this->jsonDecode($client->receive());
|
||||
if ($message->code !== 0) {
|
||||
throw new \Exception(json_encode($message));
|
||||
}
|
||||
switch ($message->data->status) {
|
||||
case 1:
|
||||
$result .= base64_decode($message->data->data);
|
||||
break;
|
||||
case 2:
|
||||
$result .= base64_decode($message->data->data);
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
231
app/extend/IFlytek/Xfyun/Speech/LfasrClient.php
Normal file
231
app/extend/IFlytek/Xfyun/Speech/LfasrClient.php
Normal file
@ -0,0 +1,231 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech;
|
||||
|
||||
use Exception;
|
||||
use IFlytek\Xfyun\Speech\Config\LfasrConfig;
|
||||
use IFlytek\Xfyun\Speech\Constants\LfasrConstants;
|
||||
use IFlytek\Xfyun\Speech\Traits\LfasrTrait;
|
||||
use IFlytek\Xfyun\Speech\Helper\SliceIdGenerator;
|
||||
use IFlytek\Xfyun\Core\Traits\SignTrait;
|
||||
use IFlytek\Xfyun\Core\Traits\JsonTrait;
|
||||
use IFlytek\Xfyun\Core\HttpClient;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use GuzzleHttp\Psr7\Response;
|
||||
use GuzzleHttp\Psr7\Query;
|
||||
use GuzzleHttp\Psr7\Stream;
|
||||
use GuzzleHttp\Psr7\MultipartStream;
|
||||
|
||||
/**
|
||||
* 语音转写客户端
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class LfasrClient
|
||||
{
|
||||
use SignTrait;
|
||||
use JsonTrait;
|
||||
use LfasrTrait;
|
||||
|
||||
/**
|
||||
* @var string app_id
|
||||
*/
|
||||
protected $appId;
|
||||
|
||||
/**
|
||||
* @var string secret_key
|
||||
*/
|
||||
protected $secretKey;
|
||||
|
||||
/**
|
||||
* @var array 转写参数配置
|
||||
*/
|
||||
protected $requestConfig;
|
||||
|
||||
/** @var HttpClient */
|
||||
protected $client;
|
||||
|
||||
/** @var array 初始化请求体 */
|
||||
protected $requestBody;
|
||||
|
||||
public function __construct($appId, $secretKey, $requestConfig = [])
|
||||
{
|
||||
$this->appId = $appId;
|
||||
$this->secretKey = $secretKey;
|
||||
$this->requestConfig = new LfasrConfig($requestConfig);
|
||||
$this->client = new HttpClient([]);
|
||||
$timestamp = time();
|
||||
$this->requestBody = [
|
||||
'app_id' => $this->appId,
|
||||
'signa' => $this->signV1($this->appId, $this->secretKey, $timestamp),
|
||||
'ts' => $timestamp,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 打包上传接口,封装了准备、分片上传和合并三个接口,并返回task_id
|
||||
*
|
||||
* @param string $filePath 文件路径
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function combineUpload($filePath)
|
||||
{
|
||||
$prepareResponse = $this->prepare($filePath);
|
||||
$prepareContent = $this->jsonDecode($prepareResponse->getBody()->getContents(), true);
|
||||
$taskId = $prepareContent['data'];
|
||||
$this->upload($taskId, $filePath);
|
||||
$this->merge($taskId);
|
||||
return $taskId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 准备接口
|
||||
*
|
||||
* @param $file_path
|
||||
* @return Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function prepare($file_path)
|
||||
{
|
||||
$this->requestBody += $this->fileInfo($file_path);
|
||||
$this->requestBody += $this->sliceInfo($file_path);
|
||||
$this->requestBody += $this->requestConfig->toArray();
|
||||
|
||||
return $this->client->sendAndReceive(
|
||||
new Request(
|
||||
'POST',
|
||||
LfasrConstants::URI_PREPARE,
|
||||
['Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'],
|
||||
Query::build($this->requestBody)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分片上传接口
|
||||
*
|
||||
* @param string $taskId task_id
|
||||
* @param string $filePath 文件路径
|
||||
* @return Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function upload($taskId, $filePath)
|
||||
{
|
||||
$sliceIdGenerator = new SliceIdGenerator();
|
||||
$sliceInfo = $this->sliceInfo($filePath);
|
||||
$fileStream = new Stream(fopen($filePath, 'r'));
|
||||
|
||||
$this->requestBody += [
|
||||
'task_id' => $taskId
|
||||
];
|
||||
|
||||
$request = new Request(
|
||||
'POST',
|
||||
LfasrConstants::URI_UPLOAD
|
||||
);
|
||||
|
||||
for ($i = 0; $i < $sliceInfo['slice_num']; $i++) {
|
||||
$multipartStream = new MultipartStream([
|
||||
[
|
||||
'name' => 'app_id',
|
||||
'contents' => $this->requestBody['app_id']
|
||||
],
|
||||
[
|
||||
'name' => 'signa',
|
||||
'contents' => $this->requestBody['signa']
|
||||
],
|
||||
[
|
||||
'name' => 'ts',
|
||||
'contents' => $this->requestBody['ts']
|
||||
],
|
||||
[
|
||||
'name' => 'task_id',
|
||||
'contents' => $taskId,
|
||||
],
|
||||
[
|
||||
'name' => 'slice_id',
|
||||
'contents' => $sliceIdGenerator->getId()
|
||||
],
|
||||
[
|
||||
'name' => 'content',
|
||||
'contents' => $fileStream->read(LfasrConstants::SLICE_PIECE_SIZE),
|
||||
'filename' => '1.pcm'
|
||||
]
|
||||
]);
|
||||
|
||||
$this->client->sendAndReceive(
|
||||
$request->withBody($multipartStream)
|
||||
);
|
||||
}
|
||||
return new Response(200);
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并接口
|
||||
*
|
||||
* @param string $taskId task_id
|
||||
* @return Response
|
||||
*/
|
||||
public function merge($taskId)
|
||||
{
|
||||
return $this->process(LfasrConstants::URI_MERGE, $taskId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询进度接口
|
||||
*
|
||||
* @param string $taskId task_id
|
||||
* @return Response
|
||||
*/
|
||||
public function getProgress($taskId)
|
||||
{
|
||||
return $this->process(LfasrConstants::URI_GET_PROGRESS, $taskId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取结果接口
|
||||
*
|
||||
* @param string $taskId task_id
|
||||
* @return Response
|
||||
*/
|
||||
public function getResult($taskId)
|
||||
{
|
||||
return $this->process(LfasrConstants::URI_GET_RESULT, $taskId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 封装操作
|
||||
*
|
||||
* @param string $task 操作
|
||||
* @param string $taskId task_id
|
||||
* @return Response
|
||||
*/
|
||||
private function process($task, $taskId)
|
||||
{
|
||||
$this->requestBody += ['task_id' => $taskId];
|
||||
return $this->client->sendAndReceive(
|
||||
new Request(
|
||||
'POST',
|
||||
$task,
|
||||
['Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'],
|
||||
Query::build($this->requestBody)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
104
app/extend/IFlytek/Xfyun/Speech/TcClient.php
Normal file
104
app/extend/IFlytek/Xfyun/Speech/TcClient.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2022 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech;
|
||||
|
||||
use IFlytek\Xfyun\Speech\Config\TcConfig;
|
||||
use IFlytek\Xfyun\Speech\Constants\TcConstants;
|
||||
use IFlytek\Xfyun\Speech\Traits\TcTrait;
|
||||
use IFlytek\Xfyun\Core\Traits\SignTrait;
|
||||
use IFlytek\Xfyun\Core\HttpClient;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
|
||||
/**
|
||||
* 文本纠错客户端
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class TcClient
|
||||
{
|
||||
use SignTrait;
|
||||
use TcTrait;
|
||||
|
||||
protected $appId;
|
||||
protected $apiKey;
|
||||
protected $apiSecret;
|
||||
protected $uid;
|
||||
protected $resId;
|
||||
protected $requestConfig;
|
||||
protected $client;
|
||||
|
||||
public function __construct($appId, $apiKey, $apiSecret, $uid = null, $resId = null, $requestConfig = [])
|
||||
{
|
||||
$this->appId = $appId;
|
||||
$this->apiKey = $apiKey;
|
||||
$this->apiSecret = $apiSecret;
|
||||
$this->uid = $uid;
|
||||
$this->resId = $resId;
|
||||
$this->requestConfig = new TcConfig($requestConfig);
|
||||
$this->client = new HttpClient([]);
|
||||
}
|
||||
|
||||
public function request($text)
|
||||
{
|
||||
$uri = self::signUriV1(TcConstants::URI, [
|
||||
'apiKey' => $this->apiKey,
|
||||
'apiSecret' => $this->apiSecret,
|
||||
'host' => TcConstants::HOST,
|
||||
'requestLine' => TcConstants::REQUEST_LINE
|
||||
]);
|
||||
$body = self::generateInput($text, $this->appId, $this->uid, $this->resId, $this->requestConfig->toArray());
|
||||
return $this->client->sendAndReceive(
|
||||
new Request(
|
||||
'POST',
|
||||
$uri,
|
||||
['Content-Type' => 'application/json;charset=UTF-8'],
|
||||
$body
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function listUpload($whiteList, $blackList)
|
||||
{
|
||||
if (empty($this->uid) || empty($this->resId)) {
|
||||
return false;
|
||||
}
|
||||
$response = $this->client->sendAndReceive(
|
||||
new Request(
|
||||
'POST',
|
||||
TcConstants::LIST_UPLOAD_URI,
|
||||
['Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'],
|
||||
self::jsonEncode([
|
||||
'common' => [
|
||||
'app_id' => $this->appId,
|
||||
'uid' => $this->uid,
|
||||
|
||||
],
|
||||
'business' => [
|
||||
'res_id' => $this->resId
|
||||
],
|
||||
'data' => base64_encode(self::jsonEncode([
|
||||
'white_list' => $whiteList,
|
||||
'black_list' => $blackList
|
||||
]))
|
||||
])
|
||||
)
|
||||
);
|
||||
$content = json_decode($response->getBody()->getContents(), true);
|
||||
return $content['message'] == 'success';
|
||||
}
|
||||
}
|
59
app/extend/IFlytek/Xfyun/Speech/Traits/IgrTrait.php
Normal file
59
app/extend/IFlytek/Xfyun/Speech/Traits/IgrTrait.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Traits;
|
||||
|
||||
use IFlytek\Xfyun\Core\Traits\ArrayTrait;
|
||||
use IFlytek\Xfyun\Core\Traits\JsonTrait;
|
||||
|
||||
/**
|
||||
* 性别年龄识别方法
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
trait IgrTrait
|
||||
{
|
||||
use ArrayTrait;
|
||||
use JsonTrait;
|
||||
|
||||
/**
|
||||
* 根据音频数据、是否是第一帧、最后一帧,生成音频上传请求体
|
||||
*
|
||||
* @param string $frameData 音频数据
|
||||
* @param boolean $isFirstFrame 是否是第一帧
|
||||
* @param boolean $isLastFrame 是否是最后一帧
|
||||
* @return string
|
||||
*/
|
||||
public function generateAudioInput($frameData, $isFirstFrame = false, $isLastFrame = false)
|
||||
{
|
||||
return self::jsonEncode(
|
||||
self::removeNull([
|
||||
"common" => !$isFirstFrame ? null : [
|
||||
"app_id" => $this->appId
|
||||
],
|
||||
'business' => !$isFirstFrame ? null : [
|
||||
"aue" => $this->requestConfig->getAue(),
|
||||
"rate" => $this->requestConfig->getRate()
|
||||
],
|
||||
'data' => [
|
||||
'status' => $isFirstFrame ? 0 : ($isLastFrame ? 2 : 1),
|
||||
'audio' => base64_encode($frameData)
|
||||
]
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
78
app/extend/IFlytek/Xfyun/Speech/Traits/IseTrait.php
Normal file
78
app/extend/IFlytek/Xfyun/Speech/Traits/IseTrait.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Traits;
|
||||
|
||||
use IFlytek\Xfyun\Core\Traits\ArrayTrait;
|
||||
use IFlytek\Xfyun\Core\Traits\JsonTrait;
|
||||
|
||||
/**
|
||||
* 语音评测方法
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
trait IseTrait
|
||||
{
|
||||
use ArrayTrait;
|
||||
use JsonTrait;
|
||||
|
||||
/**
|
||||
* 根据合成内容、app_id、配置参数,生成请求体
|
||||
*
|
||||
* @param string $appId app_id
|
||||
* @param array $iseConfigArray 语音合成参数,详见iseConfig
|
||||
* @return string
|
||||
*/
|
||||
public static function generateParamsInput($appId, $iseConfigArray)
|
||||
{
|
||||
return self::jsonEncode(
|
||||
self::removeNull([
|
||||
'common' => [
|
||||
'app_id' => $appId
|
||||
],
|
||||
'business' => $iseConfigArray,
|
||||
'data' => [
|
||||
'status' => 0
|
||||
]
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据音频数据、是否是第一帧、最后一帧,生成音频上传请求体
|
||||
*
|
||||
* @param string $frameData 音频数据
|
||||
* @param boolean $isFirstFrame 是否是第一帧
|
||||
* @param boolean $isLastFrame 是否是最后一帧
|
||||
* @return string
|
||||
*/
|
||||
public static function generateAudioInput($frameData, $isFirstFrame = false, $isLastFrame = false)
|
||||
{
|
||||
return self::jsonEncode(
|
||||
self::removeNull([
|
||||
'business' => [
|
||||
"cmd" => "auw",
|
||||
"aus" => $isFirstFrame ? 1 : ($isLastFrame ? 4 : 2)
|
||||
],
|
||||
'data' => [
|
||||
'status' => $isLastFrame ? 2 : 1,
|
||||
'data' => base64_encode($frameData)
|
||||
]
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
56
app/extend/IFlytek/Xfyun/Speech/Traits/LfasrTrait.php
Normal file
56
app/extend/IFlytek/Xfyun/Speech/Traits/LfasrTrait.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Traits;
|
||||
|
||||
use IFlytek\Xfyun\Speech\Constants\LfasrConstants;
|
||||
|
||||
/**
|
||||
* 转写方法
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
trait LfasrTrait
|
||||
{
|
||||
/**
|
||||
* 获取文件名和文件大小
|
||||
*
|
||||
* @param string $filePath 文件路径
|
||||
* @return array
|
||||
*/
|
||||
public static function fileInfo($filePath)
|
||||
{
|
||||
return [
|
||||
'file_name' => basename($filePath),
|
||||
'file_len' => filesize($filePath)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件大小和SDK默认分片大小,获取文件分片数目信息
|
||||
*
|
||||
* @param string $filePath 文件路径
|
||||
* @return array
|
||||
*/
|
||||
public static function sliceInfo($filePath)
|
||||
{
|
||||
$fileSize = filesize($filePath);
|
||||
return [
|
||||
'slice_num' => ceil($fileSize / LfasrConstants::SLICE_PIECE_SIZE)
|
||||
];
|
||||
}
|
||||
}
|
64
app/extend/IFlytek/Xfyun/Speech/Traits/TcTrait.php
Normal file
64
app/extend/IFlytek/Xfyun/Speech/Traits/TcTrait.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Traits;
|
||||
|
||||
use IFlytek\Xfyun\Core\Traits\ArrayTrait;
|
||||
use IFlytek\Xfyun\Core\Traits\JsonTrait;
|
||||
|
||||
/**
|
||||
* 文本纠错方法
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
trait TcTrait
|
||||
{
|
||||
use ArrayTrait;
|
||||
use JsonTrait;
|
||||
|
||||
public static function generateInput($text, $appId, $uid, $resId, $tcConfigArray)
|
||||
{
|
||||
return self::jsonEncode(
|
||||
self::removeNull([
|
||||
'header' => [
|
||||
'app_id' => $appId,
|
||||
'uid' => $uid,
|
||||
'status' => 3
|
||||
],
|
||||
'parameter' => [
|
||||
's9a87e3ec' => [
|
||||
'res_id' => $resId,
|
||||
'result' => [
|
||||
'encoding' => $tcConfigArray['resultEncoding'],
|
||||
'compress' => $tcConfigArray['resultCompress'],
|
||||
'format' => $tcConfigArray['resultFormat'],
|
||||
]
|
||||
]
|
||||
],
|
||||
'payload' => [
|
||||
'input' => [
|
||||
'encoding' => $tcConfigArray['inputEncoding'],
|
||||
'compress' => $tcConfigArray['inputCompress'],
|
||||
'format' => $tcConfigArray['inputFormat'],
|
||||
'status' => 3,
|
||||
'text' => base64_encode($text)
|
||||
]
|
||||
]
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
56
app/extend/IFlytek/Xfyun/Speech/Traits/TtsTrait.php
Normal file
56
app/extend/IFlytek/Xfyun/Speech/Traits/TtsTrait.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech\Traits;
|
||||
|
||||
use IFlytek\Xfyun\Core\Traits\ArrayTrait;
|
||||
use IFlytek\Xfyun\Core\Traits\JsonTrait;
|
||||
|
||||
/**
|
||||
* 语音合成方法
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
trait TtsTrait
|
||||
{
|
||||
use ArrayTrait;
|
||||
use JsonTrait;
|
||||
|
||||
/**
|
||||
* 根据合成内容、app_id、配置参数,生成请求体
|
||||
*
|
||||
* @param string $text 带合成的文本
|
||||
* @param string $appId app_id
|
||||
* @param array $ttsConfigArray 语音合成参数,详见TtsConfig
|
||||
* @return string
|
||||
*/
|
||||
public static function generateInput($text, $appId, $ttsConfigArray)
|
||||
{
|
||||
return self::jsonEncode(
|
||||
self::removeNull([
|
||||
'common' => [
|
||||
'app_id' => $appId
|
||||
],
|
||||
'business' => $ttsConfigArray,
|
||||
'data' => [
|
||||
'text' => base64_encode($text),
|
||||
'status' => 2
|
||||
]
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
100
app/extend/IFlytek/Xfyun/Speech/TtsClient.php
Normal file
100
app/extend/IFlytek/Xfyun/Speech/TtsClient.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright 1999-2021 iFLYTEK Corporation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
namespace IFlytek\Xfyun\Speech;
|
||||
|
||||
use Exception;
|
||||
use IFlytek\Xfyun\Speech\Config\TtsConfig;
|
||||
use IFlytek\Xfyun\Speech\Constants\TtsConstants;
|
||||
use IFlytek\Xfyun\Speech\Traits\TtsTrait;
|
||||
use IFlytek\Xfyun\Core\Handler\WsHandler;
|
||||
use IFlytek\Xfyun\Core\WsClient;
|
||||
use IFlytek\Xfyun\Core\Traits\SignTrait;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* 语音合成客户端
|
||||
*
|
||||
* @author guizheng@iflytek.com
|
||||
*/
|
||||
class TtsClient
|
||||
{
|
||||
use SignTrait;
|
||||
use TtsTrait;
|
||||
|
||||
/**
|
||||
* @var string app_id
|
||||
*/
|
||||
protected $appId;
|
||||
|
||||
/**
|
||||
* @var string api_key
|
||||
*/
|
||||
protected $apiKey;
|
||||
|
||||
/**
|
||||
* @var string api_secret
|
||||
*/
|
||||
protected $apiSecret;
|
||||
|
||||
/**
|
||||
* @var array 合成参数配置
|
||||
*/
|
||||
protected $requestConfig;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface or null 日志处理
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
public function __construct($appId, $apiKey, $apiSecret, $requestConfig = [], $logger = null)
|
||||
{
|
||||
$this->appId = $appId;
|
||||
$this->apiKey = $apiKey;
|
||||
$this->apiSecret = $apiSecret;
|
||||
$this->requestConfig = new TtsConfig($requestConfig);
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* 合成文本,并返回结果(字节数组)在Response->getBody()->getContents()
|
||||
*
|
||||
* @param string $text 待合成的文本
|
||||
* @return \GuzzleHttp\Psr7\Response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function request($text)
|
||||
{
|
||||
$ttsHandler = new WsHandler(
|
||||
$this->signUriV1(TtsConstants::URI, [
|
||||
'appId' => $this->appId,
|
||||
'apiKey' => $this->apiKey,
|
||||
'apiSecret' => $this->apiSecret,
|
||||
'host' => TtsConstants::HOST,
|
||||
'requestLine' => TtsConstants::REQUEST_LINE,
|
||||
]),
|
||||
$this->generateInput($text, $this->appId, $this->requestConfig->toArray())
|
||||
);
|
||||
if ($this->logger) {
|
||||
$ttsHandler->setLogger($this->logger);
|
||||
}
|
||||
$client = new WsClient([
|
||||
'handler' => $ttsHandler
|
||||
]);
|
||||
return $client->sendAndReceive();
|
||||
}
|
||||
}
|
4
app/functions.php
Normal file
4
app/functions.php
Normal file
@ -0,0 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Here is your custom functions.
|
||||
*/
|
42
app/middleware/StaticFile.php
Normal file
42
app/middleware/StaticFile.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace app\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Response;
|
||||
use Webman\Http\Request;
|
||||
|
||||
/**
|
||||
* Class StaticFile
|
||||
* @package app\middleware
|
||||
*/
|
||||
class StaticFile implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $next): Response
|
||||
{
|
||||
// Access to files beginning with. Is prohibited
|
||||
if (strpos($request->path(), '/.') !== false) {
|
||||
return response('<h1>403 forbidden</h1>', 403);
|
||||
}
|
||||
/** @var Response $response */
|
||||
$response = $next($request);
|
||||
// Add cross domain HTTP header
|
||||
/*$response->withHeaders([
|
||||
'Access-Control-Allow-Origin' => '*',
|
||||
'Access-Control-Allow-Credentials' => 'true',
|
||||
]);*/
|
||||
return $response;
|
||||
}
|
||||
}
|
29
app/model/Test.php
Normal file
29
app/model/Test.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use support\Model;
|
||||
|
||||
class Test extends Model
|
||||
{
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'test';
|
||||
|
||||
/**
|
||||
* The primary key associated with the table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
/**
|
||||
* Indicates if the model should be timestamped.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
}
|
14
app/view/index/view.html
Normal file
14
app/view/index/view.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="shortcut icon" href="/favicon.ico"/>
|
||||
<title>webman</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
hello <?=htmlspecialchars($name)?>
|
||||
</body>
|
||||
</html>
|
57
composer.json
Normal file
57
composer.json
Normal file
@ -0,0 +1,57 @@
|
||||
{
|
||||
"name": "workerman/webman",
|
||||
"type": "project",
|
||||
"keywords": [
|
||||
"high performance",
|
||||
"http service"
|
||||
],
|
||||
"homepage": "https://www.workerman.net",
|
||||
"license": "MIT",
|
||||
"description": "High performance HTTP Service Framework.",
|
||||
"authors": [
|
||||
{
|
||||
"name": "walkor",
|
||||
"email": "walkor@workerman.net",
|
||||
"homepage": "https://www.workerman.net",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"email": "walkor@workerman.net",
|
||||
"issues": "https://github.com/walkor/webman/issues",
|
||||
"forum": "https://wenda.workerman.net/",
|
||||
"wiki": "https://workerman.net/doc/webman",
|
||||
"source": "https://github.com/walkor/webman"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"workerman/webman-framework": "^1.5.0",
|
||||
"monolog/monolog": "^2.0",
|
||||
"textalk/websocket": "^1.6"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-event": "For better performance. "
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"": "./",
|
||||
"app\\": "./app",
|
||||
"App\\": "./app",
|
||||
"app\\View\\Components\\": "./app/view/components"
|
||||
},
|
||||
"files": [
|
||||
"./support/helpers.php"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"post-package-install": [
|
||||
"support\\Plugin::install"
|
||||
],
|
||||
"post-package-update": [
|
||||
"support\\Plugin::install"
|
||||
],
|
||||
"pre-package-uninstall": [
|
||||
"support\\Plugin::uninstall"
|
||||
]
|
||||
}
|
||||
}
|
533
composer.lock
generated
Normal file
533
composer.lock
generated
Normal file
@ -0,0 +1,533 @@
|
||||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "742c251f2e4bc7f8e8ebe86c60fdac51",
|
||||
"packages": [
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
"version": "2.9.1",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/monolog/monolog/2.9.1/monolog-monolog-2.9.1.zip",
|
||||
"reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"psr/log": "^1.0.1 || ^2.0 || ^3.0"
|
||||
},
|
||||
"provide": {
|
||||
"psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"aws/aws-sdk-php": "^2.4.9 || ^3.0",
|
||||
"doctrine/couchdb": "~1.0@dev",
|
||||
"elasticsearch/elasticsearch": "^7 || ^8",
|
||||
"ext-json": "*",
|
||||
"graylog2/gelf-php": "^1.4.2 || ^2@dev",
|
||||
"guzzlehttp/guzzle": "^7.4",
|
||||
"guzzlehttp/psr7": "^2.2",
|
||||
"mongodb/mongodb": "^1.8",
|
||||
"php-amqplib/php-amqplib": "~2.4 || ^3",
|
||||
"phpspec/prophecy": "^1.15",
|
||||
"phpstan/phpstan": "^0.12.91",
|
||||
"phpunit/phpunit": "^8.5.14",
|
||||
"predis/predis": "^1.1 || ^2.0",
|
||||
"rollbar/rollbar": "^1.3 || ^2 || ^3",
|
||||
"ruflin/elastica": "^7",
|
||||
"swiftmailer/swiftmailer": "^5.3|^6.0",
|
||||
"symfony/mailer": "^5.4 || ^6",
|
||||
"symfony/mime": "^5.4 || ^6"
|
||||
},
|
||||
"suggest": {
|
||||
"aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
|
||||
"doctrine/couchdb": "Allow sending log messages to a CouchDB server",
|
||||
"elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
|
||||
"ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
|
||||
"ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
|
||||
"ext-mbstring": "Allow to work properly with unicode symbols",
|
||||
"ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
|
||||
"ext-openssl": "Required to send log messages using SSL",
|
||||
"ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
|
||||
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
|
||||
"mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
|
||||
"php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
|
||||
"rollbar/rollbar": "Allow sending log messages to Rollbar",
|
||||
"ruflin/elastica": "Allow sending log messages to an Elastic Search server"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Monolog\\": "src/Monolog"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jordi Boggiano",
|
||||
"email": "j.boggiano@seld.be",
|
||||
"homepage": "https://seld.be"
|
||||
}
|
||||
],
|
||||
"description": "Sends your logs to files, sockets, inboxes, databases and various web services",
|
||||
"homepage": "https://github.com/Seldaek/monolog",
|
||||
"keywords": [
|
||||
"log",
|
||||
"logging",
|
||||
"psr-3"
|
||||
],
|
||||
"time": "2023-02-06T13:44:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/fast-route",
|
||||
"version": "v1.3.0",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.tencent.com/repository/composer/nikic/fast-route/v1.3.0/nikic-fast-route-v1.3.0.zip",
|
||||
"reference": "181d480e08d9476e61381e04a71b34dc0432e812",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.35|~5.7"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"FastRoute\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nikita Popov",
|
||||
"email": "nikic@php.net"
|
||||
}
|
||||
],
|
||||
"description": "Fast request router for PHP",
|
||||
"keywords": [
|
||||
"router",
|
||||
"routing"
|
||||
],
|
||||
"time": "2018-02-13T20:26:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phrity/net-uri",
|
||||
"version": "1.3.0",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/phrity/net-uri/1.3.0/phrity-net-uri-1.3.0.zip",
|
||||
"reference": "3f458e0c4d1ddc0e218d7a5b9420127c63925f43",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4 | ^8.0",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/http-message": "^1.0 | ^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-coveralls/php-coveralls": "^2.0",
|
||||
"phpunit/phpunit": "^9.0 | ^10.0",
|
||||
"squizlabs/php_codesniffer": "^3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Phrity\\Net\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sören Jensen",
|
||||
"email": "sirn@sirn.se",
|
||||
"homepage": "https://phrity.sirn.se"
|
||||
}
|
||||
],
|
||||
"description": "PSR-7 Uri and PSR-17 UriFactory implementation",
|
||||
"homepage": "https://phrity.sirn.se/net-uri",
|
||||
"keywords": [
|
||||
"psr-17",
|
||||
"psr-7",
|
||||
"uri",
|
||||
"uri factory"
|
||||
],
|
||||
"time": "2023-08-21T10:33:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phrity/util-errorhandler",
|
||||
"version": "1.0.1",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/phrity/util-errorhandler/1.0.1/phrity-util-errorhandler-1.0.1.zip",
|
||||
"reference": "dc9ac8fb70d733c48a9d9d1eb50f7022172da6bc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-coveralls/php-coveralls": "^2.0",
|
||||
"phpunit/phpunit": "^8.0|^9.0",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sören Jensen",
|
||||
"email": "sirn@sirn.se",
|
||||
"homepage": "https://phrity.sirn.se"
|
||||
}
|
||||
],
|
||||
"description": "Inline error handler; catch and resolve errors for code block.",
|
||||
"homepage": "https://phrity.sirn.se/util-errorhandler",
|
||||
"keywords": [
|
||||
"error",
|
||||
"warning"
|
||||
],
|
||||
"time": "2022-10-27T12:14:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
"version": "2.0.2",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/psr/container/2.0.2/psr-container-2.0.2.zip",
|
||||
"reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Container\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common Container Interface (PHP FIG PSR-11)",
|
||||
"homepage": "https://github.com/php-fig/container",
|
||||
"keywords": [
|
||||
"PSR-11",
|
||||
"container",
|
||||
"container-interface",
|
||||
"container-interop",
|
||||
"psr"
|
||||
],
|
||||
"time": "2021-11-05T16:47:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-factory",
|
||||
"version": "1.0.2",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/psr/http-factory/1.0.2/psr-http-factory-1.0.2.zip",
|
||||
"reference": "e616d01114759c4c489f93b099585439f795fe35",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0.0",
|
||||
"psr/http-message": "^1.0 || ^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interfaces for PSR-7 HTTP message factories",
|
||||
"keywords": [
|
||||
"factory",
|
||||
"http",
|
||||
"message",
|
||||
"psr",
|
||||
"psr-17",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"time": "2023-04-10T20:10:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.1",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/psr/http-message/1.1/psr-http-message-1.1.zip",
|
||||
"reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"homepage": "https://github.com/php-fig/http-message",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"time": "2023-04-04T09:50:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "3.0.0",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/psr/log/3.0.0/psr-log-3.0.0.zip",
|
||||
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Log\\": "src"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for logging libraries",
|
||||
"homepage": "https://github.com/php-fig/log",
|
||||
"keywords": [
|
||||
"log",
|
||||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"time": "2021-07-14T16:46:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "textalk/websocket",
|
||||
"version": "1.6.3",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/textalk/websocket/1.6.3/textalk-websocket-1.6.3.zip",
|
||||
"reference": "67de79745b1a357caf812bfc44e0abf481cee012",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4 | ^8.0",
|
||||
"phrity/net-uri": "^1.0",
|
||||
"phrity/util-errorhandler": "^1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"psr/log": "^1.0 | ^2.0 | ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-coveralls/php-coveralls": "^2.0",
|
||||
"phpunit/phpunit": "^9.0",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WebSocket\\": "lib"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"ISC"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fredrik Liljegren"
|
||||
},
|
||||
{
|
||||
"name": "Sören Jensen"
|
||||
}
|
||||
],
|
||||
"description": "WebSocket client and server",
|
||||
"time": "2022-11-07T18:59:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "workerman/webman-framework",
|
||||
"version": "v1.5.9",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.cloud.tencent.com/repository/composer/workerman/webman-framework/v1.5.9/workerman-webman-framework-v1.5.9.zip",
|
||||
"reference": "6c43faa4f8e3ec61b8d97ba9e8ff53965b9a8b69",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"nikic/fast-route": "^1.3",
|
||||
"php": ">=7.2",
|
||||
"psr/container": ">=1.0",
|
||||
"workerman/workerman": "^4.0.4 || ^5.0.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-event": "For better performance. "
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Webman\\": "./src",
|
||||
"Support\\": "./src/support",
|
||||
"support\\": "./src/support",
|
||||
"Support\\View\\": "./src/support/view",
|
||||
"Support\\Bootstrap\\": "./src/support/bootstrap",
|
||||
"Support\\Exception\\": "./src/support/exception"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "walkor",
|
||||
"email": "walkor@workerman.net",
|
||||
"homepage": "https://www.workerman.net",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "High performance HTTP Service Framework.",
|
||||
"homepage": "https://www.workerman.net",
|
||||
"keywords": [
|
||||
"High Performance",
|
||||
"http service"
|
||||
],
|
||||
"time": "2023-09-11T07:55:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "workerman/workerman",
|
||||
"version": "v4.1.13",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://mirrors.tencent.com/repository/composer/workerman/workerman/v4.1.13/workerman-workerman-v4.1.13.zip",
|
||||
"reference": "807780ff672775fcd08f89e573a2824e939021ce",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-event": "For better performance. "
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Workerman\\": "./"
|
||||
}
|
||||
},
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "walkor",
|
||||
"email": "walkor@workerman.net",
|
||||
"homepage": "http://www.workerman.net",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "An asynchronous event driven PHP framework for easily building fast, scalable network applications.",
|
||||
"homepage": "http://www.workerman.net",
|
||||
"keywords": [
|
||||
"asynchronous",
|
||||
"event-loop"
|
||||
],
|
||||
"time": "2023-07-31T05:57:25+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
BIN
composer.phar
Executable file
BIN
composer.phar
Executable file
Binary file not shown.
26
config/app.php
Normal file
26
config/app.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\Request;
|
||||
|
||||
return [
|
||||
'debug' => true,
|
||||
'error_reporting' => E_ALL,
|
||||
'default_timezone' => 'Asia/Shanghai',
|
||||
'request_class' => Request::class,
|
||||
'public_path' => base_path() . DIRECTORY_SEPARATOR . 'public',
|
||||
'runtime_path' => base_path(false) . DIRECTORY_SEPARATOR . 'runtime',
|
||||
'controller_suffix' => 'Controller',
|
||||
'controller_reuse' => false,
|
||||
];
|
21
config/autoload.php
Normal file
21
config/autoload.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'files' => [
|
||||
base_path() . '/app/functions.php',
|
||||
base_path() . '/support/Request.php',
|
||||
base_path() . '/support/Response.php',
|
||||
]
|
||||
];
|
18
config/bootstrap.php
Normal file
18
config/bootstrap.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
support\bootstrap\Session::class,
|
||||
support\bootstrap\LaravelDb::class,
|
||||
];
|
15
config/container.php
Normal file
15
config/container.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return new Webman\Container;
|
15
config/database.php
Normal file
15
config/database.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
15
config/dependence.php
Normal file
15
config/dependence.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
17
config/exception.php
Normal file
17
config/exception.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'' => support\exception\Handler::class,
|
||||
];
|
32
config/log.php
Normal file
32
config/log.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'default' => [
|
||||
'handlers' => [
|
||||
[
|
||||
'class' => Monolog\Handler\RotatingFileHandler::class,
|
||||
'constructor' => [
|
||||
runtime_path() . '/logs/webman.log',
|
||||
7, //$maxFiles
|
||||
Monolog\Logger::DEBUG,
|
||||
],
|
||||
'formatter' => [
|
||||
'class' => Monolog\Formatter\LineFormatter::class,
|
||||
'constructor' => [null, 'Y-m-d H:i:s', true],
|
||||
],
|
||||
]
|
||||
],
|
||||
],
|
||||
];
|
15
config/middleware.php
Normal file
15
config/middleware.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [];
|
49
config/process.php
Normal file
49
config/process.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
global $argv;
|
||||
|
||||
return [
|
||||
// File update detection and automatic reload
|
||||
'monitor' => [
|
||||
'handler' => process\Monitor::class,
|
||||
'reloadable' => false,
|
||||
'constructor' => [
|
||||
// Monitor these directories
|
||||
'monitorDir' => array_merge([
|
||||
app_path(),
|
||||
config_path(),
|
||||
base_path() . '/process',
|
||||
base_path() . '/support',
|
||||
base_path() . '/resource',
|
||||
base_path() . '/.env',
|
||||
], glob(base_path() . '/plugin/*/app'), glob(base_path() . '/plugin/*/config'), glob(base_path() . '/plugin/*/api')),
|
||||
// Files with these suffixes will be monitored
|
||||
'monitorExtensions' => [
|
||||
'php', 'html', 'htm', 'env'
|
||||
],
|
||||
'options' => [
|
||||
'enable_file_monitor' => !in_array('-d', $argv) && DIRECTORY_SEPARATOR === '/',
|
||||
'enable_memory_monitor' => DIRECTORY_SEPARATOR === '/',
|
||||
]
|
||||
]
|
||||
],
|
||||
'websocket_test' => [
|
||||
// 这里指定进程类,就是上面定义的Pusher类
|
||||
'handler' => app\Pusher::class,
|
||||
'listen' => 'websocket://0.0.0.0:8888',
|
||||
'count' => 1,
|
||||
],
|
||||
];
|
22
config/redis.php
Normal file
22
config/redis.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'default' => [
|
||||
'host' => '127.0.0.1',
|
||||
'password' => null,
|
||||
'port' => 6379,
|
||||
'database' => 0,
|
||||
],
|
||||
];
|
21
config/route.php
Normal file
21
config/route.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Webman\Route;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
31
config/server.php
Normal file
31
config/server.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
return [
|
||||
'listen' => 'http://0.0.0.0:8787',
|
||||
'transport' => 'tcp',
|
||||
'context' => [],
|
||||
'name' => 'webman',
|
||||
'count' => cpu_count() * 4,
|
||||
'user' => '',
|
||||
'group' => '',
|
||||
'reusePort' => false,
|
||||
'event_loop' => '',
|
||||
'stop_timeout' => 2,
|
||||
'pid_file' => runtime_path() . '/webman.pid',
|
||||
'status_file' => runtime_path() . '/webman.status',
|
||||
'stdout_file' => runtime_path() . '/logs/stdout.log',
|
||||
'log_file' => runtime_path() . '/logs/workerman.log',
|
||||
'max_package_size' => 10 * 1024 * 1024
|
||||
];
|
65
config/session.php
Normal file
65
config/session.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Webman\Session\FileSessionHandler;
|
||||
use Webman\Session\RedisSessionHandler;
|
||||
use Webman\Session\RedisClusterSessionHandler;
|
||||
|
||||
return [
|
||||
|
||||
'type' => 'file', // or redis or redis_cluster
|
||||
|
||||
'handler' => FileSessionHandler::class,
|
||||
|
||||
'config' => [
|
||||
'file' => [
|
||||
'save_path' => runtime_path() . '/sessions',
|
||||
],
|
||||
'redis' => [
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'auth' => '',
|
||||
'timeout' => 2,
|
||||
'database' => '',
|
||||
'prefix' => 'redis_session_',
|
||||
],
|
||||
'redis_cluster' => [
|
||||
'host' => ['127.0.0.1:7000', '127.0.0.1:7001', '127.0.0.1:7001'],
|
||||
'timeout' => 2,
|
||||
'auth' => '',
|
||||
'prefix' => 'redis_session_',
|
||||
]
|
||||
],
|
||||
|
||||
'session_name' => 'PHPSID',
|
||||
|
||||
'auto_update_timestamp' => false,
|
||||
|
||||
'lifetime' => 7*24*60*60,
|
||||
|
||||
'cookie_lifetime' => 365*24*60*60,
|
||||
|
||||
'cookie_path' => '/',
|
||||
|
||||
'domain' => '',
|
||||
|
||||
'http_only' => true,
|
||||
|
||||
'secure' => false,
|
||||
|
||||
'same_site' => '',
|
||||
|
||||
'gc_probability' => [1, 1000],
|
||||
|
||||
];
|
23
config/static.php
Normal file
23
config/static.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Static file settings
|
||||
*/
|
||||
return [
|
||||
'enable' => true,
|
||||
'middleware' => [ // Static file Middleware
|
||||
//app\middleware\StaticFile::class,
|
||||
],
|
||||
];
|
25
config/translation.php
Normal file
25
config/translation.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* Multilingual configuration
|
||||
*/
|
||||
return [
|
||||
// Default language
|
||||
'locale' => 'zh_CN',
|
||||
// Fallback language
|
||||
'fallback_locale' => ['zh_CN', 'en'],
|
||||
// Folder where language files are stored
|
||||
'path' => base_path() . '/resource/translations',
|
||||
];
|
22
config/view.php
Normal file
22
config/view.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\view\Raw;
|
||||
use support\view\Twig;
|
||||
use support\view\Blade;
|
||||
use support\view\ThinkPHP;
|
||||
|
||||
return [
|
||||
'handler' => Raw::class
|
||||
];
|
243
process/Monitor.php
Normal file
243
process/Monitor.php
Normal file
@ -0,0 +1,243 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace process;
|
||||
|
||||
use FilesystemIterator;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use SplFileInfo;
|
||||
use Workerman\Timer;
|
||||
use Workerman\Worker;
|
||||
|
||||
/**
|
||||
* Class FileMonitor
|
||||
* @package process
|
||||
*/
|
||||
class Monitor
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $paths = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $extensions = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public static $lockFile = __DIR__ . '/../runtime/monitor.lock';
|
||||
|
||||
/**
|
||||
* Pause monitor
|
||||
* @return void
|
||||
*/
|
||||
public static function pause()
|
||||
{
|
||||
file_put_contents(static::$lockFile, time());
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume monitor
|
||||
* @return void
|
||||
*/
|
||||
public static function resume(): void
|
||||
{
|
||||
clearstatcache();
|
||||
if (is_file(static::$lockFile)) {
|
||||
unlink(static::$lockFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether monitor is paused
|
||||
* @return bool
|
||||
*/
|
||||
public static function isPaused(): bool
|
||||
{
|
||||
clearstatcache();
|
||||
return file_exists(static::$lockFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* FileMonitor constructor.
|
||||
* @param $monitorDir
|
||||
* @param $monitorExtensions
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct($monitorDir, $monitorExtensions, array $options = [])
|
||||
{
|
||||
static::resume();
|
||||
$this->paths = (array)$monitorDir;
|
||||
$this->extensions = $monitorExtensions;
|
||||
if (!Worker::getAllWorkers()) {
|
||||
return;
|
||||
}
|
||||
$disableFunctions = explode(',', ini_get('disable_functions'));
|
||||
if (in_array('exec', $disableFunctions, true)) {
|
||||
echo "\nMonitor file change turned off because exec() has been disabled by disable_functions setting in " . PHP_CONFIG_FILE_PATH . "/php.ini\n";
|
||||
} else {
|
||||
if ($options['enable_file_monitor'] ?? true) {
|
||||
Timer::add(1, function () {
|
||||
$this->checkAllFilesChange();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$memoryLimit = $this->getMemoryLimit($options['memory_limit'] ?? null);
|
||||
if ($memoryLimit && ($options['enable_memory_monitor'] ?? true)) {
|
||||
Timer::add(60, [$this, 'checkMemory'], [$memoryLimit]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $monitorDir
|
||||
* @return bool
|
||||
*/
|
||||
public function checkFilesChange($monitorDir): bool
|
||||
{
|
||||
static $lastMtime, $tooManyFilesCheck;
|
||||
if (!$lastMtime) {
|
||||
$lastMtime = time();
|
||||
}
|
||||
clearstatcache();
|
||||
if (!is_dir($monitorDir)) {
|
||||
if (!is_file($monitorDir)) {
|
||||
return false;
|
||||
}
|
||||
$iterator = [new SplFileInfo($monitorDir)];
|
||||
} else {
|
||||
// recursive traversal directory
|
||||
$dirIterator = new RecursiveDirectoryIterator($monitorDir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS);
|
||||
$iterator = new RecursiveIteratorIterator($dirIterator);
|
||||
}
|
||||
$count = 0;
|
||||
foreach ($iterator as $file) {
|
||||
$count ++;
|
||||
/** var SplFileInfo $file */
|
||||
if (is_dir($file->getRealPath())) {
|
||||
continue;
|
||||
}
|
||||
// check mtime
|
||||
if (in_array($file->getExtension(), $this->extensions, true) && $lastMtime < $file->getMTime()) {
|
||||
$var = 0;
|
||||
exec('"'.PHP_BINARY . '" -l ' . $file, $out, $var);
|
||||
$lastMtime = $file->getMTime();
|
||||
if ($var) {
|
||||
continue;
|
||||
}
|
||||
echo $file . " update and reload\n";
|
||||
// send SIGUSR1 signal to master process for reload
|
||||
if (DIRECTORY_SEPARATOR === '/') {
|
||||
posix_kill(posix_getppid(), SIGUSR1);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$tooManyFilesCheck && $count > 1000) {
|
||||
echo "Monitor: There are too many files ($count files) in $monitorDir which makes file monitoring very slow\n";
|
||||
$tooManyFilesCheck = 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function checkAllFilesChange(): bool
|
||||
{
|
||||
if (static::isPaused()) {
|
||||
return false;
|
||||
}
|
||||
foreach ($this->paths as $path) {
|
||||
if ($this->checkFilesChange($path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $memoryLimit
|
||||
* @return void
|
||||
*/
|
||||
public function checkMemory($memoryLimit)
|
||||
{
|
||||
if (static::isPaused() || $memoryLimit <= 0) {
|
||||
return;
|
||||
}
|
||||
$ppid = posix_getppid();
|
||||
$childrenFile = "/proc/$ppid/task/$ppid/children";
|
||||
if (!is_file($childrenFile) || !($children = file_get_contents($childrenFile))) {
|
||||
return;
|
||||
}
|
||||
foreach (explode(' ', $children) as $pid) {
|
||||
$pid = (int)$pid;
|
||||
$statusFile = "/proc/$pid/status";
|
||||
if (!is_file($statusFile) || !($status = file_get_contents($statusFile))) {
|
||||
continue;
|
||||
}
|
||||
$mem = 0;
|
||||
if (preg_match('/VmRSS\s*?:\s*?(\d+?)\s*?kB/', $status, $match)) {
|
||||
$mem = $match[1];
|
||||
}
|
||||
$mem = (int)($mem / 1024);
|
||||
if ($mem >= $memoryLimit) {
|
||||
posix_kill($pid, SIGINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get memory limit
|
||||
* @return float
|
||||
*/
|
||||
protected function getMemoryLimit($memoryLimit)
|
||||
{
|
||||
if ($memoryLimit === 0) {
|
||||
return 0;
|
||||
}
|
||||
$usePhpIni = false;
|
||||
if (!$memoryLimit) {
|
||||
$memoryLimit = ini_get('memory_limit');
|
||||
$usePhpIni = true;
|
||||
}
|
||||
|
||||
if ($memoryLimit == -1) {
|
||||
return 0;
|
||||
}
|
||||
$unit = strtolower($memoryLimit[strlen($memoryLimit) - 1]);
|
||||
if ($unit === 'g') {
|
||||
$memoryLimit = 1024 * (int)$memoryLimit;
|
||||
} else if ($unit === 'm') {
|
||||
$memoryLimit = (int)$memoryLimit;
|
||||
} else if ($unit === 'k') {
|
||||
$memoryLimit = ((int)$memoryLimit / 1024);
|
||||
} else {
|
||||
$memoryLimit = ((int)$memoryLimit / (1024 * 1024));
|
||||
}
|
||||
if ($memoryLimit < 30) {
|
||||
$memoryLimit = 30;
|
||||
}
|
||||
if ($usePhpIni) {
|
||||
$memoryLimit = (int)(0.8 * $memoryLimit);
|
||||
}
|
||||
return $memoryLimit;
|
||||
}
|
||||
}
|
12
public/404.html
Normal file
12
public/404.html
Normal file
@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>404 Not Found - webman</title>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<h1>404 Not Found</h1>
|
||||
</center>
|
||||
<hr>
|
||||
<center>webman</center>
|
||||
</body>
|
||||
</html>
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
4
runtime/.gitignore
vendored
Normal file
4
runtime/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*
|
||||
!logs
|
||||
!views
|
||||
!.gitignore
|
2
runtime/logs/.gitignore
vendored
Normal file
2
runtime/logs/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
2
runtime/views/.gitignore
vendored
Normal file
2
runtime/views/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
4
start.php
Executable file
4
start.php
Executable file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
support\App::run();
|
24
support/Request.php
Normal file
24
support/Request.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace support;
|
||||
|
||||
/**
|
||||
* Class Request
|
||||
* @package support
|
||||
*/
|
||||
class Request extends \Webman\Http\Request
|
||||
{
|
||||
|
||||
}
|
24
support/Response.php
Normal file
24
support/Response.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace support;
|
||||
|
||||
/**
|
||||
* Class Response
|
||||
* @package support
|
||||
*/
|
||||
class Response extends \Webman\Http\Response
|
||||
{
|
||||
|
||||
}
|
133
support/bootstrap.php
Normal file
133
support/bootstrap.php
Normal file
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
use support\Log;
|
||||
use Webman\Bootstrap;
|
||||
use Webman\Config;
|
||||
use Webman\Middleware;
|
||||
use Webman\Route;
|
||||
use Webman\Util;
|
||||
|
||||
$worker = $worker ?? null;
|
||||
|
||||
set_error_handler(function ($level, $message, $file = '', $line = 0) {
|
||||
if (error_reporting() & $level) {
|
||||
throw new ErrorException($message, 0, $level, $file, $line);
|
||||
}
|
||||
});
|
||||
|
||||
if ($worker) {
|
||||
register_shutdown_function(function ($startTime) {
|
||||
if (time() - $startTime <= 0.1) {
|
||||
sleep(1);
|
||||
}
|
||||
}, time());
|
||||
}
|
||||
|
||||
if (class_exists('Dotenv\Dotenv') && file_exists(base_path(false) . '/.env')) {
|
||||
if (method_exists('Dotenv\Dotenv', 'createUnsafeMutable')) {
|
||||
Dotenv::createUnsafeMutable(base_path(false))->load();
|
||||
} else {
|
||||
Dotenv::createMutable(base_path(false))->load();
|
||||
}
|
||||
}
|
||||
|
||||
Config::clear();
|
||||
support\App::loadAllConfig(['route']);
|
||||
if ($timezone = config('app.default_timezone')) {
|
||||
date_default_timezone_set($timezone);
|
||||
}
|
||||
|
||||
foreach (config('autoload.files', []) as $file) {
|
||||
include_once $file;
|
||||
}
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['autoload']['files'] ?? [] as $file) {
|
||||
include_once $file;
|
||||
}
|
||||
}
|
||||
foreach ($projects['autoload']['files'] ?? [] as $file) {
|
||||
include_once $file;
|
||||
}
|
||||
}
|
||||
|
||||
Middleware::load(config('middleware', []));
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project) || $name === 'static') {
|
||||
continue;
|
||||
}
|
||||
Middleware::load($project['middleware'] ?? []);
|
||||
}
|
||||
Middleware::load($projects['middleware'] ?? [], $firm);
|
||||
if ($staticMiddlewares = config("plugin.$firm.static.middleware")) {
|
||||
Middleware::load(['__static__' => $staticMiddlewares], $firm);
|
||||
}
|
||||
}
|
||||
Middleware::load(['__static__' => config('static.middleware', [])]);
|
||||
|
||||
foreach (config('bootstrap', []) as $className) {
|
||||
if (!class_exists($className)) {
|
||||
$log = "Warning: Class $className setting in config/bootstrap.php not found\r\n";
|
||||
echo $log;
|
||||
Log::error($log);
|
||||
continue;
|
||||
}
|
||||
/** @var Bootstrap $className */
|
||||
$className::start($worker);
|
||||
}
|
||||
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['bootstrap'] ?? [] as $className) {
|
||||
if (!class_exists($className)) {
|
||||
$log = "Warning: Class $className setting in config/plugin/$firm/$name/bootstrap.php not found\r\n";
|
||||
echo $log;
|
||||
Log::error($log);
|
||||
continue;
|
||||
}
|
||||
/** @var Bootstrap $className */
|
||||
$className::start($worker);
|
||||
}
|
||||
}
|
||||
foreach ($projects['bootstrap'] ?? [] as $className) {
|
||||
/** @var string $className */
|
||||
if (!class_exists($className)) {
|
||||
$log = "Warning: Class $className setting in plugin/$firm/config/bootstrap.php not found\r\n";
|
||||
echo $log;
|
||||
Log::error($log);
|
||||
continue;
|
||||
}
|
||||
/** @var Bootstrap $className */
|
||||
$className::start($worker);
|
||||
}
|
||||
}
|
||||
|
||||
$directory = base_path() . '/plugin';
|
||||
$paths = [config_path()];
|
||||
foreach (Util::scanDir($directory) as $path) {
|
||||
if (is_dir($path = "$path/config")) {
|
||||
$paths[] = $path;
|
||||
}
|
||||
}
|
||||
Route::load($paths);
|
||||
|
517
support/helpers.php
Normal file
517
support/helpers.php
Normal file
@ -0,0 +1,517 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
use support\Container;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
use support\Translation;
|
||||
use support\view\Blade;
|
||||
use support\view\Raw;
|
||||
use support\view\ThinkPHP;
|
||||
use support\view\Twig;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Error\RuntimeError;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Webman\App;
|
||||
use Webman\Config;
|
||||
use Webman\Route;
|
||||
use Workerman\Protocols\Http\Session;
|
||||
use Workerman\Worker;
|
||||
|
||||
// Project base path
|
||||
define('BASE_PATH', dirname(__DIR__));
|
||||
|
||||
/**
|
||||
* return the program execute directory
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function run_path(string $path = ''): string
|
||||
{
|
||||
static $runPath = '';
|
||||
if (!$runPath) {
|
||||
$runPath = is_phar() ? dirname(Phar::running(false)) : BASE_PATH;
|
||||
}
|
||||
return path_combine($runPath, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* if the param $path equal false,will return this program current execute directory
|
||||
* @param string|false $path
|
||||
* @return string
|
||||
*/
|
||||
function base_path($path = ''): string
|
||||
{
|
||||
if (false === $path) {
|
||||
return run_path();
|
||||
}
|
||||
return path_combine(BASE_PATH, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* App path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function app_path(string $path = ''): string
|
||||
{
|
||||
return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'app', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function public_path(string $path = ''): string
|
||||
{
|
||||
static $publicPath = '';
|
||||
if (!$publicPath) {
|
||||
$publicPath = \config('app.public_path') ?: run_path('public');
|
||||
}
|
||||
return path_combine($publicPath, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Config path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function config_path(string $path = ''): string
|
||||
{
|
||||
return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'config', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runtime path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function runtime_path(string $path = ''): string
|
||||
{
|
||||
static $runtimePath = '';
|
||||
if (!$runtimePath) {
|
||||
$runtimePath = \config('app.runtime_path') ?: run_path('runtime');
|
||||
}
|
||||
return path_combine($runtimePath, $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate paths based on given information
|
||||
* @param string $front
|
||||
* @param string $back
|
||||
* @return string
|
||||
*/
|
||||
function path_combine(string $front, string $back): string
|
||||
{
|
||||
return $front . ($back ? (DIRECTORY_SEPARATOR . ltrim($back, DIRECTORY_SEPARATOR)) : $back);
|
||||
}
|
||||
|
||||
/**
|
||||
* Response
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @param string $body
|
||||
* @return Response
|
||||
*/
|
||||
function response(string $body = '', int $status = 200, array $headers = []): Response
|
||||
{
|
||||
return new Response($status, $headers, $body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Json response
|
||||
* @param $data
|
||||
* @param int $options
|
||||
* @return Response
|
||||
*/
|
||||
function json($data, int $options = JSON_UNESCAPED_UNICODE): Response
|
||||
{
|
||||
return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options));
|
||||
}
|
||||
|
||||
/**
|
||||
* Xml response
|
||||
* @param $xml
|
||||
* @return Response
|
||||
*/
|
||||
function xml($xml): Response
|
||||
{
|
||||
if ($xml instanceof SimpleXMLElement) {
|
||||
$xml = $xml->asXML();
|
||||
}
|
||||
return new Response(200, ['Content-Type' => 'text/xml'], $xml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Jsonp response
|
||||
* @param $data
|
||||
* @param string $callbackName
|
||||
* @return Response
|
||||
*/
|
||||
function jsonp($data, string $callbackName = 'callback'): Response
|
||||
{
|
||||
if (!is_scalar($data) && null !== $data) {
|
||||
$data = json_encode($data);
|
||||
}
|
||||
return new Response(200, [], "$callbackName($data)");
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect response
|
||||
* @param string $location
|
||||
* @param int $status
|
||||
* @param array $headers
|
||||
* @return Response
|
||||
*/
|
||||
function redirect(string $location, int $status = 302, array $headers = []): Response
|
||||
{
|
||||
$response = new Response($status, ['Location' => $location]);
|
||||
if (!empty($headers)) {
|
||||
$response->withHeaders($headers);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* View response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @param string|null $plugin
|
||||
* @return Response
|
||||
*/
|
||||
function view(string $template, array $vars = [], string $app = null, string $plugin = null): Response
|
||||
{
|
||||
$request = \request();
|
||||
$plugin = $plugin === null ? ($request->plugin ?? '') : $plugin;
|
||||
$handler = \config($plugin ? "plugin.$plugin.view.handler" : 'view.handler');
|
||||
return new Response(200, [], $handler::render($template, $vars, $app, $plugin));
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
* @throws Throwable
|
||||
*/
|
||||
function raw_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], Raw::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Blade view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
*/
|
||||
function blade_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], Blade::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Think view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
*/
|
||||
function think_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], ThinkPHP::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Twig view response
|
||||
* @param string $template
|
||||
* @param array $vars
|
||||
* @param string|null $app
|
||||
* @return Response
|
||||
* @throws LoaderError
|
||||
* @throws RuntimeError
|
||||
* @throws SyntaxError
|
||||
*/
|
||||
function twig_view(string $template, array $vars = [], string $app = null): Response
|
||||
{
|
||||
return new Response(200, [], Twig::render($template, $vars, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request
|
||||
* @return \Webman\Http\Request|Request|null
|
||||
*/
|
||||
function request()
|
||||
{
|
||||
return App::request();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config
|
||||
* @param string|null $key
|
||||
* @param $default
|
||||
* @return array|mixed|null
|
||||
*/
|
||||
function config(string $key = null, $default = null)
|
||||
{
|
||||
return Config::get($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create url
|
||||
* @param string $name
|
||||
* @param ...$parameters
|
||||
* @return string
|
||||
*/
|
||||
function route(string $name, ...$parameters): string
|
||||
{
|
||||
$route = Route::getByName($name);
|
||||
if (!$route) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$parameters) {
|
||||
return $route->url();
|
||||
}
|
||||
|
||||
if (is_array(current($parameters))) {
|
||||
$parameters = current($parameters);
|
||||
}
|
||||
|
||||
return $route->url($parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Session
|
||||
* @param mixed $key
|
||||
* @param mixed $default
|
||||
* @return mixed|bool|Session
|
||||
*/
|
||||
function session($key = null, $default = null)
|
||||
{
|
||||
$session = \request()->session();
|
||||
if (null === $key) {
|
||||
return $session;
|
||||
}
|
||||
if (is_array($key)) {
|
||||
$session->put($key);
|
||||
return null;
|
||||
}
|
||||
if (strpos($key, '.')) {
|
||||
$keyArray = explode('.', $key);
|
||||
$value = $session->all();
|
||||
foreach ($keyArray as $index) {
|
||||
if (!isset($value[$index])) {
|
||||
return $default;
|
||||
}
|
||||
$value = $value[$index];
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
return $session->get($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translation
|
||||
* @param string $id
|
||||
* @param array $parameters
|
||||
* @param string|null $domain
|
||||
* @param string|null $locale
|
||||
* @return string
|
||||
*/
|
||||
function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string
|
||||
{
|
||||
$res = Translation::trans($id, $parameters, $domain, $locale);
|
||||
return $res === '' ? $id : $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locale
|
||||
* @param string|null $locale
|
||||
* @return string
|
||||
*/
|
||||
function locale(string $locale = null): string
|
||||
{
|
||||
if (!$locale) {
|
||||
return Translation::getLocale();
|
||||
}
|
||||
Translation::setLocale($locale);
|
||||
return $locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* 404 not found
|
||||
* @return Response
|
||||
*/
|
||||
function not_found(): Response
|
||||
{
|
||||
return new Response(404, [], file_get_contents(public_path() . '/404.html'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy dir
|
||||
* @param string $source
|
||||
* @param string $dest
|
||||
* @param bool $overwrite
|
||||
* @return void
|
||||
*/
|
||||
function copy_dir(string $source, string $dest, bool $overwrite = false)
|
||||
{
|
||||
if (is_dir($source)) {
|
||||
if (!is_dir($dest)) {
|
||||
mkdir($dest);
|
||||
}
|
||||
$files = scandir($source);
|
||||
foreach ($files as $file) {
|
||||
if ($file !== "." && $file !== "..") {
|
||||
copy_dir("$source/$file", "$dest/$file");
|
||||
}
|
||||
}
|
||||
} else if (file_exists($source) && ($overwrite || !file_exists($dest))) {
|
||||
copy($source, $dest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove dir
|
||||
* @param string $dir
|
||||
* @return bool
|
||||
*/
|
||||
function remove_dir(string $dir): bool
|
||||
{
|
||||
if (is_link($dir) || is_file($dir)) {
|
||||
return unlink($dir);
|
||||
}
|
||||
$files = array_diff(scandir($dir), array('.', '..'));
|
||||
foreach ($files as $file) {
|
||||
(is_dir("$dir/$file") && !is_link($dir)) ? remove_dir("$dir/$file") : unlink("$dir/$file");
|
||||
}
|
||||
return rmdir($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind worker
|
||||
* @param $worker
|
||||
* @param $class
|
||||
*/
|
||||
function worker_bind($worker, $class)
|
||||
{
|
||||
$callbackMap = [
|
||||
'onConnect',
|
||||
'onMessage',
|
||||
'onClose',
|
||||
'onError',
|
||||
'onBufferFull',
|
||||
'onBufferDrain',
|
||||
'onWorkerStop',
|
||||
'onWebSocketConnect',
|
||||
'onWorkerReload'
|
||||
];
|
||||
foreach ($callbackMap as $name) {
|
||||
if (method_exists($class, $name)) {
|
||||
$worker->$name = [$class, $name];
|
||||
}
|
||||
}
|
||||
if (method_exists($class, 'onWorkerStart')) {
|
||||
call_user_func([$class, 'onWorkerStart'], $worker);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start worker
|
||||
* @param $processName
|
||||
* @param $config
|
||||
* @return void
|
||||
*/
|
||||
function worker_start($processName, $config)
|
||||
{
|
||||
$worker = new Worker($config['listen'] ?? null, $config['context'] ?? []);
|
||||
$propertyMap = [
|
||||
'count',
|
||||
'user',
|
||||
'group',
|
||||
'reloadable',
|
||||
'reusePort',
|
||||
'transport',
|
||||
'protocol',
|
||||
];
|
||||
$worker->name = $processName;
|
||||
foreach ($propertyMap as $property) {
|
||||
if (isset($config[$property])) {
|
||||
$worker->$property = $config[$property];
|
||||
}
|
||||
}
|
||||
|
||||
$worker->onWorkerStart = function ($worker) use ($config) {
|
||||
require_once base_path('/support/bootstrap.php');
|
||||
if (isset($config['handler'])) {
|
||||
if (!class_exists($config['handler'])) {
|
||||
echo "process error: class {$config['handler']} not exists\r\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$instance = Container::make($config['handler'], $config['constructor'] ?? []);
|
||||
worker_bind($worker, $instance);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get realpath
|
||||
* @param string $filePath
|
||||
* @return string
|
||||
*/
|
||||
function get_realpath(string $filePath): string
|
||||
{
|
||||
if (strpos($filePath, 'phar://') === 0) {
|
||||
return $filePath;
|
||||
} else {
|
||||
return realpath($filePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is phar
|
||||
* @return bool
|
||||
*/
|
||||
function is_phar(): bool
|
||||
{
|
||||
return class_exists(Phar::class, false) && Phar::running();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cpu count
|
||||
* @return int
|
||||
*/
|
||||
function cpu_count(): int
|
||||
{
|
||||
// Windows does not support the number of processes setting.
|
||||
if (DIRECTORY_SEPARATOR === '\\') {
|
||||
return 1;
|
||||
}
|
||||
$count = 4;
|
||||
if (is_callable('shell_exec')) {
|
||||
if (strtolower(PHP_OS) === 'darwin') {
|
||||
$count = (int)shell_exec('sysctl -n machdep.cpu.core_count');
|
||||
} else {
|
||||
$count = (int)shell_exec('nproc');
|
||||
}
|
||||
}
|
||||
return $count > 0 ? $count : 4;
|
||||
}
|
3
windows.bat
Normal file
3
windows.bat
Normal file
@ -0,0 +1,3 @@
|
||||
CHCP 65001
|
||||
php windows.php
|
||||
pause
|
116
windows.php
Normal file
116
windows.php
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
/**
|
||||
* Start file for windows
|
||||
*/
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use Dotenv\Dotenv;
|
||||
use process\Monitor;
|
||||
use support\App;
|
||||
use Workerman\Worker;
|
||||
|
||||
ini_set('display_errors', 'on');
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if (class_exists('Dotenv\Dotenv') && file_exists(base_path() . '/.env')) {
|
||||
if (method_exists('Dotenv\Dotenv', 'createUnsafeImmutable')) {
|
||||
Dotenv::createUnsafeImmutable(base_path())->load();
|
||||
} else {
|
||||
Dotenv::createMutable(base_path())->load();
|
||||
}
|
||||
}
|
||||
|
||||
App::loadAllConfig(['route']);
|
||||
|
||||
$errorReporting = config('app.error_reporting');
|
||||
if (isset($errorReporting)) {
|
||||
error_reporting($errorReporting);
|
||||
}
|
||||
|
||||
$runtimeProcessPath = runtime_path() . DIRECTORY_SEPARATOR . '/windows';
|
||||
if (!is_dir($runtimeProcessPath)) {
|
||||
mkdir($runtimeProcessPath);
|
||||
}
|
||||
$processFiles = [
|
||||
__DIR__ . DIRECTORY_SEPARATOR . 'start.php'
|
||||
];
|
||||
foreach (config('process', []) as $processName => $config) {
|
||||
$processFiles[] = write_process_file($runtimeProcessPath, $processName, '');
|
||||
}
|
||||
|
||||
foreach (config('plugin', []) as $firm => $projects) {
|
||||
foreach ($projects as $name => $project) {
|
||||
if (!is_array($project)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($project['process'] ?? [] as $processName => $config) {
|
||||
$processFiles[] = write_process_file($runtimeProcessPath, $processName, "$firm.$name");
|
||||
}
|
||||
}
|
||||
foreach ($projects['process'] ?? [] as $processName => $config) {
|
||||
$processFiles[] = write_process_file($runtimeProcessPath, $processName, $firm);
|
||||
}
|
||||
}
|
||||
|
||||
function write_process_file($runtimeProcessPath, $processName, $firm): string
|
||||
{
|
||||
$processParam = $firm ? "plugin.$firm.$processName" : $processName;
|
||||
$configParam = $firm ? "config('plugin.$firm.process')['$processName']" : "config('process')['$processName']";
|
||||
$fileContent = <<<EOF
|
||||
<?php
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
|
||||
use Workerman\Worker;
|
||||
use Webman\Config;
|
||||
use support\App;
|
||||
|
||||
ini_set('display_errors', 'on');
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if (is_callable('opcache_reset')) {
|
||||
opcache_reset();
|
||||
}
|
||||
|
||||
App::loadAllConfig(['route']);
|
||||
|
||||
worker_start('$processParam', $configParam);
|
||||
|
||||
if (DIRECTORY_SEPARATOR != "/") {
|
||||
Worker::\$logFile = config('server')['log_file'] ?? Worker::\$logFile;
|
||||
}
|
||||
|
||||
Worker::runAll();
|
||||
|
||||
EOF;
|
||||
$processFile = $runtimeProcessPath . DIRECTORY_SEPARATOR . "start_$processParam.php";
|
||||
file_put_contents($processFile, $fileContent);
|
||||
return $processFile;
|
||||
}
|
||||
|
||||
if ($monitorConfig = config('process.monitor.constructor')) {
|
||||
$monitor = new Monitor(...array_values($monitorConfig));
|
||||
}
|
||||
|
||||
function popen_processes($processFiles)
|
||||
{
|
||||
$cmd = '"' . PHP_BINARY . '" ' . implode(' ', $processFiles);
|
||||
$descriptorspec = [STDIN, STDOUT, STDOUT];
|
||||
$resource = proc_open($cmd, $descriptorspec, $pipes, null, null, ['bypass_shell' => true]);
|
||||
if (!$resource) {
|
||||
exit("Can not execute $cmd\r\n");
|
||||
}
|
||||
return $resource;
|
||||
}
|
||||
|
||||
$resource = popen_processes($processFiles);
|
||||
echo "\r\n";
|
||||
while (1) {
|
||||
sleep(1);
|
||||
if (!empty($monitor) && $monitor->checkAllFilesChange()) {
|
||||
$status = proc_get_status($resource);
|
||||
$pid = $status['pid'];
|
||||
shell_exec("taskkill /F /T /PID $pid");
|
||||
proc_close($resource);
|
||||
$resource = popen_processes($processFiles);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user