更新
This commit is contained in:
2
vendor/fastadminnet/fastadmin-addons/.gitignore
vendored
Normal file
2
vendor/fastadminnet/fastadmin-addons/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
.idea
|
||||
202
vendor/fastadminnet/fastadmin-addons/LICENSE.txt
vendored
Normal file
202
vendor/fastadminnet/fastadmin-addons/LICENSE.txt
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [2024] [FastAdmin]
|
||||
|
||||
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.
|
||||
11
vendor/fastadminnet/fastadmin-addons/README.md
vendored
Normal file
11
vendor/fastadminnet/fastadmin-addons/README.md
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# fastamin-addons
|
||||
FastAdmin插件模块
|
||||
|
||||
## 使用方法
|
||||
http://doc.fastadmin.net/docs/addons.html
|
||||
|
||||
## 特别感谢
|
||||
https://github.com/5ini99/think-addons
|
||||
|
||||
## 开源协议
|
||||
Apache License 2.0
|
||||
37
vendor/fastadminnet/fastadmin-addons/composer.json
vendored
Normal file
37
vendor/fastadminnet/fastadmin-addons/composer.json
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "fastadminnet/fastadmin-addons",
|
||||
"description": "addons package for fastadmin",
|
||||
"homepage": "https://github.com/fastadminnet/fastadmin-addons",
|
||||
"license": "Apache-2.0",
|
||||
"version": "1.4.1",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Karson",
|
||||
"email": "karson@fastadmin.net"
|
||||
},
|
||||
{
|
||||
"name": "xiaobo.sun",
|
||||
"email": "xiaobo.sun@qq.com"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/fastadminnet/fastadmin-addons/issues"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0.0",
|
||||
"nelexa/zip": "^3.3 || ^4.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"think\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/common.php"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"think-config": {
|
||||
"addons": "src/config.php"
|
||||
}
|
||||
}
|
||||
}
|
||||
32
vendor/fastadminnet/fastadmin-addons/licenses/think-addons.txt
vendored
Normal file
32
vendor/fastadminnet/fastadmin-addons/licenses/think-addons.txt
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
|
||||
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
|
||||
All rights reserved。
|
||||
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
|
||||
|
||||
Apache Licence是著名的非盈利开源组织Apache采用的协议。
|
||||
该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
|
||||
允许代码修改,再作为开源或商业软件发布。需要满足
|
||||
的条件:
|
||||
1. 需要给代码的用户一份Apache Licence ;
|
||||
2. 如果你修改了代码,需要在被修改的文件中说明;
|
||||
3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
|
||||
带有原来代码中的协议,商标,专利声明和其他原来作者规
|
||||
定需要包含的说明;
|
||||
4. 如果再发布的产品中包含一个Notice文件,则在Notice文
|
||||
件中需要带有本协议内容。你可以在Notice中增加自己的
|
||||
许可,但不可以表现为对Apache Licence构成更改。
|
||||
具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
296
vendor/fastadminnet/fastadmin-addons/src/Addons.php
vendored
Normal file
296
vendor/fastadminnet/fastadmin-addons/src/Addons.php
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | thinkphp5 Addons [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016 http://www.zzstudio.net All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: Byron Sampson <xiaobo.sun@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think;
|
||||
|
||||
use think\Config;
|
||||
use think\View;
|
||||
|
||||
/**
|
||||
* 插件基类
|
||||
* Class Addons
|
||||
* @author Byron Sampson <xiaobo.sun@qq.com>
|
||||
* @package think\addons
|
||||
*/
|
||||
abstract class Addons
|
||||
{
|
||||
|
||||
// 视图实例对象
|
||||
protected $view = null;
|
||||
// 当前错误信息
|
||||
protected $error;
|
||||
// 插件目录
|
||||
public $addons_path = '';
|
||||
public $addonPath = '';
|
||||
|
||||
// 插件标识
|
||||
protected $addonName = '';
|
||||
// 插件配置作用域
|
||||
protected $configRange = 'addonconfig';
|
||||
// 插件信息作用域
|
||||
protected $infoRange = 'addoninfo';
|
||||
|
||||
/**
|
||||
* 架构函数
|
||||
* @access public
|
||||
*/
|
||||
public function __construct($name = null)
|
||||
{
|
||||
$name = is_null($name) ? $this->getName() : $name;
|
||||
|
||||
//设置插件标识
|
||||
$this->addonName = $name;
|
||||
|
||||
// 获取当前插件目录
|
||||
$this->addonPath = ADDON_PATH . $name . DS;
|
||||
$this->addons_path = $this->addonPath;
|
||||
|
||||
// 初始化视图模型
|
||||
$config = ['view_path' => $this->addonPath];
|
||||
$config = array_merge(Config::get('template'), $config);
|
||||
$this->view = new View($config, Config::get('view_replace_str'));
|
||||
|
||||
// 控制器初始化
|
||||
if (method_exists($this, '_initialize')) {
|
||||
$this->_initialize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取基础配置信息
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
final public function getInfo($name = '', $force = false)
|
||||
{
|
||||
if (empty($name)) {
|
||||
$name = $this->getName();
|
||||
}
|
||||
if (!$force) {
|
||||
$info = Config::get($name, $this->infoRange);
|
||||
if ($info) {
|
||||
return $info;
|
||||
}
|
||||
}
|
||||
$info = [];
|
||||
$infoFile = $this->addonPath . 'info.ini';
|
||||
if (is_file($infoFile)) {
|
||||
$info = Config::parse($infoFile, '', $name, $this->infoRange);
|
||||
$info['url'] = addon_url($name);
|
||||
}
|
||||
Config::set($name, $info, $this->infoRange);
|
||||
|
||||
return $info ? $info : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件的配置数组
|
||||
* @param string $name 可选模块名
|
||||
* @return array
|
||||
*/
|
||||
final public function getConfig($name = '', $force = false)
|
||||
{
|
||||
if (empty($name)) {
|
||||
$name = $this->getName();
|
||||
}
|
||||
if (!$force) {
|
||||
$config = Config::get($name, $this->configRange);
|
||||
if ($config) {
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
$config = [];
|
||||
$configFile = $this->addonPath . 'config.php';
|
||||
if (is_file($configFile)) {
|
||||
$configArr = include $configFile;
|
||||
if (is_array($configArr)) {
|
||||
foreach ($configArr as $key => $value) {
|
||||
$config[$value['name']] = $value['value'];
|
||||
}
|
||||
unset($configArr);
|
||||
}
|
||||
}
|
||||
Config::set($name, $config, $this->configRange);
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置配置数据
|
||||
* @param $name
|
||||
* @param array $value
|
||||
* @return array
|
||||
*/
|
||||
final public function setConfig($name = '', $value = [])
|
||||
{
|
||||
if (empty($name)) {
|
||||
$name = $this->getName();
|
||||
}
|
||||
$config = $this->getConfig($name);
|
||||
$config = array_merge($config, $value);
|
||||
Config::set($name, $config, $this->configRange);
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置插件信息数据
|
||||
* @param $name
|
||||
* @param array $value
|
||||
* @return array
|
||||
*/
|
||||
final public function setInfo($name = '', $value = [])
|
||||
{
|
||||
if (empty($name)) {
|
||||
$name = $this->getName();
|
||||
}
|
||||
$info = $this->getInfo($name);
|
||||
$info = array_merge($info, $value);
|
||||
Config::set($name, $info, $this->infoRange);
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取完整配置列表
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
final public function getFullConfig($name = '')
|
||||
{
|
||||
$fullConfigArr = [];
|
||||
if (empty($name)) {
|
||||
$name = $this->getName();
|
||||
}
|
||||
$configFile = $this->addonPath . 'config.php';
|
||||
if (is_file($configFile)) {
|
||||
$fullConfigArr = include $configFile;
|
||||
}
|
||||
return $fullConfigArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前模块名
|
||||
* @return string
|
||||
*/
|
||||
final public function getName()
|
||||
{
|
||||
if ($this->addonName) {
|
||||
return $this->addonName;
|
||||
}
|
||||
$data = explode('\\', get_class($this));
|
||||
return strtolower(array_pop($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置插件标识
|
||||
* @param $name
|
||||
*/
|
||||
final public function setName($name)
|
||||
{
|
||||
$this->addonName = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查基础配置信息是否完整
|
||||
* @return bool
|
||||
*/
|
||||
final public function checkInfo()
|
||||
{
|
||||
$info = $this->getInfo();
|
||||
$info_check_keys = ['name', 'title', 'intro', 'author', 'version', 'state'];
|
||||
foreach ($info_check_keys as $value) {
|
||||
if (!array_key_exists($value, $info)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载模板和页面输出 可以返回输出内容
|
||||
* @access public
|
||||
* @param string $template 模板文件名或者内容
|
||||
* @param array $vars 模板输出变量
|
||||
* @param array $replace 替换内容
|
||||
* @param array $config 模板参数
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function fetch($template = '', $vars = [], $replace = [], $config = [])
|
||||
{
|
||||
if (!is_file($template)) {
|
||||
$template = '/' . $template;
|
||||
}
|
||||
// 关闭模板布局
|
||||
$this->view->engine->layout(false);
|
||||
|
||||
echo $this->view->fetch($template, $vars, $replace, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染内容输出
|
||||
* @access public
|
||||
* @param string $content 内容
|
||||
* @param array $vars 模板输出变量
|
||||
* @param array $replace 替换内容
|
||||
* @param array $config 模板参数
|
||||
* @return mixed
|
||||
*/
|
||||
public function display($content, $vars = [], $replace = [], $config = [])
|
||||
{
|
||||
// 关闭模板布局
|
||||
$this->view->engine->layout(false);
|
||||
|
||||
echo $this->view->display($content, $vars, $replace, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染内容输出
|
||||
* @access public
|
||||
* @param string $content 内容
|
||||
* @param array $vars 模板输出变量
|
||||
* @return mixed
|
||||
*/
|
||||
public function show($content, $vars = [])
|
||||
{
|
||||
// 关闭模板布局
|
||||
$this->view->engine->layout(false);
|
||||
|
||||
echo $this->view->fetch($content, $vars, [], [], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 模板变量赋值
|
||||
* @access protected
|
||||
* @param mixed $name 要显示的模板变量
|
||||
* @param mixed $value 变量的值
|
||||
* @return void
|
||||
*/
|
||||
public function assign($name, $value = '')
|
||||
{
|
||||
$this->view->assign($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前错误信息
|
||||
* @return mixed
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
//必须实现安装
|
||||
abstract public function install();
|
||||
|
||||
//必须卸载插件方法
|
||||
abstract public function uninstall();
|
||||
}
|
||||
21
vendor/fastadminnet/fastadmin-addons/src/addons/AddonException.php
vendored
Normal file
21
vendor/fastadminnet/fastadmin-addons/src/addons/AddonException.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace think\addons;
|
||||
|
||||
use think\Exception;
|
||||
|
||||
/**
|
||||
* 插件异常处理类
|
||||
* @package think\addons
|
||||
*/
|
||||
class AddonException extends Exception
|
||||
{
|
||||
|
||||
public function __construct($message, $code = 0, $data = '')
|
||||
{
|
||||
$this->message = $message;
|
||||
$this->code = $code;
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
}
|
||||
220
vendor/fastadminnet/fastadmin-addons/src/addons/Controller.php
vendored
Normal file
220
vendor/fastadminnet/fastadmin-addons/src/addons/Controller.php
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | thinkphp5 Addons [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016 http://www.zzstudio.net All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: Byron Sampson <xiaobo.sun@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\addons;
|
||||
|
||||
use app\common\library\Auth;
|
||||
use think\Config;
|
||||
use think\Hook;
|
||||
use think\Lang;
|
||||
use think\Loader;
|
||||
use think\Request;
|
||||
use think\Validate;
|
||||
|
||||
/**
|
||||
* 插件基类控制器
|
||||
* @package think\addons
|
||||
*/
|
||||
class Controller extends \think\Controller
|
||||
{
|
||||
|
||||
// 当前插件操作
|
||||
protected $addon = null;
|
||||
protected $controller = null;
|
||||
protected $action = null;
|
||||
// 当前template
|
||||
protected $template;
|
||||
|
||||
/**
|
||||
* 无需登录的方法,同时也就不需要鉴权了
|
||||
* @var array
|
||||
*/
|
||||
protected $noNeedLogin = ['*'];
|
||||
|
||||
/**
|
||||
* 无需鉴权的方法,但需要登录
|
||||
* @var array
|
||||
*/
|
||||
protected $noNeedRight = ['*'];
|
||||
|
||||
/**
|
||||
* 权限Auth
|
||||
* @var Auth
|
||||
*/
|
||||
protected $auth = null;
|
||||
|
||||
/**
|
||||
* 布局模板
|
||||
* @var string
|
||||
*/
|
||||
protected $layout = null;
|
||||
|
||||
/**
|
||||
* 架构函数
|
||||
* @param Request $request Request对象
|
||||
* @access public
|
||||
*/
|
||||
public function __construct(Request $request = null)
|
||||
{
|
||||
if (is_null($request)) {
|
||||
$request = Request::instance();
|
||||
}
|
||||
// 生成request对象
|
||||
$this->request = $request;
|
||||
|
||||
//移除HTML标签
|
||||
$this->request->filter('trim,strip_tags,htmlspecialchars');
|
||||
|
||||
// 是否自动转换控制器和操作名
|
||||
$convert = Config::get('url_convert');
|
||||
|
||||
$filter = $convert ? 'strtolower' : 'trim';
|
||||
// 处理路由参数
|
||||
$param = $this->request->param();
|
||||
$dispatch = $this->request->dispatch();
|
||||
$var = isset($dispatch['var']) ? $dispatch['var'] : [];
|
||||
$var = array_merge($param, $var);
|
||||
if (isset($dispatch['method']) && substr($dispatch['method'][0], 0, 7) == "\\addons") {
|
||||
$arr = explode("\\", $dispatch['method'][0]);
|
||||
$addon = strtolower($arr[2]);
|
||||
$controller = strtolower(end($arr));
|
||||
$action = $dispatch['method'][1];
|
||||
} else {
|
||||
$addon = isset($var['addon']) ? $var['addon'] : '';
|
||||
$controller = isset($var['controller']) ? $var['controller'] : '';
|
||||
$action = isset($var['action']) ? $var['action'] : '';
|
||||
}
|
||||
|
||||
$this->addon = $addon ? call_user_func($filter, $addon) : '';
|
||||
$this->controller = $controller ? call_user_func($filter, $controller) : 'index';
|
||||
$this->action = $action ? call_user_func($filter, $action) : 'index';
|
||||
|
||||
// 重置配置
|
||||
Config::set('template.view_path', ADDON_PATH . $this->addon . DS . 'view' . DS);
|
||||
|
||||
// 父类的调用必须放在设置模板路径之后
|
||||
parent::__construct($this->request);
|
||||
}
|
||||
|
||||
protected function _initialize()
|
||||
{
|
||||
// 检测IP是否允许
|
||||
if (function_exists("check_ip_allowed")) {
|
||||
check_ip_allowed();
|
||||
}
|
||||
|
||||
// 渲染配置到视图中
|
||||
$config = get_addon_config($this->addon);
|
||||
$this->view->assign("config", $config);
|
||||
|
||||
$lang = $this->request->langset();
|
||||
$lang = preg_match("/^([a-zA-Z\-_]{2,10})\$/i", $lang) ? $lang : 'zh-cn';
|
||||
|
||||
// 加载系统语言包
|
||||
Lang::load([
|
||||
ADDON_PATH . $this->addon . DS . 'lang' . DS . $lang . EXT,
|
||||
]);
|
||||
|
||||
// 设置替换字符串
|
||||
$cdnurl = Config::get('site.cdnurl');
|
||||
$this->view->replace('__ADDON__', $cdnurl . "/assets/addons/" . $this->addon);
|
||||
|
||||
$this->auth = Auth::instance();
|
||||
// token
|
||||
$token = $this->request->server('HTTP_TOKEN', $this->request->request('token', \think\Cookie::get('token')));
|
||||
|
||||
$path = 'addons/' . $this->addon . '/' . str_replace('.', '/', $this->controller) . '/' . $this->action;
|
||||
// 设置当前请求的URI
|
||||
$this->auth->setRequestUri($path);
|
||||
// 检测是否需要验证登录
|
||||
if (!$this->auth->match($this->noNeedLogin)) {
|
||||
//初始化
|
||||
$this->auth->init($token);
|
||||
//检测是否登录
|
||||
if (!$this->auth->isLogin()) {
|
||||
$this->error(__('Please login first'), 'index/user/login');
|
||||
}
|
||||
// 判断是否需要验证权限
|
||||
if (!$this->auth->match($this->noNeedRight)) {
|
||||
// 判断控制器和方法判断是否有对应权限
|
||||
if (!$this->auth->check($path)) {
|
||||
$this->error(__('You have no permission'));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 如果有传递token才验证是否登录状态
|
||||
if ($token) {
|
||||
$this->auth->init($token);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有使用模板布局
|
||||
if ($this->layout) {
|
||||
$this->view->engine->layout('layout/' . $this->layout);
|
||||
}
|
||||
|
||||
$this->view->assign('user', $this->auth->getUser());
|
||||
|
||||
$site = Config::get("site");
|
||||
|
||||
$upload = \app\common\model\Config::upload();
|
||||
|
||||
// 上传信息配置后
|
||||
Hook::listen("upload_config_init", $upload);
|
||||
Config::set('upload', array_merge(Config::get('upload'), $upload));
|
||||
|
||||
// 加载当前控制器语言包
|
||||
$this->assign('site', $site);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载模板输出
|
||||
* @access protected
|
||||
* @param string $template 模板文件名
|
||||
* @param array $vars 模板输出变量
|
||||
* @param array $replace 模板替换
|
||||
* @param array $config 模板参数
|
||||
* @return mixed
|
||||
*/
|
||||
protected function fetch($template = '', $vars = [], $replace = [], $config = [])
|
||||
{
|
||||
$controller = Loader::parseName($this->controller);
|
||||
if ('think' == strtolower(Config::get('template.type')) && $controller && 0 !== strpos($template, '/')) {
|
||||
$depr = Config::get('template.view_depr');
|
||||
$template = str_replace(['/', ':'], $depr, $template);
|
||||
if ('' == $template) {
|
||||
// 如果模板文件名为空 按照默认规则定位
|
||||
$template = str_replace('.', DS, $controller) . $depr . $this->action;
|
||||
} elseif (false === strpos($template, $depr)) {
|
||||
$template = str_replace('.', DS, $controller) . $depr . $template;
|
||||
}
|
||||
}
|
||||
return parent::fetch($template, $vars, $replace, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新Token
|
||||
*/
|
||||
protected function token()
|
||||
{
|
||||
$token = $this->request->param('__token__');
|
||||
|
||||
//验证Token
|
||||
if (!Validate::make()->check(['__token__' => $token], ['__token__' => 'require|token'])) {
|
||||
$this->error(__('Token verification error'), '', ['__token__' => $this->request->token()]);
|
||||
}
|
||||
|
||||
//刷新Token
|
||||
$this->request->token();
|
||||
}
|
||||
|
||||
}
|
||||
94
vendor/fastadminnet/fastadmin-addons/src/addons/Route.php
vendored
Normal file
94
vendor/fastadminnet/fastadmin-addons/src/addons/Route.php
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | thinkphp5 Addons [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016 http://www.zzstudio.net All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: Byron Sampson <xiaobo.sun@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\addons;
|
||||
|
||||
use think\Config;
|
||||
use think\exception\HttpException;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\Hook;
|
||||
use think\Loader;
|
||||
use think\Request;
|
||||
use think\Response;
|
||||
|
||||
/**
|
||||
* 插件执行默认控制器
|
||||
* @package think\addons
|
||||
*/
|
||||
class Route
|
||||
{
|
||||
|
||||
/**
|
||||
* 插件执行
|
||||
*/
|
||||
public function execute($addon = null, $controller = null, $action = null)
|
||||
{
|
||||
$request = Request::instance();
|
||||
// 是否自动转换控制器和操作名
|
||||
$convert = Config::get('url_convert');
|
||||
$filter = $convert ? 'strtolower' : 'trim';
|
||||
|
||||
$addon = $addon ? trim(call_user_func($filter, $addon)) : '';
|
||||
$controller = $controller ? trim(call_user_func($filter, $controller)) : 'index';
|
||||
$action = $action ? trim(call_user_func($filter, $action)) : 'index';
|
||||
|
||||
Hook::listen('addon_begin', $request);
|
||||
if (!empty($addon) && !empty($controller) && !empty($action)) {
|
||||
$info = get_addon_info($addon);
|
||||
if (!$info) {
|
||||
throw new HttpException(404, __('addon %s not found', $addon));
|
||||
}
|
||||
if (!$info['state']) {
|
||||
throw new HttpException(500, __('addon %s is disabled', $addon));
|
||||
}
|
||||
$dispatch = $request->dispatch();
|
||||
if (isset($dispatch['var']) && $dispatch['var']) {
|
||||
$request->route(array_diff_key($dispatch['var'], array_flip(['addon', 'controller', 'action'])));
|
||||
}
|
||||
|
||||
// 设置当前请求的控制器、操作
|
||||
$request->controller($controller)->action($action);
|
||||
|
||||
// 监听addon_module_init
|
||||
Hook::listen('addon_module_init', $request);
|
||||
// 兼容旧版本行为,即将移除,不建议使用
|
||||
Hook::listen('addons_init', $request);
|
||||
|
||||
$class = get_addon_class($addon, 'controller', $controller);
|
||||
if (!$class) {
|
||||
throw new HttpException(404, __('addon controller %s not found', Loader::parseName($controller, 1)));
|
||||
}
|
||||
|
||||
$instance = new $class($request);
|
||||
|
||||
$vars = [];
|
||||
if (is_callable([$instance, $action])) {
|
||||
// 执行操作方法
|
||||
$call = [$instance, $action];
|
||||
} elseif (is_callable([$instance, '_empty'])) {
|
||||
// 空操作
|
||||
$call = [$instance, '_empty'];
|
||||
$vars = [$action];
|
||||
} else {
|
||||
// 操作不存在
|
||||
throw new HttpException(404, __('addon action %s not found', get_class($instance) . '->' . $action . '()'));
|
||||
}
|
||||
|
||||
Hook::listen('addon_action_begin', $call);
|
||||
|
||||
return call_user_func_array($call, $vars);
|
||||
} else {
|
||||
abort(500, lang('addon can not be empty'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1146
vendor/fastadminnet/fastadmin-addons/src/addons/Service.php
vendored
Normal file
1146
vendor/fastadminnet/fastadmin-addons/src/addons/Service.php
vendored
Normal file
File diff suppressed because it is too large
Load Diff
530
vendor/fastadminnet/fastadmin-addons/src/common.php
vendored
Normal file
530
vendor/fastadminnet/fastadmin-addons/src/common.php
vendored
Normal file
@@ -0,0 +1,530 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | thinkphp5 Addons [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016 http://www.zzstudio.net All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: Byron Sampson <xiaobo.sun@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
use Symfony\Component\VarExporter\VarExporter;
|
||||
use think\addons\Service;
|
||||
use think\App;
|
||||
use think\Cache;
|
||||
use think\Config;
|
||||
use think\Exception;
|
||||
use think\exception\HttpException;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\Hook;
|
||||
use think\Loader;
|
||||
use think\Response;
|
||||
use think\Route;
|
||||
|
||||
// 插件目录
|
||||
define('ADDON_PATH', ROOT_PATH . 'addons' . DS);
|
||||
|
||||
// 定义路由
|
||||
Route::any('addons/:addon/[:controller]/[:action]', "\\think\\addons\\Route@execute");
|
||||
|
||||
// 如果插件目录不存在则创建
|
||||
if (!is_dir(ADDON_PATH)) {
|
||||
@mkdir(ADDON_PATH, 0755, true);
|
||||
}
|
||||
|
||||
// 注册类的根命名空间
|
||||
Loader::addNamespace('addons', ADDON_PATH);
|
||||
|
||||
// 监听addon_init
|
||||
Hook::listen('addon_init');
|
||||
|
||||
// 闭包自动识别插件目录配置
|
||||
Hook::add('app_init', function () {
|
||||
// 获取开关
|
||||
$autoload = (bool)Config::get('addons.autoload', false);
|
||||
// 非正是返回
|
||||
if (!$autoload) {
|
||||
return;
|
||||
}
|
||||
// 当debug时不缓存配置
|
||||
$config = App::$debug ? [] : Cache::get('addons', []);
|
||||
if (empty($config)) {
|
||||
$config = get_addon_autoload_config();
|
||||
Cache::set('addons', $config);
|
||||
}
|
||||
});
|
||||
|
||||
// 闭包初始化行为
|
||||
Hook::add('app_init', function () {
|
||||
//注册路由
|
||||
$routeArr = (array)Config::get('addons.route');
|
||||
$domains = [];
|
||||
$rules = [];
|
||||
$execute = "\\think\\addons\\Route@execute?addon=%s&controller=%s&action=%s";
|
||||
foreach ($routeArr as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
$addon = $v['addon'];
|
||||
$domain = $v['domain'];
|
||||
$drules = [];
|
||||
foreach ($v['rule'] as $m => $n) {
|
||||
$urlArr = explode('/', $n);
|
||||
if (count($urlArr) < 3) {
|
||||
continue;
|
||||
}
|
||||
list($addon, $controller, $action) = $urlArr;
|
||||
$drules[$m] = sprintf($execute . '&indomain=1', $addon, $controller, $action);
|
||||
}
|
||||
//$domains[$domain] = $drules ? $drules : "\\addons\\{$k}\\controller";
|
||||
$domains[$domain] = $drules ? $drules : [];
|
||||
$domains[$domain][':controller/[:action]'] = sprintf($execute . '&indomain=1', $addon, ":controller", ":action");
|
||||
} else {
|
||||
if (!$v) {
|
||||
continue;
|
||||
}
|
||||
$urlArr = explode('/', $v);
|
||||
if (count($urlArr) < 3) {
|
||||
continue;
|
||||
}
|
||||
list($addon, $controller, $action) = $urlArr;
|
||||
$rules[$k] = sprintf($execute, $addon, $controller, $action);
|
||||
}
|
||||
}
|
||||
Route::rule($rules);
|
||||
if ($domains) {
|
||||
Route::domain($domains);
|
||||
}
|
||||
|
||||
// 获取系统配置
|
||||
$hooks = App::$debug ? [] : Cache::get('hooks', []);
|
||||
if (empty($hooks)) {
|
||||
$hooks = (array)Config::get('addons.hooks');
|
||||
// 初始化钩子
|
||||
foreach ($hooks as $key => $values) {
|
||||
$values = is_string($values) ? explode(',', $values) : (array)$values;
|
||||
$values = array_filter($values);
|
||||
$hooks[$key] = array_filter(array_map('get_addon_class', $values));
|
||||
}
|
||||
Cache::set('hooks', $hooks);
|
||||
}
|
||||
//如果在插件中有定义app_init,则直接执行
|
||||
if (isset($hooks['app_init'])) {
|
||||
foreach ($hooks['app_init'] as $k => $v) {
|
||||
Hook::exec($v, 'app_init');
|
||||
}
|
||||
}
|
||||
Hook::import($hooks, true);
|
||||
});
|
||||
|
||||
/**
|
||||
* 处理插件钩子
|
||||
* @param string $hook 钩子名称
|
||||
* @param mixed $params 传入参数
|
||||
* @return void
|
||||
*/
|
||||
function hook($hook, $params = [])
|
||||
{
|
||||
Hook::listen($hook, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除空目录
|
||||
* @param string $dir 目录
|
||||
*/
|
||||
function remove_empty_folder($dir)
|
||||
{
|
||||
try {
|
||||
$isDirEmpty = !(new \FilesystemIterator($dir))->valid();
|
||||
if ($isDirEmpty) {
|
||||
@rmdir($dir);
|
||||
remove_empty_folder(dirname($dir));
|
||||
}
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得插件列表
|
||||
* @return array
|
||||
*/
|
||||
function get_addon_list()
|
||||
{
|
||||
$results = scandir(ADDON_PATH);
|
||||
$list = [];
|
||||
foreach ($results as $name) {
|
||||
if ($name === '.' or $name === '..') {
|
||||
continue;
|
||||
}
|
||||
if (is_file(ADDON_PATH . $name)) {
|
||||
continue;
|
||||
}
|
||||
$addonDir = ADDON_PATH . $name . DS;
|
||||
if (!is_dir($addonDir)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!is_file($addonDir . ucfirst($name) . '.php')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//这里不采用get_addon_info是因为会有缓存
|
||||
//$info = get_addon_info($name);
|
||||
$info_file = $addonDir . 'info.ini';
|
||||
if (!is_file($info_file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$info = Config::parse($info_file, '', "addon-info-{$name}");
|
||||
if (!isset($info['name'])) {
|
||||
continue;
|
||||
}
|
||||
$info['url'] = addon_url($name);
|
||||
$list[$name] = $info;
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得插件自动加载的配置
|
||||
* @param bool $truncate 是否清除手动配置的钩子
|
||||
* @return array
|
||||
*/
|
||||
function get_addon_autoload_config($truncate = false)
|
||||
{
|
||||
// 读取addons的配置
|
||||
$config = (array)Config::get('addons');
|
||||
if ($truncate) {
|
||||
// 清空手动配置的钩子
|
||||
$config['hooks'] = [];
|
||||
}
|
||||
|
||||
// 伪静态优先级
|
||||
$priority = isset($config['priority']) && $config['priority'] ? is_array($config['priority']) ? $config['priority'] : explode(',', $config['priority']) : [];
|
||||
|
||||
$route = [];
|
||||
// 读取插件目录及钩子列表
|
||||
$base = get_class_methods("\\think\\Addons");
|
||||
$base = array_merge($base, ['install', 'uninstall', 'enable', 'disable']);
|
||||
|
||||
$url_domain_deploy = Config::get('url_domain_deploy');
|
||||
$addons = get_addon_list();
|
||||
$domain = [];
|
||||
|
||||
$priority = array_merge($priority, array_keys($addons));
|
||||
|
||||
$orderedAddons = array();
|
||||
foreach ($priority as $key) {
|
||||
if (!isset($addons[$key])) {
|
||||
continue;
|
||||
}
|
||||
$orderedAddons[$key] = $addons[$key];
|
||||
}
|
||||
|
||||
foreach ($orderedAddons as $name => $addon) {
|
||||
if (!$addon['state']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 读取出所有公共方法
|
||||
$methods = (array)get_class_methods("\\addons\\" . $name . "\\" . ucfirst($name));
|
||||
// 跟插件基类方法做比对,得到差异结果
|
||||
$hooks = array_diff($methods, $base);
|
||||
// 循环将钩子方法写入配置中
|
||||
foreach ($hooks as $hook) {
|
||||
$hook = Loader::parseName($hook, 0, false);
|
||||
if (!isset($config['hooks'][$hook])) {
|
||||
$config['hooks'][$hook] = [];
|
||||
}
|
||||
// 兼容手动配置项
|
||||
if (is_string($config['hooks'][$hook])) {
|
||||
$config['hooks'][$hook] = explode(',', $config['hooks'][$hook]);
|
||||
}
|
||||
if (!in_array($name, $config['hooks'][$hook])) {
|
||||
$config['hooks'][$hook][] = $name;
|
||||
}
|
||||
}
|
||||
$conf = get_addon_config($addon['name']);
|
||||
if ($conf) {
|
||||
$conf['rewrite'] = isset($conf['rewrite']) && is_array($conf['rewrite']) ? $conf['rewrite'] : [];
|
||||
$rule = array_map(function ($value) use ($addon) {
|
||||
return "{$addon['name']}/{$value}";
|
||||
}, array_flip($conf['rewrite']));
|
||||
if ($url_domain_deploy && isset($conf['domain']) && $conf['domain']) {
|
||||
$domain[] = [
|
||||
'addon' => $addon['name'],
|
||||
'domain' => $conf['domain'],
|
||||
'rule' => $rule
|
||||
];
|
||||
} else {
|
||||
$route = array_merge($route, $rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
$config['route'] = $route;
|
||||
$config['route'] = array_merge($config['route'], $domain);
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件类的类名
|
||||
* @param string $name 插件名
|
||||
* @param string $type 返回命名空间类型
|
||||
* @param string $class 当前类名
|
||||
* @return string
|
||||
*/
|
||||
function get_addon_class($name, $type = 'hook', $class = null)
|
||||
{
|
||||
$name = Loader::parseName($name);
|
||||
// 处理多级控制器情况
|
||||
if (!is_null($class) && strpos($class, '.')) {
|
||||
$class = explode('.', $class);
|
||||
|
||||
$class[count($class) - 1] = Loader::parseName(end($class), 1);
|
||||
$class = implode('\\', $class);
|
||||
} else {
|
||||
$class = Loader::parseName(is_null($class) ? $name : $class, 1);
|
||||
}
|
||||
switch ($type) {
|
||||
case 'controller':
|
||||
$namespace = "\\addons\\" . $name . "\\controller\\" . $class;
|
||||
break;
|
||||
default:
|
||||
$namespace = "\\addons\\" . $name . "\\" . $class;
|
||||
}
|
||||
return class_exists($namespace) ? $namespace : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取插件的基础信息
|
||||
* @param string $name 插件名
|
||||
* @return array
|
||||
*/
|
||||
function get_addon_info($name)
|
||||
{
|
||||
$addon = get_addon_instance($name);
|
||||
if (!$addon) {
|
||||
return [];
|
||||
}
|
||||
return $addon->getInfo($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件类的配置数组
|
||||
* @param string $name 插件名
|
||||
* @return array
|
||||
*/
|
||||
function get_addon_fullconfig($name)
|
||||
{
|
||||
$addon = get_addon_instance($name);
|
||||
if (!$addon) {
|
||||
return [];
|
||||
}
|
||||
return $addon->getFullConfig($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件类的配置值值
|
||||
* @param string $name 插件名
|
||||
* @return array
|
||||
*/
|
||||
function get_addon_config($name)
|
||||
{
|
||||
$addon = get_addon_instance($name);
|
||||
if (!$addon) {
|
||||
return [];
|
||||
}
|
||||
return $addon->getConfig($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件的单例
|
||||
* @param string $name 插件名
|
||||
* @return mixed|null
|
||||
*/
|
||||
function get_addon_instance($name)
|
||||
{
|
||||
static $_addons = [];
|
||||
if (isset($_addons[$name])) {
|
||||
return $_addons[$name];
|
||||
}
|
||||
$class = get_addon_class($name);
|
||||
if (class_exists($class)) {
|
||||
$_addons[$name] = new $class();
|
||||
return $_addons[$name];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件创建的表
|
||||
* @param string $name 插件名
|
||||
* @return array
|
||||
*/
|
||||
function get_addon_tables($name)
|
||||
{
|
||||
$addonInfo = get_addon_info($name);
|
||||
if (!$addonInfo) {
|
||||
return [];
|
||||
}
|
||||
$regex = "/^CREATE\s+TABLE\s+(IF\s+NOT\s+EXISTS\s+)?`?([a-zA-Z_]+)`?/mi";
|
||||
$sqlFile = ADDON_PATH . $name . DS . 'install.sql';
|
||||
$tables = [];
|
||||
if (is_file($sqlFile)) {
|
||||
preg_match_all($regex, file_get_contents($sqlFile), $matches);
|
||||
if ($matches && isset($matches[2]) && $matches[2]) {
|
||||
$prefix = config('database.prefix');
|
||||
$tables = array_map(function ($item) use ($prefix) {
|
||||
return str_replace("__PREFIX__", $prefix, $item);
|
||||
}, $matches[2]);
|
||||
}
|
||||
}
|
||||
return $tables;
|
||||
}
|
||||
|
||||
/**
|
||||
* 插件显示内容里生成访问插件的url
|
||||
* @param string $url 地址 格式:插件名/控制器/方法
|
||||
* @param array $vars 变量参数
|
||||
* @param bool|string $suffix 生成的URL后缀
|
||||
* @param bool|string $domain 域名
|
||||
* @return bool|string
|
||||
*/
|
||||
function addon_url($url, $vars = [], $suffix = true, $domain = false)
|
||||
{
|
||||
$url = ltrim($url, '/');
|
||||
$addon = substr($url, 0, stripos($url, '/'));
|
||||
if (!is_array($vars)) {
|
||||
parse_str($vars, $params);
|
||||
$vars = $params;
|
||||
}
|
||||
$params = [];
|
||||
foreach ($vars as $k => $v) {
|
||||
if (substr($k, 0, 1) === ':') {
|
||||
$params[$k] = $v;
|
||||
unset($vars[$k]);
|
||||
}
|
||||
}
|
||||
$val = "@addons/{$url}";
|
||||
$config = get_addon_config($addon);
|
||||
$dispatch = think\Request::instance()->dispatch();
|
||||
$indomain = isset($dispatch['var']['indomain']) && $dispatch['var']['indomain'] && $dispatch['var']['addon'] == $addon ? true : false;
|
||||
//优先取插件配置中的domain,没有的情况下取全局的域名前缀配置
|
||||
$domainprefix = $config && isset($config['domain']) && $config['domain'] ? $config['domain'] : Config::get('addons.domain');
|
||||
$domain = $domainprefix && Config::get('url_domain_deploy') ? $domainprefix : $domain;
|
||||
$rewrite = $config && isset($config['rewrite']) && $config['rewrite'] ? $config['rewrite'] : [];
|
||||
if ($rewrite) {
|
||||
$path = substr($url, stripos($url, '/') + 1);
|
||||
if (isset($rewrite[$path]) && $rewrite[$path]) {
|
||||
$val = $rewrite[$path];
|
||||
array_walk($params, function ($value, $key) use (&$val) {
|
||||
$val = str_replace("[{$key}]", $value, $val);
|
||||
});
|
||||
$val = str_replace(['^', '$'], '', $val);
|
||||
if (substr($val, -1) === '/') {
|
||||
$suffix = false;
|
||||
}
|
||||
} else {
|
||||
// 如果采用了域名部署,则需要去掉前两段
|
||||
if ($indomain && $domainprefix) {
|
||||
$arr = explode("/", $val);
|
||||
$val = implode("/", array_slice($arr, 2));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 如果采用了域名部署,则需要去掉前两段
|
||||
if ($indomain && $domainprefix) {
|
||||
$arr = explode("/", $val);
|
||||
$val = implode("/", array_slice($arr, 2));
|
||||
}
|
||||
foreach ($params as $k => $v) {
|
||||
$vars[substr($k, 1)] = $v;
|
||||
}
|
||||
}
|
||||
$url = url($val, [], $suffix, $domain) . ($vars ? '?' . http_build_query($vars) : '');
|
||||
$url = preg_replace("/\/((?!index)[\w]+)\.php\//i", "/", $url);
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置基础配置信息
|
||||
* @param string $name 插件名
|
||||
* @param array $array 配置数据
|
||||
* @return boolean
|
||||
* @throws Exception
|
||||
*/
|
||||
function set_addon_info($name, $array)
|
||||
{
|
||||
$file = ADDON_PATH . $name . DS . 'info.ini';
|
||||
$addon = get_addon_instance($name);
|
||||
$array = $addon->setInfo($name, $array);
|
||||
if (!isset($array['name']) || !isset($array['title']) || !isset($array['version'])) {
|
||||
throw new Exception("插件配置写入失败");
|
||||
}
|
||||
$res = array();
|
||||
foreach ($array as $key => $val) {
|
||||
if (is_array($val)) {
|
||||
$res[] = "[$key]";
|
||||
foreach ($val as $skey => $sval) {
|
||||
$res[] = "$skey = " . (is_numeric($sval) ? $sval : $sval);
|
||||
}
|
||||
} else {
|
||||
$res[] = "$key = " . (is_numeric($val) ? $val : $val);
|
||||
}
|
||||
}
|
||||
if (file_put_contents($file, implode("\n", $res) . "\n", LOCK_EX)) {
|
||||
//清空当前配置缓存
|
||||
Config::set($name, null, 'addoninfo');
|
||||
} else {
|
||||
throw new Exception("文件没有写入权限");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入配置文件
|
||||
* @param string $name 插件名
|
||||
* @param array $config 配置数据
|
||||
* @param boolean $writefile 是否写入配置文件
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
function set_addon_config($name, $config, $writefile = true)
|
||||
{
|
||||
$addon = get_addon_instance($name);
|
||||
$addon->setConfig($name, $config);
|
||||
$fullconfig = get_addon_fullconfig($name);
|
||||
foreach ($fullconfig as $k => &$v) {
|
||||
if (isset($config[$v['name']])) {
|
||||
$value = $v['type'] !== 'array' && is_array($config[$v['name']]) ? implode(',', $config[$v['name']]) : $config[$v['name']];
|
||||
$v['value'] = $value;
|
||||
}
|
||||
}
|
||||
if ($writefile) {
|
||||
// 写入配置文件
|
||||
set_addon_fullconfig($name, $fullconfig);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入配置文件
|
||||
*
|
||||
* @param string $name 插件名
|
||||
* @param array $array 配置数据
|
||||
* @return boolean
|
||||
* @throws Exception
|
||||
*/
|
||||
function set_addon_fullconfig($name, $array)
|
||||
{
|
||||
$file = ADDON_PATH . $name . DS . 'config.php';
|
||||
$ret = file_put_contents($file, "<?php\n\n" . "return " . VarExporter::export($array) . ";\n", LOCK_EX);
|
||||
if (!$ret) {
|
||||
throw new Exception("配置写入失败");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
15
vendor/fastadminnet/fastadmin-addons/src/config.php
vendored
Normal file
15
vendor/fastadminnet/fastadmin-addons/src/config.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | thinkphp5 Addons [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2016 http://www.zzstudio.net All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: Byron Sampson <xiaobo.sun@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
return [
|
||||
'addons_on' => true,
|
||||
];
|
||||
20
vendor/fastadminnet/fastadmin-mailer/LICENSE
vendored
Normal file
20
vendor/fastadminnet/fastadmin-mailer/LICENSE
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013
|
||||
|
||||
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.
|
||||
38
vendor/fastadminnet/fastadmin-mailer/composer.json
vendored
Normal file
38
vendor/fastadminnet/fastadmin-mailer/composer.json
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "fastadminnet/fastadmin-mailer",
|
||||
"type": "library",
|
||||
"keywords": ["mail", "smtp"],
|
||||
"description": "A very lightweight PHP SMTP mail sender",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/fastadminnet/fastadmin-mailer",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Cloud",
|
||||
"email": "cloud@txthinking.com",
|
||||
"homepage": "http://www.txthinking.com",
|
||||
"role": "Thinker"
|
||||
},
|
||||
{
|
||||
"name": "Matt Sowers",
|
||||
"email": "msowers@erblearn.org"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.2",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~5.0",
|
||||
"monolog/monolog": "~1.13"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Tx\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"classmap": [
|
||||
"tests/TestCase.php"
|
||||
]
|
||||
}
|
||||
}
|
||||
209
vendor/fastadminnet/fastadmin-mailer/src/Mailer.php
vendored
Normal file
209
vendor/fastadminnet/fastadmin-mailer/src/Mailer.php
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
/***************************************************\
|
||||
*
|
||||
* Mailer (https://github.com/txthinking/Mailer)
|
||||
*
|
||||
* A lightweight PHP SMTP mail sender.
|
||||
* Implement RFC0821, RFC0822, RFC1869, RFC2045, RFC2821
|
||||
*
|
||||
* Support html body, don't worry that the receiver's
|
||||
* mail client can't support html, because Mailer will
|
||||
* send both text/plain and text/html body, so if the
|
||||
* mail client can't support html, it will display the
|
||||
* text/plain body.
|
||||
*
|
||||
* Create Date 2012-07-25.
|
||||
* Under the MIT license.
|
||||
*
|
||||
\***************************************************/
|
||||
namespace Tx;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use \Tx\Mailer\Message;
|
||||
use \Tx\Mailer\SMTP;
|
||||
|
||||
/**
|
||||
* Class Mailer
|
||||
*
|
||||
* This class provides the Mailer public methods for backwards compatibility, but it is recommended
|
||||
* that you use the Tx\Mailer\SMTP and Tx\Mailer\Message classes going forward
|
||||
*
|
||||
* @package Tx
|
||||
*/
|
||||
class Mailer
|
||||
{
|
||||
/**
|
||||
* SMTP Class
|
||||
* @var SMTP
|
||||
*/
|
||||
protected $smtp;
|
||||
|
||||
/**
|
||||
* Mail Message
|
||||
* @var Message
|
||||
*/
|
||||
protected $message;
|
||||
|
||||
/**
|
||||
* construct function
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function __construct(LoggerInterface $logger=null)
|
||||
{
|
||||
$this->smtp = new SMTP($logger);
|
||||
$this->message = new Message();
|
||||
}
|
||||
|
||||
/**
|
||||
* set server and port
|
||||
* @param string $host server
|
||||
* @param int $port port
|
||||
* @param string $secure ssl tls tlsv1.0 tlsv1.1 tlsv1.2
|
||||
* @return $this
|
||||
*/
|
||||
public function setServer($host, $port, $secure=null)
|
||||
{
|
||||
$this->smtp->setServer($host, $port, $secure);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* auth with server
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return $this
|
||||
*/
|
||||
public function setAuth($username, $password)
|
||||
{
|
||||
$this->smtp->setAuth($username, $password);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* auth oauthbearer with server
|
||||
* @param string $accessToken
|
||||
* @return $this
|
||||
*/
|
||||
public function setOAuth($accessToken)
|
||||
{
|
||||
$this->smtp->setOAuth($accessToken);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set mail from
|
||||
* @param string $name
|
||||
* @param string $email
|
||||
* @return $this
|
||||
*/
|
||||
public function setFrom($name, $email)
|
||||
{
|
||||
$this->message->setFrom($name, $email);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set fake mail from
|
||||
* @param string $name
|
||||
* @param string $email
|
||||
* @return $this
|
||||
*/
|
||||
public function setFakeFrom($name, $email)
|
||||
{
|
||||
$this->message->setFakeFrom($name, $email);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* add mail receiver
|
||||
* @param string $name
|
||||
* @param string $email
|
||||
* @return $this
|
||||
*/
|
||||
public function addTo($name, $email)
|
||||
{
|
||||
$this->message->addTo($name, $email);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* add cc mail receiver
|
||||
* @param string $name
|
||||
* @param string $email
|
||||
* @return $this
|
||||
*/
|
||||
public function addCc($name, $email)
|
||||
{
|
||||
$this->message->addCc($name, $email);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* add bcc mail receiver
|
||||
* @param string $name
|
||||
* @param string $email
|
||||
* @return $this
|
||||
*/
|
||||
public function addBcc($name, $email)
|
||||
{
|
||||
$this->message->addBcc($name, $email);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set mail subject
|
||||
* @param string $subject
|
||||
* @return $this
|
||||
*/
|
||||
public function setSubject($subject)
|
||||
{
|
||||
$this->message->setSubject($subject);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set mail body
|
||||
* @param string $body
|
||||
* @return $this
|
||||
*/
|
||||
public function setBody($body)
|
||||
{
|
||||
$this->message->setBody($body);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* add mail attachment
|
||||
* @param $name
|
||||
* @param $path
|
||||
* @return $this
|
||||
*/
|
||||
public function addAttachment($name, $path)
|
||||
{
|
||||
$this->message->addAttachment($name, $path);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set mail reply-to
|
||||
* @param string $name
|
||||
* @param string $email
|
||||
* @return $this
|
||||
*/
|
||||
public function setReplyTo($name, $email)
|
||||
{
|
||||
$this->message->setReplyTo($name, $email);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the message...
|
||||
* @return boolean
|
||||
*/
|
||||
public function send()
|
||||
{
|
||||
return $this->smtp->send($this->message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
40
vendor/fastadminnet/fastadmin-mailer/src/Mailer/Exceptions/CodeException.php
vendored
Normal file
40
vendor/fastadminnet/fastadmin-mailer/src/Mailer/Exceptions/CodeException.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/***************************************************\
|
||||
*
|
||||
* Mailer (https://github.com/txthinking/Mailer)
|
||||
*
|
||||
* A lightweight PHP SMTP mail sender.
|
||||
* Implement RFC0821, RFC0822, RFC1869, RFC2045, RFC2821
|
||||
*
|
||||
* Support html body, don't worry that the receiver's
|
||||
* mail client can't support html, because Mailer will
|
||||
* send both text/plain and text/html body, so if the
|
||||
* mail client can't support html, it will display the
|
||||
* text/plain body.
|
||||
*
|
||||
* Create Date 2012-07-25.
|
||||
* Under the MIT license.
|
||||
*
|
||||
\***************************************************/
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: msowers
|
||||
* Date: 3/30/15
|
||||
* Time: 2:42 PM
|
||||
*/
|
||||
|
||||
namespace Tx\Mailer\Exceptions;
|
||||
|
||||
|
||||
class CodeException extends SMTPException
|
||||
{
|
||||
public function __construct($expected, $received, $serverMessage = null)
|
||||
{
|
||||
$message = "Unexpected return code - Expected: {$expected}, Got: {$received}";
|
||||
if (isset($serverMessage)) {
|
||||
$message .= " | " . $serverMessage;
|
||||
}
|
||||
parent::__construct($message);
|
||||
}
|
||||
|
||||
}
|
||||
32
vendor/fastadminnet/fastadmin-mailer/src/Mailer/Exceptions/CryptoException.php
vendored
Normal file
32
vendor/fastadminnet/fastadmin-mailer/src/Mailer/Exceptions/CryptoException.php
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/***************************************************\
|
||||
*
|
||||
* Mailer (https://github.com/txthinking/Mailer)
|
||||
*
|
||||
* A lightweight PHP SMTP mail sender.
|
||||
* Implement RFC0821, RFC0822, RFC1869, RFC2045, RFC2821
|
||||
*
|
||||
* Support html body, don't worry that the receiver's
|
||||
* mail client can't support html, because Mailer will
|
||||
* send both text/plain and text/html body, so if the
|
||||
* mail client can't support html, it will display the
|
||||
* text/plain body.
|
||||
*
|
||||
* Create Date 2012-07-25.
|
||||
* Under the MIT license.
|
||||
*
|
||||
\***************************************************/
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: msowers
|
||||
* Date: 3/30/15
|
||||
* Time: 2:48 PM
|
||||
*/
|
||||
|
||||
namespace Tx\Mailer\Exceptions;
|
||||
|
||||
|
||||
class CryptoException extends SMTPException
|
||||
{
|
||||
|
||||
}
|
||||
35
vendor/fastadminnet/fastadmin-mailer/src/Mailer/Exceptions/SMTPException.php
vendored
Normal file
35
vendor/fastadminnet/fastadmin-mailer/src/Mailer/Exceptions/SMTPException.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/***************************************************\
|
||||
*
|
||||
* Mailer (https://github.com/txthinking/Mailer)
|
||||
*
|
||||
* A lightweight PHP SMTP mail sender.
|
||||
* Implement RFC0821, RFC0822, RFC1869, RFC2045, RFC2821
|
||||
*
|
||||
* Support html body, don't worry that the receiver's
|
||||
* mail client can't support html, because Mailer will
|
||||
* send both text/plain and text/html body, so if the
|
||||
* mail client can't support html, it will display the
|
||||
* text/plain body.
|
||||
*
|
||||
* Create Date 2012-07-25.
|
||||
* Under the MIT license.
|
||||
*
|
||||
\***************************************************/
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: msowers
|
||||
* Date: 3/30/15
|
||||
* Time: 1:51 PM
|
||||
*/
|
||||
|
||||
namespace Tx\Mailer\Exceptions;
|
||||
|
||||
class SMTPException extends \Exception
|
||||
{
|
||||
public function __construct($message)
|
||||
{
|
||||
parent::__construct($message);
|
||||
}
|
||||
|
||||
}
|
||||
31
vendor/fastadminnet/fastadmin-mailer/src/Mailer/Exceptions/SendException.php
vendored
Normal file
31
vendor/fastadminnet/fastadmin-mailer/src/Mailer/Exceptions/SendException.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/***************************************************\
|
||||
*
|
||||
* Mailer (https://github.com/txthinking/Mailer)
|
||||
*
|
||||
* A lightweight PHP SMTP mail sender.
|
||||
* Implement RFC0821, RFC0822, RFC1869, RFC2045, RFC2821
|
||||
*
|
||||
* Support html body, don't worry that the receiver's
|
||||
* mail client can't support html, because Mailer will
|
||||
* send both text/plain and text/html body, so if the
|
||||
* mail client can't support html, it will display the
|
||||
* text/plain body.
|
||||
*
|
||||
* Create Date 2012-07-25.
|
||||
* Under the MIT license.
|
||||
*
|
||||
\***************************************************/
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: msowers
|
||||
* Date: 3/30/15
|
||||
* Time: 1:47 PM
|
||||
*/
|
||||
|
||||
namespace Tx\Mailer\Exceptions;
|
||||
|
||||
class SendException extends SMTPException
|
||||
{
|
||||
|
||||
}
|
||||
456
vendor/fastadminnet/fastadmin-mailer/src/Mailer/Message.php
vendored
Normal file
456
vendor/fastadminnet/fastadmin-mailer/src/Mailer/Message.php
vendored
Normal file
@@ -0,0 +1,456 @@
|
||||
<?php
|
||||
/***************************************************\
|
||||
*
|
||||
* Mailer (https://github.com/txthinking/Mailer)
|
||||
*
|
||||
* A lightweight PHP SMTP mail sender.
|
||||
* Implement RFC0821, RFC0822, RFC1869, RFC2045, RFC2821
|
||||
*
|
||||
* Support html body, don't worry that the receiver's
|
||||
* mail client can't support html, because Mailer will
|
||||
* send both text/plain and text/html body, so if the
|
||||
* mail client can't support html, it will display the
|
||||
* text/plain body.
|
||||
*
|
||||
* Create Date 2012-07-25.
|
||||
* Under the MIT license.
|
||||
*
|
||||
\***************************************************/
|
||||
namespace Tx\Mailer;
|
||||
|
||||
class Message
|
||||
{
|
||||
/**
|
||||
* from name
|
||||
*/
|
||||
protected $fromName;
|
||||
|
||||
/**
|
||||
* from email
|
||||
*/
|
||||
protected $fromEmail;
|
||||
|
||||
/**
|
||||
* fake from name
|
||||
*/
|
||||
protected $fakeFromName;
|
||||
|
||||
/**
|
||||
* fake from email
|
||||
*/
|
||||
protected $fakeFromEmail;
|
||||
|
||||
/**
|
||||
* to email
|
||||
*/
|
||||
protected $to = array();
|
||||
|
||||
/**
|
||||
* cc email
|
||||
*/
|
||||
protected $cc = array();
|
||||
|
||||
/**
|
||||
* bcc email
|
||||
*/
|
||||
protected $bcc = array();
|
||||
|
||||
/**
|
||||
* mail subject
|
||||
*/
|
||||
protected $subject;
|
||||
|
||||
/**
|
||||
* mail body
|
||||
*/
|
||||
protected $body;
|
||||
|
||||
/**
|
||||
*mail attachment
|
||||
*/
|
||||
protected $attachment = array();
|
||||
|
||||
/**
|
||||
* message header
|
||||
*/
|
||||
protected $header = array();
|
||||
|
||||
/**
|
||||
* charset
|
||||
*/
|
||||
protected $charset = "UTF-8";
|
||||
|
||||
/**
|
||||
* header multipart boundaryMixed
|
||||
*/
|
||||
protected $boundaryMixed;
|
||||
|
||||
/**
|
||||
* header multipart alternative
|
||||
*/
|
||||
protected $boundaryAlternative;
|
||||
|
||||
/**
|
||||
* $this->CRLF
|
||||
* @var string
|
||||
*/
|
||||
protected $CRLF = "\r\n";
|
||||
|
||||
|
||||
/**
|
||||
* Address for the reply-to header
|
||||
* @var string
|
||||
*/
|
||||
protected $replyToName;
|
||||
|
||||
/**
|
||||
* Address for the reply-to header
|
||||
* @var string
|
||||
*/
|
||||
protected $replyToEmail;
|
||||
|
||||
|
||||
public function setReplyTo($name, $email)
|
||||
{
|
||||
$this->replyToName = $name;
|
||||
$this->replyToEmail = $email;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set mail from
|
||||
* @param string $name
|
||||
* @param string $email
|
||||
* @return $this
|
||||
*/
|
||||
public function setFrom($name, $email)
|
||||
{
|
||||
$this->fromName = $name;
|
||||
$this->fromEmail = $email;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set mail fake from
|
||||
* @param string $name
|
||||
* @param string $email
|
||||
* @return $this
|
||||
*/
|
||||
public function setFakeFrom($name, $email)
|
||||
{
|
||||
$this->fakeFromName = $name;
|
||||
$this->fakeFromEmail = $email;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* add mail receiver
|
||||
* @param string $name
|
||||
* @param string $email
|
||||
* @return $this
|
||||
*/
|
||||
public function addTo($name, $email)
|
||||
{
|
||||
$this->to[$email] = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* add cc mail receiver
|
||||
* @param string $name
|
||||
* @param string $email
|
||||
* @return $this
|
||||
*/
|
||||
public function addCc($name, $email)
|
||||
{
|
||||
$this->cc[$email] = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* add bcc mail receiver
|
||||
* @param string $name
|
||||
* @param string $email
|
||||
* @return $this
|
||||
*/
|
||||
public function addBcc($name, $email)
|
||||
{
|
||||
$this->bcc[$email] = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set mail subject
|
||||
* @param string $subject
|
||||
* @return $this
|
||||
*/
|
||||
public function setSubject($subject)
|
||||
{
|
||||
$this->subject = $subject;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set mail body
|
||||
* @param string $body
|
||||
* @return $this
|
||||
*/
|
||||
public function setBody($body)
|
||||
{
|
||||
$this->body = $body;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* add mail attachment
|
||||
* @param $name
|
||||
* @param $path
|
||||
* @return $this
|
||||
*/
|
||||
public function addAttachment($name, $path)
|
||||
{
|
||||
$this->attachment[$name] = $path;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFromName()
|
||||
{
|
||||
return $this->fromName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFromEmail()
|
||||
{
|
||||
return $this->fromEmail;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFakeFromName()
|
||||
{
|
||||
return $this->fakeFromName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFakeFromEmail()
|
||||
{
|
||||
return $this->fakeFromEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTo()
|
||||
{
|
||||
return $this->to;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCc()
|
||||
{
|
||||
return $this->cc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getBcc()
|
||||
{
|
||||
return $this->bcc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSubject()
|
||||
{
|
||||
return $this->subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getBody()
|
||||
{
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAttachment()
|
||||
{
|
||||
return $this->attachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create mail header
|
||||
* @return $this
|
||||
*/
|
||||
protected function createHeader()
|
||||
{
|
||||
$this->header['Date'] = date('r');
|
||||
|
||||
$fromName = "";
|
||||
$fromEmail = $this->fromEmail;
|
||||
if(!empty($this->fromName)){
|
||||
$fromName = sprintf("=?utf-8?B?%s?= ", base64_encode($this->fromName));
|
||||
}
|
||||
if(!empty($this->fakeFromEmail)){
|
||||
if(!empty($this->fakeFromName)){
|
||||
$fromName = sprintf("=?utf-8?B?%s?= ", base64_encode($this->fakeFromName));
|
||||
}
|
||||
$fromEmail = $this->fakeFromEmail;
|
||||
}
|
||||
$this->header['Return-Path'] = $fromEmail;
|
||||
$this->header['From'] = $fromName . "<" . $fromEmail .">";
|
||||
|
||||
$this->header['To'] = '';
|
||||
foreach ($this->to as $toEmail => $toName) {
|
||||
if(!empty($toName)){
|
||||
$toName = sprintf("=?utf-8?B?%s?= ", base64_encode($toName));
|
||||
}
|
||||
$this->header['To'] .= $toName . "<" . $toEmail . ">, ";
|
||||
}
|
||||
$this->header['To'] = substr($this->header['To'], 0, -2);
|
||||
$this->header['Cc'] = '';
|
||||
foreach ($this->cc as $toEmail => $toName) {
|
||||
if(!empty($toName)){
|
||||
$toName = sprintf("=?utf-8?B?%s?= ", base64_encode($toName));
|
||||
}
|
||||
$this->header['Cc'] .= $toName . "<" . $toEmail . ">, ";
|
||||
}
|
||||
$this->header['Cc'] = substr($this->header['Cc'], 0, -2);
|
||||
$this->header['Bcc'] = '';
|
||||
foreach ($this->bcc as $toEmail => $toName) {
|
||||
if(!empty($toName)){
|
||||
$toName = sprintf("=?utf-8?B?%s?= ", base64_encode($toName));
|
||||
}
|
||||
$this->header['Bcc'] .= $toName . "<" . $toEmail . ">, ";
|
||||
}
|
||||
$this->header['Bcc'] = substr($this->header['Bcc'], 0, -2);
|
||||
|
||||
$replyToName = "";
|
||||
if(!empty($this->replyToEmail)){
|
||||
if(!empty($this->replyToName)){
|
||||
$replyToName = sprintf("=?utf-8?B?%s?= ", base64_encode($this->replyToName));
|
||||
}
|
||||
$this->header['Reply-To'] = $replyToName . "<" . $this->replyToEmail . ">";
|
||||
}
|
||||
|
||||
if(empty($this->subject)){
|
||||
$subject = '';
|
||||
}else{
|
||||
$subject = sprintf("=?utf-8?B?%s?= ", base64_encode($this->subject));
|
||||
}
|
||||
$this->header['Subject'] = $subject;
|
||||
|
||||
$this->header['Message-ID'] = '<' . md5(uniqid()) . $this->fromEmail . '>';
|
||||
$this->header['X-Priority'] = '3';
|
||||
$this->header['X-Mailer'] = 'Mailer (https://github.com/txthinking/Mailer)';
|
||||
$this->header['MIME-Version'] = '1.0';
|
||||
if (!empty($this->attachment)){
|
||||
$this->boundaryMixed = md5(md5(time().'TxMailer').uniqid());
|
||||
$this->header['Content-Type'] = "multipart/mixed; \r\n\tboundary=\"" . $this->boundaryMixed . "\"";
|
||||
}
|
||||
$this->boundaryAlternative = md5(md5(time().'TXMailer').uniqid());
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief createBody create body
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createBody()
|
||||
{
|
||||
$in = "";
|
||||
$in .= "Content-Type: multipart/alternative; boundary=\"$this->boundaryAlternative\"" . $this->CRLF;
|
||||
$in .= $this->CRLF;
|
||||
$in .= "--" . $this->boundaryAlternative . $this->CRLF;
|
||||
$in .= "Content-Type: text/plain; charset=\"" . $this->charset . "\"" . $this->CRLF;
|
||||
$in .= "Content-Transfer-Encoding: base64" . $this->CRLF;
|
||||
$in .= $this->CRLF;
|
||||
$in .= chunk_split(base64_encode($this->body)) . $this->CRLF;
|
||||
$in .= $this->CRLF;
|
||||
$in .= "--" . $this->boundaryAlternative . $this->CRLF;
|
||||
$in .= "Content-Type: text/html; charset=\"" . $this->charset ."\"" . $this->CRLF;
|
||||
$in .= "Content-Transfer-Encoding: base64" . $this->CRLF;
|
||||
$in .= $this->CRLF;
|
||||
$in .= chunk_split(base64_encode($this->body)) . $this->CRLF;
|
||||
$in .= $this->CRLF;
|
||||
$in .= "--" . $this->boundaryAlternative . "--" . $this->CRLF;
|
||||
return $in;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief createBodyWithAttachment create body with attachment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createBodyWithAttachment()
|
||||
{
|
||||
$in = "";
|
||||
$in .= $this->CRLF;
|
||||
$in .= $this->CRLF;
|
||||
$in .= '--' . $this->boundaryMixed . $this->CRLF;
|
||||
$in .= "Content-Type: multipart/alternative; boundary=\"$this->boundaryAlternative\"" . $this->CRLF;
|
||||
$in .= $this->CRLF;
|
||||
$in .= "--" . $this->boundaryAlternative . $this->CRLF;
|
||||
$in .= "Content-Type: text/plain; charset=\"" . $this->charset . "\"" . $this->CRLF;
|
||||
$in .= "Content-Transfer-Encoding: base64" . $this->CRLF;
|
||||
$in .= $this->CRLF;
|
||||
$in .= chunk_split(base64_encode($this->body)) . $this->CRLF;
|
||||
$in .= $this->CRLF;
|
||||
$in .= "--" . $this->boundaryAlternative . $this->CRLF;
|
||||
$in .= "Content-Type: text/html; charset=\"" . $this->charset ."\"" . $this->CRLF;
|
||||
$in .= "Content-Transfer-Encoding: base64" . $this->CRLF;
|
||||
$in .= $this->CRLF;
|
||||
$in .= chunk_split(base64_encode($this->body)) . $this->CRLF;
|
||||
$in .= $this->CRLF;
|
||||
$in .= "--" . $this->boundaryAlternative . "--" . $this->CRLF;
|
||||
foreach ($this->attachment as $name => $path){
|
||||
$in .= $this->CRLF;
|
||||
$in .= '--' . $this->boundaryMixed . $this->CRLF;
|
||||
$in .= "Content-Type: application/octet-stream; name=\"". $name ."\"" . $this->CRLF;
|
||||
$in .= "Content-Transfer-Encoding: base64" . $this->CRLF;
|
||||
$in .= "Content-Disposition: attachment; filename=\"" . $name . "\"" . $this->CRLF;
|
||||
$in .= $this->CRLF;
|
||||
$in .= chunk_split(base64_encode(file_get_contents($path))) . $this->CRLF;
|
||||
}
|
||||
$in .= $this->CRLF;
|
||||
$in .= $this->CRLF;
|
||||
$in .= '--' . $this->boundaryMixed . '--' . $this->CRLF;
|
||||
return $in;
|
||||
}
|
||||
|
||||
public function toString()
|
||||
{
|
||||
$in = '';
|
||||
$this->createHeader();
|
||||
foreach ($this->header as $key => $value) {
|
||||
$in .= $key . ': ' . $value . $this->CRLF;
|
||||
}
|
||||
if (empty($this->attachment)) {
|
||||
$in .= $this->createBody();
|
||||
} else {
|
||||
$in .= $this->createBodyWithAttachment();
|
||||
}
|
||||
$in .= $this->CRLF . $this->CRLF . "." . $this->CRLF;
|
||||
return $in;
|
||||
}
|
||||
|
||||
}
|
||||
492
vendor/fastadminnet/fastadmin-mailer/src/Mailer/SMTP.php
vendored
Normal file
492
vendor/fastadminnet/fastadmin-mailer/src/Mailer/SMTP.php
vendored
Normal file
@@ -0,0 +1,492 @@
|
||||
<?php
|
||||
/***************************************************\
|
||||
*
|
||||
* Mailer (https://github.com/txthinking/Mailer)
|
||||
*
|
||||
* A lightweight PHP SMTP mail sender.
|
||||
* Implement RFC0821, RFC0822, RFC1869, RFC2045, RFC2821
|
||||
*
|
||||
* Support html body, don't worry that the receiver's
|
||||
* mail client can't support html, because Mailer will
|
||||
* send both text/plain and text/html body, so if the
|
||||
* mail client can't support html, it will display the
|
||||
* text/plain body.
|
||||
*
|
||||
* Create Date 2012-07-25.
|
||||
* Under the MIT license.
|
||||
*
|
||||
\***************************************************/
|
||||
|
||||
namespace Tx\Mailer;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Tx\Mailer\Exceptions\CodeException;
|
||||
use Tx\Mailer\Exceptions\CryptoException;
|
||||
use Tx\Mailer\Exceptions\SMTPException;
|
||||
|
||||
class SMTP
|
||||
{
|
||||
/**
|
||||
* smtp socket
|
||||
*/
|
||||
protected $smtp;
|
||||
|
||||
/**
|
||||
* smtp server
|
||||
*/
|
||||
protected $host;
|
||||
|
||||
/**
|
||||
* smtp server port
|
||||
*/
|
||||
protected $port;
|
||||
|
||||
/**
|
||||
* smtp secure ssl tls tlsv1.0 tlsv1.1 tlsv1.2
|
||||
*/
|
||||
protected $secure;
|
||||
|
||||
/**
|
||||
* smtp allow insecure ssl
|
||||
*/
|
||||
protected $allowInsecure;
|
||||
|
||||
/**
|
||||
* EHLO message
|
||||
*/
|
||||
protected $ehlo;
|
||||
|
||||
/**
|
||||
* smtp username
|
||||
*/
|
||||
protected $username;
|
||||
|
||||
/**
|
||||
* smtp password
|
||||
*/
|
||||
protected $password;
|
||||
|
||||
/**
|
||||
* oauth access token
|
||||
*/
|
||||
protected $oauthToken;
|
||||
|
||||
/**
|
||||
* $this->CRLF
|
||||
* @var string
|
||||
*/
|
||||
protected $CRLF = "\r\n";
|
||||
|
||||
/**
|
||||
* @var Message
|
||||
*/
|
||||
protected $message;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface - Used to make things prettier than self::$logger
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Stack of all commands issued to SMTP
|
||||
* @var array
|
||||
*/
|
||||
protected $commandStack = array();
|
||||
|
||||
/**
|
||||
* Stack of all results issued to SMTP
|
||||
* @var array
|
||||
*/
|
||||
protected $resultStack = array();
|
||||
|
||||
public function __construct(LoggerInterface $logger=null)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* set server and port
|
||||
* @param string $host server
|
||||
* @param int $port port
|
||||
* @param string $secure ssl tls tlsv1.0 tlsv1.1 tlsv1.2
|
||||
* @return $this
|
||||
*/
|
||||
public function setServer($host, $port, $secure=null, $allowInsecure=null)
|
||||
{
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->secure = $secure;
|
||||
$this->allowInsecure = $allowInsecure;
|
||||
if(!$this->ehlo) $this->ehlo = $host;
|
||||
$this->logger && $this->logger->debug("Set: the server");
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* auth login with server
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return $this
|
||||
*/
|
||||
public function setAuth($username, $password)
|
||||
{
|
||||
$this->username = $username;
|
||||
$this->password = $password;
|
||||
$this->logger && $this->logger->debug("Set: the auth login");
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* auth oauthbearer with server
|
||||
* @param string $accessToken
|
||||
* @return $this
|
||||
*/
|
||||
public function setOAuth($accessToken)
|
||||
{
|
||||
$this->oauthToken = $accessToken;
|
||||
$this->logger && $this->logger->debug("Set: the auth oauthbearer");
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the EHLO message
|
||||
* @param $ehlo
|
||||
* @return $this
|
||||
*/
|
||||
public function setEhlo($ehlo)
|
||||
{
|
||||
$this->ehlo = $ehlo;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the message
|
||||
*
|
||||
* @param Message $message
|
||||
* @return bool
|
||||
* @throws CodeException
|
||||
* @throws CryptoException
|
||||
* @throws SMTPException
|
||||
*/
|
||||
public function send(Message $message)
|
||||
{
|
||||
$this->logger && $this->logger->debug('Set: a message will be sent');
|
||||
$this->message = $message;
|
||||
$this->connect()
|
||||
->ehlo();
|
||||
|
||||
if ($this->secure === 'tls' || $this->secure === 'tlsv1.0' || $this->secure === 'tlsv1.1' | $this->secure === 'tlsv1.2') {
|
||||
$this->starttls()
|
||||
->ehlo();
|
||||
}
|
||||
|
||||
if ($this->username !== null || $this->password !== null) {
|
||||
$this->authLogin();
|
||||
} elseif ($this->oauthToken !== null) {
|
||||
$this->authOAuthBearer();
|
||||
}
|
||||
$this->mailFrom()
|
||||
->rcptTo()
|
||||
->data()
|
||||
->quit();
|
||||
return fclose($this->smtp);
|
||||
}
|
||||
|
||||
/**
|
||||
* connect the server
|
||||
* SUCCESS 220
|
||||
* @return $this
|
||||
* @throws CodeException
|
||||
* @throws SMTPException
|
||||
*/
|
||||
protected function connect()
|
||||
{
|
||||
$this->logger && $this->logger->debug("Connecting to {$this->host} at {$this->port}");
|
||||
$host = ($this->secure == 'ssl') ? 'ssl://' . $this->host : $this->host;
|
||||
// Create connection
|
||||
$context = null;
|
||||
if ($this->allowInsecure) {
|
||||
$context = stream_context_create([
|
||||
'ssl' => [
|
||||
'security_level' => 0,
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false
|
||||
]
|
||||
]);
|
||||
} else {
|
||||
$context = stream_context_create();
|
||||
}
|
||||
$this->smtp = stream_socket_client(
|
||||
$host.':'.$this->port,
|
||||
$error_code,
|
||||
$error_message,
|
||||
ini_get('default_socket_timeout'),
|
||||
STREAM_CLIENT_CONNECT,
|
||||
$context
|
||||
);
|
||||
//set block mode
|
||||
// stream_set_blocking($this->smtp, 1);
|
||||
if (!$this->smtp){
|
||||
throw new SMTPException("Could not open SMTP Port.");
|
||||
}
|
||||
$code = $this->getCode();
|
||||
if ($code !== '220'){
|
||||
throw new CodeException('220', $code, array_pop($this->resultStack));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* SMTP STARTTLS
|
||||
* SUCCESS 220
|
||||
* @return $this
|
||||
* @throws CodeException
|
||||
* @throws CryptoException
|
||||
* @throws SMTPException
|
||||
*/
|
||||
protected function starttls()
|
||||
{
|
||||
$in = "STARTTLS" . $this->CRLF;
|
||||
$code = $this->pushStack($in);
|
||||
if ($code !== '220'){
|
||||
throw new CodeException('220', $code, array_pop($this->resultStack));
|
||||
}
|
||||
|
||||
if ($this->secure !== 'tls' && version_compare(phpversion(), '5.6.0', '<')) {
|
||||
throw new CryptoException('Crypto type expected PHP 5.6 or greater');
|
||||
}
|
||||
|
||||
switch ($this->secure) {
|
||||
case 'tlsv1.0':
|
||||
$crypto_type = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT;
|
||||
break;
|
||||
case 'tlsv1.1':
|
||||
$crypto_type = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
|
||||
break;
|
||||
case 'tlsv1.2':
|
||||
$crypto_type = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
|
||||
break;
|
||||
default:
|
||||
$crypto_type = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT |
|
||||
STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT |
|
||||
STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!\stream_socket_enable_crypto($this->smtp, true, $crypto_type)) {
|
||||
throw new CryptoException("Start TLS failed to enable crypto");
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* SMTP EHLO
|
||||
* SUCCESS 250
|
||||
* @return $this
|
||||
* @throws CodeException
|
||||
* @throws SMTPException
|
||||
*/
|
||||
protected function ehlo()
|
||||
{
|
||||
$in = "EHLO " . $this->ehlo . $this->CRLF;
|
||||
$code = $this->pushStack($in);
|
||||
if ($code !== '250'){
|
||||
throw new CodeException('250', $code, array_pop($this->resultStack));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* SMTP AUTH LOGIN
|
||||
* SUCCESS 334
|
||||
* SUCCESS 334
|
||||
* SUCCESS 235
|
||||
* @return $this
|
||||
* @throws CodeException
|
||||
* @throws SMTPException
|
||||
*/
|
||||
protected function authLogin()
|
||||
{
|
||||
$in = "AUTH LOGIN" . $this->CRLF;
|
||||
$code = $this->pushStack($in);
|
||||
if ($code !== '334'){
|
||||
throw new CodeException('334', $code, array_pop($this->resultStack));
|
||||
}
|
||||
$in = base64_encode($this->username) . $this->CRLF;
|
||||
$code = $this->pushStack($in);
|
||||
if ($code !== '334'){
|
||||
throw new CodeException('334', $code, array_pop($this->resultStack));
|
||||
}
|
||||
$in = base64_encode($this->password) . $this->CRLF;
|
||||
$code = $this->pushStack($in);
|
||||
if ($code !== '235'){
|
||||
throw new CodeException('235', $code, array_pop($this->resultStack));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* SMTP AUTH OAUTHBEARER
|
||||
* SUCCESS 235
|
||||
* @return $this
|
||||
* @throws CodeException
|
||||
* @throws SMTPException
|
||||
*/
|
||||
protected function authOAuthBearer()
|
||||
{
|
||||
$authStr = sprintf("n,a=%s,%shost=%s%sport=%s%sauth=Bearer %s%s%s",
|
||||
$this->message->getFromEmail(),
|
||||
chr(1),
|
||||
$this->host,
|
||||
chr(1),
|
||||
$this->port,
|
||||
chr(1),
|
||||
$this->oauthToken,
|
||||
chr(1),
|
||||
chr(1)
|
||||
);
|
||||
$authStr = base64_encode($authStr);
|
||||
$in = "AUTH OAUTHBEARER $authStr" . $this->CRLF;
|
||||
$code = $this->pushStack($in);
|
||||
if ($code !== '235'){
|
||||
throw new CodeException('235', $code, array_pop($this->resultStack));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* SMTP AUTH XOAUTH2
|
||||
* SUCCESS 235
|
||||
* @return $this
|
||||
* @throws CodeException
|
||||
* @throws SMTPException
|
||||
*/
|
||||
protected function authXOAuth2()
|
||||
{
|
||||
$authStr = sprintf("user=%s%sauth=Bearer %s%s%s",
|
||||
$this->message->getFromEmail(),
|
||||
chr(1),
|
||||
$this->oauthToken,
|
||||
chr(1),
|
||||
chr(1)
|
||||
);
|
||||
$authStr = base64_encode($authStr);
|
||||
$in = "AUTH XOAUTH2 $authStr" . $this->CRLF;
|
||||
$code = $this->pushStack($in);
|
||||
if ($code !== '235'){
|
||||
throw new CodeException('235', $code, array_pop($this->resultStack));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* SMTP MAIL FROM
|
||||
* SUCCESS 250
|
||||
* @return $this
|
||||
* @throws CodeException
|
||||
* @throws SMTPException
|
||||
*/
|
||||
protected function mailFrom()
|
||||
{
|
||||
$in = "MAIL FROM:<{$this->message->getFromEmail()}>" . $this->CRLF;
|
||||
$code = $this->pushStack($in);
|
||||
if ($code !== '250') {
|
||||
throw new CodeException('250', $code, array_pop($this->resultStack));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* SMTP RCPT TO
|
||||
* SUCCESS 250
|
||||
* @return $this
|
||||
* @throws CodeException
|
||||
* @throws SMTPException
|
||||
*/
|
||||
protected function rcptTo()
|
||||
{
|
||||
$to = array_merge(
|
||||
$this->message->getTo(),
|
||||
$this->message->getCc(),
|
||||
$this->message->getBcc()
|
||||
);
|
||||
foreach ($to as $toEmail=>$_) {
|
||||
$in = "RCPT TO:<" . $toEmail . ">" . $this->CRLF;
|
||||
$code = $this->pushStack($in);
|
||||
if ($code !== '250') {
|
||||
throw new CodeException('250', $code, array_pop($this->resultStack));
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* SMTP DATA
|
||||
* SUCCESS 354
|
||||
* SUCCESS 250
|
||||
* @return $this
|
||||
* @throws CodeException
|
||||
* @throws SMTPException
|
||||
*/
|
||||
protected function data()
|
||||
{
|
||||
$in = "DATA" . $this->CRLF;
|
||||
$code = $this->pushStack($in);
|
||||
if ($code !== '354') {
|
||||
throw new CodeException('354', $code, array_pop($this->resultStack));
|
||||
}
|
||||
$in = $this->message->toString();
|
||||
$code = $this->pushStack($in);
|
||||
if ($code !== '250'){
|
||||
throw new CodeException('250', $code, array_pop($this->resultStack));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* SMTP QUIT
|
||||
* SUCCESS 221
|
||||
* @return $this
|
||||
* @throws CodeException
|
||||
* @throws SMTPException
|
||||
*/
|
||||
protected function quit()
|
||||
{
|
||||
$in = "QUIT" . $this->CRLF;
|
||||
$code = $this->pushStack($in);
|
||||
if ($code !== '221'){
|
||||
throw new CodeException('221', $code, array_pop($this->resultStack));
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function pushStack($string)
|
||||
{
|
||||
$this->commandStack[] = $string;
|
||||
fputs($this->smtp, $string, strlen($string));
|
||||
$this->logger && $this->logger->debug('Sent: '. $string);
|
||||
return $this->getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* get smtp response code
|
||||
* once time has three digital and a space
|
||||
* @return string
|
||||
* @throws SMTPException
|
||||
*/
|
||||
protected function getCode()
|
||||
{
|
||||
while ($str = fgets($this->smtp, 515)) {
|
||||
$this->logger && $this->logger->debug("Got: ". $str);
|
||||
$this->resultStack[] = $str;
|
||||
$str = ltrim($str);
|
||||
if(substr($str,3,1) == " ") {
|
||||
$code = substr($str,0,3);
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
throw new SMTPException("SMTP Server did not respond with anything I recognized");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user