Refactor codes
This commit is contained in:
+4
-9
@@ -1,18 +1,13 @@
|
||||
<?php
|
||||
/*
|
||||
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
|
||||
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
|
||||
Site: http://scripts.incutio.com/xmlrpc/
|
||||
Manual: http://scripts.incutio.com/xmlrpc/manual.php
|
||||
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
|
||||
*/
|
||||
|
||||
namespace IXR;
|
||||
|
||||
/**
|
||||
* IXR Base64编码
|
||||
*
|
||||
* @package IXR
|
||||
*/
|
||||
class IXR_Base64
|
||||
class Base64
|
||||
{
|
||||
/**
|
||||
* 编码数据
|
||||
@@ -26,7 +21,7 @@ class IXR_Base64
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function __construct($data)
|
||||
public function __construct(string $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
+65
-76
@@ -1,11 +1,9 @@
|
||||
<?php
|
||||
/*
|
||||
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
|
||||
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
|
||||
Site: http://scripts.incutio.com/xmlrpc/
|
||||
Manual: http://scripts.incutio.com/xmlrpc/manual.php
|
||||
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
|
||||
*/
|
||||
|
||||
namespace IXR;
|
||||
|
||||
use Typecho\Common;
|
||||
use Typecho\Http\Client as HttpClient;
|
||||
|
||||
/**
|
||||
* IXR客户端
|
||||
@@ -13,10 +11,10 @@
|
||||
*
|
||||
* @package IXR
|
||||
*/
|
||||
class IXR_Client
|
||||
class Client
|
||||
{
|
||||
/** 默认客户端 */
|
||||
const DEFAULT_USERAGENT = 'The Incutio XML-RPC PHP Library(Reload By Typecho)';
|
||||
private const DEFAULT_USERAGENT = 'Typecho XML-RPC PHP Library';
|
||||
|
||||
/**
|
||||
* 服务端地址
|
||||
@@ -58,21 +56,12 @@ class IXR_Client
|
||||
*/
|
||||
private $useragent;
|
||||
|
||||
/**
|
||||
* 回执结构体
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $response;
|
||||
|
||||
/**
|
||||
* 消息体
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
* @var Message
|
||||
*/
|
||||
private $message = false;
|
||||
private $message;
|
||||
|
||||
/**
|
||||
* 调试开关
|
||||
@@ -86,48 +75,53 @@ class IXR_Client
|
||||
* 请求前缀
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
* @var string|null
|
||||
*/
|
||||
private $prefix = NULL;
|
||||
private $prefix = null;
|
||||
|
||||
// Storage place for an error message
|
||||
private $error = false;
|
||||
/**
|
||||
* @var Error
|
||||
*/
|
||||
private $error;
|
||||
|
||||
/**
|
||||
* 客户端构造函数
|
||||
*
|
||||
* @access public
|
||||
* @param string $server 服务端地址
|
||||
* @param string $path 路径名称
|
||||
* @param string|null $path 路径名称
|
||||
* @param integer $port 端口名称
|
||||
* @param string $useragent 客户端
|
||||
* @param string|null $useragent 客户端
|
||||
* @param string|null $prefix
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($server, $path = false, $port = 80, $useragent = self::DEFAULT_USERAGENT, $prefix = NULL)
|
||||
{
|
||||
public function construct(
|
||||
string $server,
|
||||
?string $path = null,
|
||||
int $port = 80,
|
||||
string $useragent = self::DEFAULT_USERAGENT,
|
||||
?string $prefix = null
|
||||
) {
|
||||
if (!$path) {
|
||||
$this->url = $server;
|
||||
|
||||
// Assume we have been given a Url instead
|
||||
$bits = parse_url($server);
|
||||
$this->server = $bits['host'];
|
||||
$this->port = isset($bits['port']) ? $bits['port'] : 80;
|
||||
$this->path = isset($bits['path']) ? $bits['path'] : '/';
|
||||
$this->port = $bits['port'] ?? 80;
|
||||
$this->path = $bits['path'] ?? '/';
|
||||
|
||||
// Make absolutely sure we have a path
|
||||
if (isset($bits['query'])) {
|
||||
$this->path .= '?' . $bits['query'];
|
||||
}
|
||||
} else {
|
||||
/** Typecho_Common */
|
||||
require_once 'Typecho/Common.php';
|
||||
|
||||
$this->url = Typecho_Common::buildUrl(array(
|
||||
'scheme' => 'http',
|
||||
'host' => $server,
|
||||
'path' => $path,
|
||||
'port' => $port
|
||||
));
|
||||
$this->url = Common::buildUrl([
|
||||
'scheme' => 'http',
|
||||
'host' => $server,
|
||||
'path' => $path,
|
||||
'port' => $port
|
||||
]);
|
||||
|
||||
$this->server = $server;
|
||||
$this->path = $path;
|
||||
@@ -144,7 +138,7 @@ class IXR_Client
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __setDebug()
|
||||
public function setDebug()
|
||||
{
|
||||
$this->debug = true;
|
||||
}
|
||||
@@ -152,44 +146,44 @@ class IXR_Client
|
||||
/**
|
||||
* 执行请求
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @param string $method
|
||||
* @param ...$args
|
||||
* @return bool
|
||||
* @throws HttpClient\Exception
|
||||
*/
|
||||
public function __rpcCall()
|
||||
private function rpcCall(string $method, ...$args): bool
|
||||
{
|
||||
$args = func_get_args();
|
||||
$method = array_shift($args);
|
||||
$request = new IXR_Request($method, $args);
|
||||
$request = new Request($method, $args);
|
||||
$xml = $request->getXml();
|
||||
|
||||
$client = Typecho_Http_Client::get();
|
||||
$client = HttpClient::get();
|
||||
if (!$client) {
|
||||
$this->error = new IXR_Error(-32300, 'transport error - could not open socket');
|
||||
$this->error = new Error(-32300, 'transport error - could not open socket');
|
||||
return false;
|
||||
}
|
||||
|
||||
$client->setHeader('Content-Type', 'text/xml')
|
||||
->setHeader('User-Agent', $this->useragent)
|
||||
->setData($xml)
|
||||
->send($this->url);
|
||||
->setHeader('User-Agent', $this->useragent)
|
||||
->setData($xml)
|
||||
->send($this->url);
|
||||
|
||||
$contents = $client->getResponseBody();
|
||||
|
||||
if ($this->debug) {
|
||||
echo '<pre>'.htmlspecialchars($contents)."\n</pre>\n\n";
|
||||
echo '<pre>' . htmlspecialchars($contents) . "\n</pre>\n\n";
|
||||
}
|
||||
|
||||
// Now parse what we've got back
|
||||
$this->message = new IXR_Message($contents);
|
||||
$this->message = new Message($contents);
|
||||
if (!$this->message->parse()) {
|
||||
// XML error
|
||||
$this->error = new IXR_Error(-32700, 'parse error. not well formed');
|
||||
$this->error = new Error(-32700, 'parse error. not well formed');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Is the message a fault?
|
||||
if ($this->message->messageType == 'fault') {
|
||||
$this->error = new IXR_Error($this->message->faultCode, $this->message->faultString);
|
||||
$this->error = new Error($this->message->faultCode, $this->message->faultString);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -205,40 +199,38 @@ class IXR_Client
|
||||
*
|
||||
* @access public
|
||||
* @param string $prefix 前缀
|
||||
* @return IXR_Client
|
||||
* @return Client
|
||||
*/
|
||||
public function __get($prefix)
|
||||
public function get(string $prefix): Client
|
||||
{
|
||||
return new IXR_Client($this->server, $this->path, $this->port, $this->useragent, $this->prefix . $prefix . '.');
|
||||
return new self($this->server, $this->path, $this->port, $this->useragent, $this->prefix . $prefix . '.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加魔术特性
|
||||
* by 70
|
||||
*
|
||||
* @access public
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
array_unshift($args, $this->prefix . $method);
|
||||
$return = call_user_func_array(array($this, '__rpcCall'), $args);
|
||||
$return = call_user_func_array([$this, 'rpcCall'], $args);
|
||||
|
||||
if ($return) {
|
||||
return $this->__getResponse();
|
||||
return $this->getResponse();
|
||||
} else {
|
||||
require_once 'IXR/Exception.php';
|
||||
throw new IXR_Exception($this->__getErrorMessage(), $this->__getErrorCode());
|
||||
throw new Exception($this->getErrorMessage(), $this->getErrorCode());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得返回值
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @return mixed
|
||||
*/
|
||||
public function __getResponse()
|
||||
public function getResponse()
|
||||
{
|
||||
// methodResponses can only have one param - return that
|
||||
return $this->message->params[0];
|
||||
@@ -247,21 +239,19 @@ class IXR_Client
|
||||
/**
|
||||
* 是否为错误
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
public function __isError()
|
||||
public function isError(): bool
|
||||
{
|
||||
return (is_object($this->error));
|
||||
return isset($this->error);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取错误代码
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @return int
|
||||
*/
|
||||
public function __getErrorCode()
|
||||
private function getErrorCode(): int
|
||||
{
|
||||
return $this->error->code;
|
||||
}
|
||||
@@ -269,10 +259,9 @@ class IXR_Client
|
||||
/**
|
||||
* 获取错误消息
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @return string
|
||||
*/
|
||||
public function __getErrorMessage()
|
||||
private function getErrorMessage(): string
|
||||
{
|
||||
return $this->error->message;
|
||||
}
|
||||
|
||||
+54
-23
@@ -1,33 +1,44 @@
|
||||
<?php
|
||||
/*
|
||||
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
|
||||
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
|
||||
Site: http://scripts.incutio.com/xmlrpc/
|
||||
Manual: http://scripts.incutio.com/xmlrpc/manual.php
|
||||
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
|
||||
*/
|
||||
|
||||
namespace IXR;
|
||||
|
||||
/**
|
||||
* IXR日期
|
||||
*
|
||||
* @package IXR
|
||||
*/
|
||||
class IXR_Date {
|
||||
var $year;
|
||||
var $month;
|
||||
var $day;
|
||||
var $hour;
|
||||
var $minute;
|
||||
var $second;
|
||||
function __construct($time) {
|
||||
class Date
|
||||
{
|
||||
private $year;
|
||||
|
||||
private $month;
|
||||
|
||||
private $day;
|
||||
|
||||
private $hour;
|
||||
|
||||
private $minute;
|
||||
|
||||
private $second;
|
||||
|
||||
/**
|
||||
* @param int|string $time
|
||||
*/
|
||||
public function __construct($time)
|
||||
{
|
||||
// $time can be a PHP timestamp or an ISO one
|
||||
if (is_numeric($time)) {
|
||||
$this->parseTimestamp($time);
|
||||
$this->parseTimestamp(intval($time));
|
||||
} else {
|
||||
$this->parseIso($time);
|
||||
}
|
||||
}
|
||||
function parseTimestamp($timestamp) {
|
||||
|
||||
/**
|
||||
* @param int $timestamp
|
||||
*/
|
||||
private function parseTimestamp(int $timestamp)
|
||||
{
|
||||
$this->year = date('Y', $timestamp);
|
||||
$this->month = date('m', $timestamp);
|
||||
$this->day = date('d', $timestamp);
|
||||
@@ -35,7 +46,12 @@ class IXR_Date {
|
||||
$this->minute = date('i', $timestamp);
|
||||
$this->second = date('s', $timestamp);
|
||||
}
|
||||
function parseIso($iso) {
|
||||
|
||||
/**
|
||||
* @param string $iso
|
||||
*/
|
||||
private function parseIso(string $iso)
|
||||
{
|
||||
$this->year = substr($iso, 0, 4);
|
||||
$this->month = substr($iso, 4, 2);
|
||||
$this->day = substr($iso, 6, 2);
|
||||
@@ -43,13 +59,28 @@ class IXR_Date {
|
||||
$this->minute = substr($iso, 12, 2);
|
||||
$this->second = substr($iso, 15, 2);
|
||||
}
|
||||
function getIso() {
|
||||
return $this->year.$this->month.$this->day.'T'.$this->hour.':'.$this->minute.':'.$this->second;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIso(): string
|
||||
{
|
||||
return $this->year . $this->month . $this->day . 'T' . $this->hour . ':' . $this->minute . ':' . $this->second;
|
||||
}
|
||||
function getXml() {
|
||||
return '<dateTime.iso8601>'.$this->getIso().'</dateTime.iso8601>';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getXml(): string
|
||||
{
|
||||
return '<dateTime.iso8601>' . $this->getIso() . '</dateTime.iso8601>';
|
||||
}
|
||||
function getTimestamp() {
|
||||
|
||||
/**
|
||||
* @return false|int
|
||||
*/
|
||||
public function getTimestamp()
|
||||
{
|
||||
return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-13
@@ -1,18 +1,13 @@
|
||||
<?php
|
||||
/*
|
||||
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
|
||||
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
|
||||
Site: http://scripts.incutio.com/xmlrpc/
|
||||
Manual: http://scripts.incutio.com/xmlrpc/manual.php
|
||||
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
|
||||
*/
|
||||
|
||||
namespace IXR;
|
||||
|
||||
/**
|
||||
* IXR错误
|
||||
*
|
||||
* @package IXR
|
||||
*/
|
||||
class IXR_Error
|
||||
class Error
|
||||
{
|
||||
/**
|
||||
* 错误代码
|
||||
@@ -26,7 +21,7 @@ class IXR_Error
|
||||
* 错误消息
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
* @var string|null
|
||||
*/
|
||||
public $message;
|
||||
|
||||
@@ -35,10 +30,10 @@ class IXR_Error
|
||||
*
|
||||
* @access public
|
||||
* @param integer $code 错误代码
|
||||
* @param string $message 错误消息
|
||||
* @param string|null $message 错误消息
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($code, $message)
|
||||
public function __construct(int $code, ?string $message)
|
||||
{
|
||||
$this->code = $code;
|
||||
$this->message = $message;
|
||||
@@ -52,7 +47,7 @@ class IXR_Error
|
||||
*/
|
||||
public function getXml()
|
||||
{
|
||||
$xml = <<<EOD
|
||||
return <<<EOD
|
||||
<methodResponse>
|
||||
<fault>
|
||||
<value>
|
||||
@@ -71,6 +66,5 @@ class IXR_Error
|
||||
</methodResponse>
|
||||
|
||||
EOD;
|
||||
return $xml;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-10
@@ -1,17 +1,16 @@
|
||||
<?php
|
||||
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
|
||||
/*
|
||||
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
|
||||
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
|
||||
Site: http://scripts.incutio.com/xmlrpc/
|
||||
Manual: http://scripts.incutio.com/xmlrpc/manual.php
|
||||
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
|
||||
*/
|
||||
|
||||
namespace IXR;
|
||||
|
||||
if (!defined('__TYPECHO_ROOT_DIR__')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* IXR异常类
|
||||
*
|
||||
* @package IXR
|
||||
*/
|
||||
class IXR_Exception extends Exception
|
||||
{}
|
||||
class Exception extends \Exception
|
||||
{
|
||||
}
|
||||
|
||||
+114
-82
@@ -1,57 +1,79 @@
|
||||
<?php
|
||||
/*
|
||||
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
|
||||
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
|
||||
Site: http://scripts.incutio.com/xmlrpc/
|
||||
Manual: http://scripts.incutio.com/xmlrpc/manual.php
|
||||
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
|
||||
*/
|
||||
|
||||
namespace IXR;
|
||||
|
||||
/**
|
||||
* IXR消息
|
||||
*
|
||||
* @package IXR
|
||||
*/
|
||||
class IXR_Message {
|
||||
var $message;
|
||||
var $messageType; // methodCall / methodResponse / fault
|
||||
var $faultCode;
|
||||
var $faultString;
|
||||
var $methodName;
|
||||
var $params;
|
||||
class Message
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $message;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $messageType; // methodCall / methodResponse / fault
|
||||
|
||||
public $faultCode;
|
||||
|
||||
public $faultString;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $methodName;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $params = [];
|
||||
|
||||
// Current variable stacks
|
||||
var $_arraystructs = array(); // The stack used to keep track of the current array/struct
|
||||
var $_arraystructstypes = array(); // Stack keeping track of if things are structs or array
|
||||
var $_currentStructName = array(); // A stack as well
|
||||
var $_param;
|
||||
var $_value;
|
||||
var $_currentTag;
|
||||
var $_currentTagContents;
|
||||
// The XML parser
|
||||
var $_parser;
|
||||
function __construct ($message) {
|
||||
private $arrayStructs = []; // The stack used to keep track of the current array/struct
|
||||
|
||||
private $arrayStructsTypes = []; // Stack keeping track of if things are structs or array
|
||||
|
||||
private $currentStructName = []; // A stack as well
|
||||
|
||||
private $currentTagContents;
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
*/
|
||||
public function __construct(string $message)
|
||||
{
|
||||
$this->message = $message;
|
||||
}
|
||||
function parse() {
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function parse(): bool
|
||||
{
|
||||
// first remove the XML declaration
|
||||
$this->message = preg_replace('/<\?xml(.*)?\?'.'>/', '', $this->message);
|
||||
$this->message = preg_replace('/<\?xml(.*)?\?' . '>/', '', $this->message);
|
||||
if (trim($this->message) == '') {
|
||||
return false;
|
||||
}
|
||||
$this->_parser = xml_parser_create();
|
||||
$parser = xml_parser_create();
|
||||
// Set XML parser to take the case of tags in to account
|
||||
xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false);
|
||||
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
|
||||
// Set XML parser callback functions
|
||||
xml_set_object($this->_parser, $this);
|
||||
xml_set_element_handler($this->_parser, 'tag_open', 'tag_close');
|
||||
xml_set_character_data_handler($this->_parser, 'cdata');
|
||||
if (!xml_parse($this->_parser, $this->message)) {
|
||||
xml_set_object($parser, $this);
|
||||
xml_set_element_handler($parser, [$this, 'tagOpen'], [$this, 'tagClose']);
|
||||
xml_set_character_data_handler($parser, [$this, 'cdata']);
|
||||
if (!xml_parse($parser, $this->message)) {
|
||||
/* die(sprintf('XML error: %s at line %d',
|
||||
xml_error_string(xml_get_error_code($this->_parser)),
|
||||
xml_get_current_line_number($this->_parser))); */
|
||||
xml_error_string(xml_get_error_code($this->parser)),
|
||||
xml_get_current_line_number($this->parser))); */
|
||||
return false;
|
||||
}
|
||||
xml_parser_free($this->_parser);
|
||||
xml_parser_free($parser);
|
||||
// Grab the error messages, if any
|
||||
if ($this->messageType == 'fault') {
|
||||
$this->faultCode = $this->params[0]['faultCode'];
|
||||
@@ -59,9 +81,15 @@ class IXR_Message {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function tag_open($parser, $tag, $attr) {
|
||||
$this->currentTag = $tag;
|
||||
switch($tag) {
|
||||
|
||||
/**
|
||||
* @param $parser
|
||||
* @param $tag
|
||||
* @param $attr
|
||||
*/
|
||||
private function tagOpen($parser, string $tag, $attr)
|
||||
{
|
||||
switch ($tag) {
|
||||
case 'methodCall':
|
||||
case 'methodResponse':
|
||||
case 'fault':
|
||||
@@ -69,94 +97,98 @@ class IXR_Message {
|
||||
break;
|
||||
/* Deal with stacks of arrays and structs */
|
||||
case 'data': // data is to all intents and puposes more interesting than array
|
||||
$this->_arraystructstypes[] = 'array';
|
||||
$this->_arraystructs[] = array();
|
||||
$this->arrayStructsTypes[] = 'array';
|
||||
$this->arrayStructs[] = [];
|
||||
break;
|
||||
case 'struct':
|
||||
$this->_arraystructstypes[] = 'struct';
|
||||
$this->_arraystructs[] = array();
|
||||
$this->arrayStructsTypes[] = 'struct';
|
||||
$this->arrayStructs[] = [];
|
||||
break;
|
||||
}
|
||||
}
|
||||
function cdata($parser, $cdata) {
|
||||
$this->_currentTagContents .= $cdata;
|
||||
|
||||
/**
|
||||
* @param $parser
|
||||
* @param string $cdata
|
||||
*/
|
||||
private function cdata($parser, string $cdata)
|
||||
{
|
||||
$this->currentTagContents .= $cdata;
|
||||
}
|
||||
function tag_close($parser, $tag) {
|
||||
$valueFlag = false;
|
||||
switch($tag) {
|
||||
|
||||
/**
|
||||
* @param $parser
|
||||
* @param string $tag
|
||||
*/
|
||||
private function tagClose($parser, string $tag)
|
||||
{
|
||||
switch ($tag) {
|
||||
case 'int':
|
||||
case 'i4':
|
||||
$value = (int)trim($this->_currentTagContents);
|
||||
$this->_currentTagContents = '';
|
||||
$valueFlag = true;
|
||||
$value = (int) trim($this->currentTagContents);
|
||||
$this->currentTagContents = '';
|
||||
break;
|
||||
case 'double':
|
||||
$value = (double)trim($this->_currentTagContents);
|
||||
$this->_currentTagContents = '';
|
||||
$valueFlag = true;
|
||||
$value = (double) trim($this->currentTagContents);
|
||||
$this->currentTagContents = '';
|
||||
break;
|
||||
case 'string':
|
||||
$value = (string)trim($this->_currentTagContents);
|
||||
$this->_currentTagContents = '';
|
||||
$valueFlag = true;
|
||||
$value = (string)trim($this->currentTagContents);
|
||||
$this->currentTagContents = '';
|
||||
break;
|
||||
case 'dateTime.iso8601':
|
||||
$value = new IXR_Date(trim($this->_currentTagContents));
|
||||
$value = new Date(trim($this->currentTagContents));
|
||||
// $value = $iso->getTimestamp();
|
||||
$this->_currentTagContents = '';
|
||||
$valueFlag = true;
|
||||
$this->currentTagContents = '';
|
||||
break;
|
||||
case 'value':
|
||||
// "If no type is indicated, the type is string."
|
||||
if (trim($this->_currentTagContents) != '') {
|
||||
$value = (string)$this->_currentTagContents;
|
||||
$this->_currentTagContents = '';
|
||||
$valueFlag = true;
|
||||
if (trim($this->currentTagContents) != '') {
|
||||
$value = (string) $this->currentTagContents;
|
||||
$this->currentTagContents = '';
|
||||
}
|
||||
break;
|
||||
case 'boolean':
|
||||
$value = (boolean)trim($this->_currentTagContents);
|
||||
$this->_currentTagContents = '';
|
||||
$valueFlag = true;
|
||||
$value = (bool) trim($this->currentTagContents);
|
||||
$this->currentTagContents = '';
|
||||
break;
|
||||
case 'base64':
|
||||
$value = base64_decode($this->_currentTagContents);
|
||||
$this->_currentTagContents = '';
|
||||
$valueFlag = true;
|
||||
$value = base64_decode($this->currentTagContents);
|
||||
$this->currentTagContents = '';
|
||||
break;
|
||||
/* Deal with stacks of arrays and structs */
|
||||
case 'data':
|
||||
case 'struct':
|
||||
$value = array_pop($this->_arraystructs);
|
||||
array_pop($this->_arraystructstypes);
|
||||
$valueFlag = true;
|
||||
$value = array_pop($this->arrayStructs);
|
||||
array_pop($this->arrayStructsTypes);
|
||||
break;
|
||||
case 'member':
|
||||
array_pop($this->_currentStructName);
|
||||
array_pop($this->currentStructName);
|
||||
break;
|
||||
case 'name':
|
||||
$this->_currentStructName[] = trim($this->_currentTagContents);
|
||||
$this->_currentTagContents = '';
|
||||
$this->currentStructName[] = trim($this->currentTagContents);
|
||||
$this->currentTagContents = '';
|
||||
break;
|
||||
case 'methodName':
|
||||
$this->methodName = trim($this->_currentTagContents);
|
||||
$this->_currentTagContents = '';
|
||||
$this->methodName = trim($this->currentTagContents);
|
||||
$this->currentTagContents = '';
|
||||
break;
|
||||
}
|
||||
if ($valueFlag) {
|
||||
if (isset($value)) {
|
||||
/*
|
||||
if (!is_array($value) && !is_object($value)) {
|
||||
$value = trim($value);
|
||||
}
|
||||
*/
|
||||
if (count($this->_arraystructs) > 0) {
|
||||
if (count($this->arrayStructs) > 0) {
|
||||
// Add value to struct or array
|
||||
if ($this->_arraystructstypes[count($this->_arraystructstypes)-1] == 'struct') {
|
||||
if ($this->arrayStructsTypes[count($this->arrayStructsTypes) - 1] == 'struct') {
|
||||
// Add to struct
|
||||
$this->_arraystructs[count($this->_arraystructs)-1][$this->_currentStructName[count($this->_currentStructName)-1]] = $value;
|
||||
$this->arrayStructs[count($this->arrayStructs) - 1]
|
||||
[$this->currentStructName[count($this->currentStructName) - 1]] = $value;
|
||||
} else {
|
||||
// Add to array
|
||||
$this->_arraystructs[count($this->_arraystructs)-1][] = $value;
|
||||
$this->arrayStructs[count($this->arrayStructs) - 1][] = $value;
|
||||
}
|
||||
} else {
|
||||
// Just add as a paramater
|
||||
|
||||
+31
-19
@@ -1,43 +1,55 @@
|
||||
<?php
|
||||
/*
|
||||
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
|
||||
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
|
||||
Site: http://scripts.incutio.com/xmlrpc/
|
||||
Manual: http://scripts.incutio.com/xmlrpc/manual.php
|
||||
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
|
||||
*/
|
||||
|
||||
namespace IXR;
|
||||
|
||||
/**
|
||||
* IXR请求体
|
||||
*
|
||||
* @package IXR
|
||||
*/
|
||||
class IXR_Request {
|
||||
var $method;
|
||||
var $args;
|
||||
var $xml;
|
||||
function __construct($method, $args) {
|
||||
$this->method = $method;
|
||||
$this->args = $args;
|
||||
class Request
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $xml;
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param array $args
|
||||
*/
|
||||
public function __construct(string $method, array $args)
|
||||
{
|
||||
$this->xml = <<<EOD
|
||||
<?xml version="1.0"?>
|
||||
<methodCall>
|
||||
<methodName>{$this->method}</methodName>
|
||||
<methodName>{$method}</methodName>
|
||||
<params>
|
||||
|
||||
EOD;
|
||||
foreach ($this->args as $arg) {
|
||||
foreach ($args as $arg) {
|
||||
$this->xml .= '<param><value>';
|
||||
$v = new IXR_Value($arg);
|
||||
$v = new Value($arg);
|
||||
$this->xml .= $v->getXml();
|
||||
$this->xml .= "</value></param>\n";
|
||||
}
|
||||
|
||||
$this->xml .= '</params></methodCall>';
|
||||
}
|
||||
function getLength() {
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLength(): int
|
||||
{
|
||||
return strlen($this->xml);
|
||||
}
|
||||
function getXml() {
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getXml(): string
|
||||
{
|
||||
return $this->xml;
|
||||
}
|
||||
}
|
||||
|
||||
+169
-252
@@ -1,42 +1,20 @@
|
||||
<?php
|
||||
/*
|
||||
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
|
||||
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
|
||||
Site: http://scripts.incutio.com/xmlrpc/
|
||||
Manual: http://scripts.incutio.com/xmlrpc/manual.php
|
||||
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
|
||||
*/
|
||||
|
||||
namespace IXR;
|
||||
|
||||
/**
|
||||
* IXR服务器
|
||||
*
|
||||
* @package IXR
|
||||
*/
|
||||
class IXR_Server
|
||||
class Server
|
||||
{
|
||||
/**
|
||||
* 输入参数
|
||||
*
|
||||
* @access private
|
||||
* @var array
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* 回调函数
|
||||
*
|
||||
* @access private
|
||||
* @var array
|
||||
*/
|
||||
private $callbacks = array();
|
||||
|
||||
/**
|
||||
* 消息体
|
||||
*
|
||||
* @access private
|
||||
* @var IXR_Message
|
||||
*/
|
||||
private $message;
|
||||
private $callbacks;
|
||||
|
||||
/**
|
||||
* 默认参数
|
||||
@@ -49,234 +27,23 @@ class IXR_Server
|
||||
/**
|
||||
* 构造函数
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $callbacks 回调函数
|
||||
* @param mixed $data 输入参数
|
||||
* @return void
|
||||
* @param array $callbacks 回调函数
|
||||
*/
|
||||
public function __construct($callbacks = false, $data = false)
|
||||
public function __construct(array $callbacks = [])
|
||||
{
|
||||
$this->setCapabilities();
|
||||
if ($callbacks) {
|
||||
$this->callbacks = $callbacks;
|
||||
}
|
||||
$this->callbacks = $callbacks;
|
||||
$this->setCallbacks();
|
||||
$this->serve($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 呼叫内部方法
|
||||
*
|
||||
* @access private
|
||||
* @param string $methodname 方法名
|
||||
* @param mixed $args 参数
|
||||
* @return mixed
|
||||
*/
|
||||
private function call($methodname, $args)
|
||||
{
|
||||
// hook
|
||||
if (0 !== strpos($methodname, 'hook.') && $this->hasMethod('hook.beforeCall')) {
|
||||
$this->call('hook.beforeCall', array($methodname));
|
||||
}
|
||||
|
||||
if (!$this->hasMethod($methodname)) {
|
||||
return new IXR_Error(-32601, 'server error. requested method '.$methodname.' does not exist.');
|
||||
}
|
||||
$method = $this->callbacks[$methodname];
|
||||
|
||||
// Are we dealing with a function or a method?
|
||||
if (is_string($method) && substr($method, 0, 5) == 'this:') {
|
||||
// It's a class method - check it exists
|
||||
$method = substr($method, 5);
|
||||
if (!method_exists($this, $method)) {
|
||||
return new IXR_Error(-32601, 'server error. requested class method "'.$method.'" does not exist.');
|
||||
}
|
||||
// Call the method
|
||||
$result = $this->$method($args);
|
||||
} else {
|
||||
if (is_array($method)) {
|
||||
list($object, $func) = $method;
|
||||
if (!is_callable($method)) {
|
||||
return new IXR_Error(-32601, 'server error. requested class method "'.$object . '.' . $func.'" does not exist.');
|
||||
}
|
||||
|
||||
$result = call_user_func_array(array($object, $func), $args);
|
||||
} elseif (!function_exists($method)) {
|
||||
// It's a function - does it exist?
|
||||
return new IXR_Error(-32601, 'server error. requested function "'.$method.'" does not exist.');
|
||||
} else {
|
||||
// Call the function
|
||||
$result = $method($args);
|
||||
}
|
||||
}
|
||||
|
||||
// hook
|
||||
if (0 !== strpos($methodname, 'hook.') && $this->hasMethod('hook.afterCall')) {
|
||||
$this->call('hook.afterCall', array($methodname));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 抛出错误
|
||||
*
|
||||
* @access private
|
||||
* @param integer $error 错误代码
|
||||
* @param string $message 错误消息
|
||||
* @return void
|
||||
*/
|
||||
private function error($error, $message = false)
|
||||
{
|
||||
// Accepts either an error object or an error code and message
|
||||
if ($message && !is_object($error)) {
|
||||
$error = new IXR_Error($error, $message);
|
||||
}
|
||||
$this->output($error->getXml());
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出xml
|
||||
*
|
||||
* @access private
|
||||
* @param string $xml 输出xml
|
||||
* @return 输出xml
|
||||
*/
|
||||
private function output($xml)
|
||||
{
|
||||
$xml = '<?xml version="1.0"?>'."\n".$xml;
|
||||
$length = strlen($xml);
|
||||
header('Connection: close');
|
||||
header('Content-Length: '.$length);
|
||||
header('Content-Type: text/xml');
|
||||
header('Date: '.date('r'));
|
||||
echo $xml;
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否存在方法
|
||||
*
|
||||
* @access private
|
||||
* @param string $method 方法名
|
||||
* @return mixed
|
||||
*/
|
||||
private function hasMethod($method)
|
||||
{
|
||||
return in_array($method, array_keys($this->callbacks));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认参数
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
private function setCapabilities()
|
||||
{
|
||||
// Initialises capabilities array
|
||||
$this->capabilities = array(
|
||||
'xmlrpc' => array(
|
||||
'specUrl' => 'http://www.xmlrpc.com/spec',
|
||||
'specVersion' => 1
|
||||
),
|
||||
'faults_interop' => array(
|
||||
'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
|
||||
'specVersion' => 20010516
|
||||
),
|
||||
'system.multicall' => array(
|
||||
'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
|
||||
'specVersion' => 1
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认方法
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function setCallbacks()
|
||||
{
|
||||
$this->callbacks['system.getCapabilities'] = 'this:getCapabilities';
|
||||
$this->callbacks['system.listMethods'] = 'this:listMethods';
|
||||
$this->callbacks['system.multicall'] = 'this:multiCall';
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务入口
|
||||
*
|
||||
* @access private
|
||||
* @param mixed $data 输入参数
|
||||
* @return void
|
||||
*/
|
||||
private function serve($data = false)
|
||||
{
|
||||
if (!isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
|
||||
$GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents("php://input");
|
||||
}
|
||||
if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
|
||||
$GLOBALS['HTTP_RAW_POST_DATA'] = trim($GLOBALS['HTTP_RAW_POST_DATA']);
|
||||
}
|
||||
|
||||
if (!$data) {
|
||||
global $HTTP_RAW_POST_DATA;
|
||||
if (!$HTTP_RAW_POST_DATA) {
|
||||
die('XML-RPC server accepts POST requests only.');
|
||||
}
|
||||
$data = $HTTP_RAW_POST_DATA;
|
||||
}
|
||||
$this->message = new IXR_Message($data);
|
||||
if (!$this->message->parse()) {
|
||||
$this->error(-32700, 'parse error. not well formed');
|
||||
}
|
||||
if ($this->message->messageType != 'methodCall') {
|
||||
$this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall');
|
||||
}
|
||||
|
||||
if (0 === strpos($this->message->methodName, 'hook.')) {
|
||||
die('THIS METHOD MUST BE CALLED INSIDE.');
|
||||
}
|
||||
|
||||
$result = $this->call($this->message->methodName, $this->message->params);
|
||||
// Is the result an error?
|
||||
if (is_a($result, 'IXR_Error')) {
|
||||
$this->error($result);
|
||||
}
|
||||
// Encode the result
|
||||
$r = new IXR_Value($result);
|
||||
$resultxml = $r->getXml();
|
||||
// Create the XML
|
||||
$xml = <<<EOD
|
||||
<methodResponse>
|
||||
<params>
|
||||
<param>
|
||||
<value>
|
||||
$resultxml
|
||||
</value>
|
||||
</param>
|
||||
</params>
|
||||
</methodResponse>
|
||||
|
||||
EOD;
|
||||
// hook
|
||||
if ($this->hasMethod('hook.beforeOutput')) {
|
||||
$this->call('hook.beforeOutput', array());
|
||||
}
|
||||
|
||||
// Send it
|
||||
$this->output($xml);
|
||||
$this->serve();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认参数
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $args 输入参数
|
||||
* @return array
|
||||
*/
|
||||
public function getCapabilities($args)
|
||||
public function getCapabilities(): array
|
||||
{
|
||||
return $this->capabilities;
|
||||
}
|
||||
@@ -285,10 +52,9 @@ EOD;
|
||||
* 列出所有方法
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $args 输入参数
|
||||
* @return mixed
|
||||
* @return array
|
||||
*/
|
||||
public function listMethods($args)
|
||||
public function listMethods(): array
|
||||
{
|
||||
// Returns a list of methods - uses array_reverse to ensure user defined
|
||||
// methods are listed before server defined methods
|
||||
@@ -305,24 +71,175 @@ EOD;
|
||||
public function multiCall($methodcalls)
|
||||
{
|
||||
// See http://www.xmlrpc.com/discuss/msgReader$1208
|
||||
$return = array();
|
||||
$return = [];
|
||||
foreach ($methodcalls as $call) {
|
||||
$method = $call['methodName'];
|
||||
$params = $call['params'];
|
||||
if ($method == 'system.multicall') {
|
||||
$result = new IXR_Error(-32600, 'Recursive calls to system.multicall are forbidden');
|
||||
$result = new Error(-32600, 'Recursive calls to system.multicall are forbidden');
|
||||
} else {
|
||||
$result = $this->call($method, $params);
|
||||
}
|
||||
if (is_a($result, 'IXR_Error')) {
|
||||
$return[] = array(
|
||||
'faultCode' => $result->code,
|
||||
if (is_a($result, 'Error')) {
|
||||
$return[] = [
|
||||
'faultCode' => $result->code,
|
||||
'faultString' => $result->message
|
||||
);
|
||||
];
|
||||
} else {
|
||||
$return[] = array($result);
|
||||
$return[] = [$result];
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* 呼叫内部方法
|
||||
*
|
||||
* @param string $methodName 方法名
|
||||
* @param array $args 参数
|
||||
* @return mixed
|
||||
*/
|
||||
private function call(string $methodName, array $args)
|
||||
{
|
||||
if (!$this->hasMethod($methodName)) {
|
||||
return new Error(-32601, 'server error. requested method ' . $methodName . ' does not exist.');
|
||||
}
|
||||
$method = $this->callbacks[$methodName];
|
||||
|
||||
if (!is_callable($method)) {
|
||||
return new Error(
|
||||
-32601,
|
||||
'server error. requested class method "' . $methodName . '" does not exist.'
|
||||
);
|
||||
}
|
||||
|
||||
return call_user_func_array($method, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 抛出错误
|
||||
*
|
||||
* @access private
|
||||
* @param integer|Error $error 错误代码
|
||||
* @param string|null $message 错误消息
|
||||
* @return void
|
||||
*/
|
||||
private function error($error, ?string $message = null)
|
||||
{
|
||||
// Accepts either an error object or an error code and message
|
||||
if (!$error instanceof Error) {
|
||||
$error = new Error($error, $message);
|
||||
}
|
||||
|
||||
$this->output($error->getXml());
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出xml
|
||||
*
|
||||
* @access private
|
||||
* @param string $xml 输出xml
|
||||
*/
|
||||
private function output(string $xml)
|
||||
{
|
||||
$xml = '<?xml version="1.0"?>' . "\n" . $xml;
|
||||
$length = strlen($xml);
|
||||
header('Connection: close');
|
||||
header('Content-Length: ' . $length);
|
||||
header('Content-Type: text/xml');
|
||||
header('Date: ' . date('r'));
|
||||
echo $xml;
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否存在方法
|
||||
*
|
||||
* @access private
|
||||
* @param string $method 方法名
|
||||
* @return mixed
|
||||
*/
|
||||
private function hasMethod(string $method)
|
||||
{
|
||||
return in_array($method, array_keys($this->callbacks));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认参数
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
private function setCapabilities()
|
||||
{
|
||||
// Initialises capabilities array
|
||||
$this->capabilities = [
|
||||
'xmlrpc' => [
|
||||
'specUrl' => 'http://www.xmlrpc.com/spec',
|
||||
'specVersion' => 1
|
||||
],
|
||||
'faults_interop' => [
|
||||
'specUrl' => 'http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php',
|
||||
'specVersion' => 20010516
|
||||
],
|
||||
'system.multicall' => [
|
||||
'specUrl' => 'http://www.xmlrpc.com/discuss/msgReader$1208',
|
||||
'specVersion' => 1
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认方法
|
||||
*
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function setCallbacks()
|
||||
{
|
||||
$this->callbacks['system.getCapabilities'] = [$this, 'getCapabilities'];
|
||||
$this->callbacks['system.listMethods'] = [$this, 'listMethods'];
|
||||
$this->callbacks['system.multicall'] = [$this, 'multiCall'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务入口
|
||||
*/
|
||||
private function serve()
|
||||
{
|
||||
$message = new Message(file_get_contents('php://input') ?: '');
|
||||
|
||||
if (!$message->parse()) {
|
||||
$this->error(-32700, 'parse error. not well formed');
|
||||
} elseif ($message->messageType != 'methodCall') {
|
||||
$this->error(-32600, 'server error. invalid xml-rpc. not conforming to spec. Request must be a methodCall');
|
||||
}
|
||||
|
||||
$result = $this->call($message->methodName, $message->params);
|
||||
// Is the result an error?
|
||||
if ($result instanceof Error) {
|
||||
$this->error($result);
|
||||
}
|
||||
|
||||
// Encode the result
|
||||
$r = new Value($result);
|
||||
$resultXml = $r->getXml();
|
||||
|
||||
// Create the XML
|
||||
$xml = <<<EOD
|
||||
<methodResponse>
|
||||
<params>
|
||||
<param>
|
||||
<value>
|
||||
$resultXml
|
||||
</value>
|
||||
</param>
|
||||
</params>
|
||||
</methodResponse>
|
||||
|
||||
EOD;
|
||||
|
||||
// Send it
|
||||
$this->output($xml);
|
||||
}
|
||||
}
|
||||
|
||||
+66
-55
@@ -1,21 +1,24 @@
|
||||
<?php
|
||||
/*
|
||||
IXR - The Inutio XML-RPC Library - (c) Incutio Ltd 2002
|
||||
Version 1.61 - Simon Willison, 11th July 2003 (htmlentities -> htmlspecialchars)
|
||||
Site: http://scripts.incutio.com/xmlrpc/
|
||||
Manual: http://scripts.incutio.com/xmlrpc/manual.php
|
||||
Made available under the Artistic License: http://www.opensource.org/licenses/artistic-license.php
|
||||
*/
|
||||
|
||||
namespace IXR;
|
||||
|
||||
/**
|
||||
* IXR值
|
||||
*
|
||||
* @package IXR
|
||||
*/
|
||||
class IXR_Value {
|
||||
var $data;
|
||||
var $type;
|
||||
function __construct ($data, $type = false) {
|
||||
class Value
|
||||
{
|
||||
private $data;
|
||||
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* @param mixed $data
|
||||
* @param bool|string $type
|
||||
*/
|
||||
public function __construct($data, $type = false)
|
||||
{
|
||||
$this->data = $data;
|
||||
if (!$type) {
|
||||
$type = $this->calculateType();
|
||||
@@ -24,16 +27,62 @@ class IXR_Value {
|
||||
if ($type == 'struct') {
|
||||
/* Turn all the values in the array in to new IXR_Value objects */
|
||||
foreach ($this->data as $key => $value) {
|
||||
$this->data[$key] = new IXR_Value($value);
|
||||
$this->data[$key] = new Value($value);
|
||||
}
|
||||
}
|
||||
if ($type == 'array') {
|
||||
for ($i = 0, $j = count($this->data); $i < $j; $i++) {
|
||||
$this->data[$i] = new IXR_Value($this->data[$i]);
|
||||
$this->data[$i] = new Value($this->data[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
function calculateType() {
|
||||
|
||||
public function getXml(): string
|
||||
{
|
||||
/* Return XML for this value */
|
||||
switch ($this->type) {
|
||||
case 'boolean':
|
||||
return '<boolean>' . (($this->data) ? '1' : '0') . '</boolean>';
|
||||
break;
|
||||
case 'int':
|
||||
return '<int>' . $this->data . '</int>';
|
||||
break;
|
||||
case 'double':
|
||||
return '<double>' . $this->data . '</double>';
|
||||
break;
|
||||
case 'string':
|
||||
return '<string>' . htmlspecialchars($this->data) . '</string>';
|
||||
break;
|
||||
case 'array':
|
||||
$return = '<array><data>' . "\n";
|
||||
foreach ($this->data as $item) {
|
||||
$return .= ' <value>' . $item->getXml() . "</value>\n";
|
||||
}
|
||||
$return .= '</data></array>';
|
||||
return $return;
|
||||
break;
|
||||
case 'struct':
|
||||
$return = '<struct>' . "\n";
|
||||
foreach ($this->data as $name => $value) {
|
||||
$return .= " <member><name>$name</name><value>";
|
||||
$return .= $value->getXml() . "</value></member>\n";
|
||||
}
|
||||
$return .= '</struct>';
|
||||
return $return;
|
||||
break;
|
||||
case 'date':
|
||||
case 'base64':
|
||||
return $this->data->getXml();
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function calculateType(): string
|
||||
{
|
||||
if ($this->data === true || $this->data === false) {
|
||||
return 'boolean';
|
||||
}
|
||||
@@ -52,7 +101,6 @@ class IXR_Value {
|
||||
}
|
||||
// If it is a normal PHP object convert it in to a struct
|
||||
if (is_object($this->data)) {
|
||||
|
||||
$this->data = get_object_vars($this->data);
|
||||
return 'struct';
|
||||
}
|
||||
@@ -66,46 +114,9 @@ class IXR_Value {
|
||||
return 'array';
|
||||
}
|
||||
}
|
||||
function getXml() {
|
||||
/* Return XML for this value */
|
||||
switch ($this->type) {
|
||||
case 'boolean':
|
||||
return '<boolean>'.(($this->data) ? '1' : '0').'</boolean>';
|
||||
break;
|
||||
case 'int':
|
||||
return '<int>'.$this->data.'</int>';
|
||||
break;
|
||||
case 'double':
|
||||
return '<double>'.$this->data.'</double>';
|
||||
break;
|
||||
case 'string':
|
||||
return '<string>'.htmlspecialchars($this->data).'</string>';
|
||||
break;
|
||||
case 'array':
|
||||
$return = '<array><data>'."\n";
|
||||
foreach ($this->data as $item) {
|
||||
$return .= ' <value>'.$item->getXml()."</value>\n";
|
||||
}
|
||||
$return .= '</data></array>';
|
||||
return $return;
|
||||
break;
|
||||
case 'struct':
|
||||
$return = '<struct>'."\n";
|
||||
foreach ($this->data as $name => $value) {
|
||||
$return .= " <member><name>$name</name><value>";
|
||||
$return .= $value->getXml()."</value></member>\n";
|
||||
}
|
||||
$return .= '</struct>';
|
||||
return $return;
|
||||
break;
|
||||
case 'date':
|
||||
case 'base64':
|
||||
return $this->data->getXml();
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isStruct($array) {
|
||||
|
||||
private function isStruct($array): bool
|
||||
{
|
||||
/* Nasty function to check if an array is a struct or not */
|
||||
$expected = 0;
|
||||
foreach ($array as $key => $value) {
|
||||
|
||||
+14
-21
@@ -1,13 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* cookie支持
|
||||
*
|
||||
* @category typecho
|
||||
* @package Cookie
|
||||
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
|
||||
* @license GNU General Public License 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace Typecho;
|
||||
|
||||
/**
|
||||
* cookie支持
|
||||
@@ -16,7 +9,7 @@
|
||||
* @category typecho
|
||||
* @package Cookie
|
||||
*/
|
||||
class Typecho_Cookie
|
||||
class Cookie
|
||||
{
|
||||
/**
|
||||
* 前缀
|
||||
@@ -24,7 +17,7 @@ class Typecho_Cookie
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
private static $_prefix = '';
|
||||
private static $prefix = '';
|
||||
|
||||
/**
|
||||
* 路径
|
||||
@@ -32,7 +25,7 @@ class Typecho_Cookie
|
||||
* @var string
|
||||
* @access private
|
||||
*/
|
||||
private static $_path = '/';
|
||||
private static $path = '/';
|
||||
|
||||
/**
|
||||
* 获取前缀
|
||||
@@ -42,7 +35,7 @@ class Typecho_Cookie
|
||||
*/
|
||||
public static function getPrefix(): string
|
||||
{
|
||||
return self::$_prefix;
|
||||
return self::$prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,11 +48,11 @@ class Typecho_Cookie
|
||||
*/
|
||||
public static function setPrefix(string $url)
|
||||
{
|
||||
self::$_prefix = md5($url);
|
||||
self::$prefix = md5($url);
|
||||
$parsed = parse_url($url);
|
||||
|
||||
/** 在路径后面强制加上斜杠 */
|
||||
self::$_path = empty($parsed['path']) ? '/' : Typecho_Common::url(null, $parsed['path']);
|
||||
self::$path = empty($parsed['path']) ? '/' : Common::url(null, $parsed['path']);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,7 +63,7 @@ class Typecho_Cookie
|
||||
*/
|
||||
public static function getPath(): string
|
||||
{
|
||||
return self::$_path;
|
||||
return self::$path;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +78,7 @@ class Typecho_Cookie
|
||||
*/
|
||||
public static function get(string $key, ?string $default = null)
|
||||
{
|
||||
$key = self::$_prefix . $key;
|
||||
$key = self::$prefix . $key;
|
||||
$value = $_COOKIE[$key] ?? $default;
|
||||
return is_array($value) ? $default : $value;
|
||||
}
|
||||
@@ -103,8 +96,8 @@ class Typecho_Cookie
|
||||
*/
|
||||
public static function set(string $key, $value, int $expire = 0)
|
||||
{
|
||||
$key = self::$_prefix . $key;
|
||||
setrawcookie($key, rawurlencode($value), $expire, self::$_path);
|
||||
$key = self::$prefix . $key;
|
||||
setrawcookie($key, rawurlencode($value), $expire, self::$path);
|
||||
$_COOKIE[$key] = $value;
|
||||
}
|
||||
|
||||
@@ -119,12 +112,12 @@ class Typecho_Cookie
|
||||
*/
|
||||
public static function delete(string $key)
|
||||
{
|
||||
$key = self::$_prefix . $key;
|
||||
$key = self::$prefix . $key;
|
||||
if (!isset($_COOKIE[$key])) {
|
||||
return;
|
||||
}
|
||||
|
||||
setcookie($key, '', time() - 2592000, self::$_path);
|
||||
setcookie($key, '', time() - 2592000, self::$path);
|
||||
unset($_COOKIE[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Typecho;
|
||||
|
||||
/**
|
||||
* 日期处理
|
||||
*
|
||||
@@ -7,7 +9,7 @@
|
||||
* @category typecho
|
||||
* @package Date
|
||||
*/
|
||||
class Typecho_Date
|
||||
class Date
|
||||
{
|
||||
/**
|
||||
* 期望时区偏移
|
||||
@@ -48,9 +50,10 @@ class Typecho_Date
|
||||
*
|
||||
* @param integer|null $time 时间戳
|
||||
*/
|
||||
public function __construct(?int $time = NULL)
|
||||
public function __construct(?int $time = null)
|
||||
{
|
||||
$this->timeStamp = (NULL === $time ? self::time() : $time) + (self::$timezoneOffset - self::$serverTimezoneOffset);
|
||||
$this->timeStamp = (null === $time ? self::time() : $time)
|
||||
+ (self::$timezoneOffset - self::$serverTimezoneOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +93,7 @@ class Typecho_Date
|
||||
*/
|
||||
public function word(): string
|
||||
{
|
||||
return Typecho_I18n::dateWord($this->timeStamp, self::time() + (self::$timezoneOffset - self::$serverTimezoneOffset));
|
||||
return I18n::dateWord($this->timeStamp, self::time() + (self::$timezoneOffset - self::$serverTimezoneOffset));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+71
-76
@@ -1,43 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* 格式化聚合XML数据,整合自Univarsel Feed Writer
|
||||
*
|
||||
* @author Anis uddin Ahmad <anisniit@gmail.com>
|
||||
* @category typecho
|
||||
* @package Feed
|
||||
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
|
||||
* @license GNU General Public License 2.0
|
||||
* @version $Id: Feed.php 219 2008-05-27 09:06:15Z magike.net $
|
||||
*/
|
||||
|
||||
namespace Typecho;
|
||||
|
||||
/**
|
||||
* Typecho_Feed
|
||||
*
|
||||
* @author qining
|
||||
* @category typecho
|
||||
* @package Feed
|
||||
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
|
||||
* @license GNU General Public License 2.0
|
||||
*/
|
||||
class Typecho_Feed
|
||||
class Feed
|
||||
{
|
||||
/** 定义RSS 1.0类型 */
|
||||
const RSS1 = 'RSS 1.0';
|
||||
public const RSS1 = 'RSS 1.0';
|
||||
|
||||
/** 定义RSS 2.0类型 */
|
||||
const RSS2 = 'RSS 2.0';
|
||||
public const RSS2 = 'RSS 2.0';
|
||||
|
||||
/** 定义ATOM 1.0类型 */
|
||||
const ATOM1 = 'ATOM 1.0';
|
||||
public const ATOM1 = 'ATOM 1.0';
|
||||
|
||||
/** 定义RSS时间格式 */
|
||||
const DATE_RFC822 = 'r';
|
||||
public const DATE_RFC822 = 'r';
|
||||
|
||||
/** 定义ATOM时间格式 */
|
||||
const DATE_W3CDTF = 'c';
|
||||
public const DATE_W3CDTF = 'c';
|
||||
|
||||
/** 定义行结束符 */
|
||||
const EOL = "\n";
|
||||
public const EOL = "\n";
|
||||
|
||||
/**
|
||||
* feed状态
|
||||
@@ -45,7 +33,7 @@ class Typecho_Feed
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_type;
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* 字符集编码
|
||||
@@ -53,7 +41,7 @@ class Typecho_Feed
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_charset;
|
||||
private $charset;
|
||||
|
||||
/**
|
||||
* 语言状态
|
||||
@@ -61,7 +49,7 @@ class Typecho_Feed
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_lang;
|
||||
private $lang;
|
||||
|
||||
/**
|
||||
* 聚合地址
|
||||
@@ -69,7 +57,7 @@ class Typecho_Feed
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_feedUrl;
|
||||
private $feedUrl;
|
||||
|
||||
/**
|
||||
* 基本地址
|
||||
@@ -77,7 +65,7 @@ class Typecho_Feed
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_baseUrl;
|
||||
private $baseUrl;
|
||||
|
||||
/**
|
||||
* 聚合标题
|
||||
@@ -85,7 +73,7 @@ class Typecho_Feed
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_title;
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* 聚合副标题
|
||||
@@ -93,7 +81,7 @@ class Typecho_Feed
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_subTitle;
|
||||
private $subTitle;
|
||||
|
||||
/**
|
||||
* 版本信息
|
||||
@@ -101,7 +89,7 @@ class Typecho_Feed
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $_version;
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* 所有的items
|
||||
@@ -109,7 +97,7 @@ class Typecho_Feed
|
||||
* @access private
|
||||
* @var array
|
||||
*/
|
||||
private $_items = [];
|
||||
private $items = [];
|
||||
|
||||
/**
|
||||
* 创建Feed对象
|
||||
@@ -119,10 +107,10 @@ class Typecho_Feed
|
||||
*/
|
||||
public function __construct($version, $type = self::RSS2, $charset = 'UTF-8', $lang = 'en')
|
||||
{
|
||||
$this->_version = $version;
|
||||
$this->_type = $type;
|
||||
$this->_charset = $charset;
|
||||
$this->_lang = $lang;
|
||||
$this->version = $version;
|
||||
$this->type = $type;
|
||||
$this->charset = $charset;
|
||||
$this->lang = $lang;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,7 +124,7 @@ class Typecho_Feed
|
||||
*/
|
||||
public function setTitle(string $title)
|
||||
{
|
||||
$this->_title = $title;
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,7 +138,7 @@ class Typecho_Feed
|
||||
*/
|
||||
public function setSubTitle(string $subTitle)
|
||||
{
|
||||
$this->_subTitle = $subTitle;
|
||||
$this->subTitle = $subTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,7 +152,7 @@ class Typecho_Feed
|
||||
*/
|
||||
public function setFeedUrl(string $feedUrl)
|
||||
{
|
||||
$this->_feedUrl = $feedUrl;
|
||||
$this->feedUrl = $feedUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,7 +166,7 @@ class Typecho_Feed
|
||||
*/
|
||||
public function setBaseUrl(string $baseUrl)
|
||||
{
|
||||
$this->_baseUrl = $baseUrl;
|
||||
$this->baseUrl = $baseUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,7 +191,7 @@ class Typecho_Feed
|
||||
*/
|
||||
public function addItem(array $item)
|
||||
{
|
||||
$this->_items[] = $item;
|
||||
$this->items[] = $item;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,11 +200,11 @@ class Typecho_Feed
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
public function __toString(): string
|
||||
{
|
||||
$result = '<?xml version="1.0" encoding="' . $this->_charset . '"?>' . self::EOL;
|
||||
$result = '<?xml version="1.0" encoding="' . $this->charset . '"?>' . self::EOL;
|
||||
|
||||
if (self::RSS1 == $this->_type) {
|
||||
if (self::RSS1 == $this->type) {
|
||||
$result .= '<rdf:RDF
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://purl.org/rss/1.0/"
|
||||
@@ -226,7 +214,7 @@ xmlns:dc="http://purl.org/dc/elements/1.1/">' . self::EOL;
|
||||
$links = [];
|
||||
$lastUpdate = 0;
|
||||
|
||||
foreach ($this->_items as $item) {
|
||||
foreach ($this->items as $item) {
|
||||
$content .= '<item rdf:about="' . $item['link'] . '">' . self::EOL;
|
||||
$content .= '<title>' . htmlspecialchars($item['title']) . '</title>' . self::EOL;
|
||||
$content .= '<link>' . $item['link'] . '</link>' . self::EOL;
|
||||
@@ -244,10 +232,10 @@ xmlns:dc="http://purl.org/dc/elements/1.1/">' . self::EOL;
|
||||
}
|
||||
}
|
||||
|
||||
$result .= '<channel rdf:about="' . $this->_feedUrl . '">
|
||||
<title>' . htmlspecialchars($this->_title) . '</title>
|
||||
<link>' . $this->_baseUrl . '</link>
|
||||
<description>' . htmlspecialchars($this->_subTitle) . '</description>
|
||||
$result .= '<channel rdf:about="' . $this->feedUrl . '">
|
||||
<title>' . htmlspecialchars($this->title) . '</title>
|
||||
<link>' . $this->baseUrl . '</link>
|
||||
<description>' . htmlspecialchars($this->subTitle) . '</description>
|
||||
<items>
|
||||
<rdf:Seq>' . self::EOL;
|
||||
|
||||
@@ -260,8 +248,7 @@ xmlns:dc="http://purl.org/dc/elements/1.1/">' . self::EOL;
|
||||
</channel>' . self::EOL;
|
||||
|
||||
$result .= $content . '</rdf:RDF>';
|
||||
|
||||
} else if (self::RSS2 == $this->_type) {
|
||||
} elseif (self::RSS2 == $this->type) {
|
||||
$result .= '<rss version="2.0"
|
||||
xmlns:content="http://purl.org/rss/1.0/modules/content/"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
@@ -273,13 +260,14 @@ xmlns:wfw="http://wellformedweb.org/CommentAPI/">
|
||||
$content = '';
|
||||
$lastUpdate = 0;
|
||||
|
||||
foreach ($this->_items as $item) {
|
||||
foreach ($this->items as $item) {
|
||||
$content .= '<item>' . self::EOL;
|
||||
$content .= '<title>' . htmlspecialchars($item['title']) . '</title>' . self::EOL;
|
||||
$content .= '<link>' . $item['link'] . '</link>' . self::EOL;
|
||||
$content .= '<guid>' . $item['link'] . '</guid>' . self::EOL;
|
||||
$content .= '<pubDate>' . $this->dateFormat($item['date']) . '</pubDate>' . self::EOL;
|
||||
$content .= '<dc:creator>' . htmlspecialchars($item['author']->screenName) . '</dc:creator>' . self::EOL;
|
||||
$content .= '<dc:creator>' . htmlspecialchars($item['author']->screenName)
|
||||
. '</dc:creator>' . self::EOL;
|
||||
|
||||
if (!empty($item['category']) && is_array($item['category'])) {
|
||||
foreach ($item['category'] as $category) {
|
||||
@@ -288,11 +276,12 @@ xmlns:wfw="http://wellformedweb.org/CommentAPI/">
|
||||
}
|
||||
|
||||
if (!empty($item['excerpt'])) {
|
||||
$content .= '<description><![CDATA[' . strip_tags($item['excerpt']) . ']]></description>' . self::EOL;
|
||||
$content .= '<description><![CDATA[' . strip_tags($item['excerpt'])
|
||||
. ']]></description>' . self::EOL;
|
||||
}
|
||||
|
||||
if (!empty($item['content'])) {
|
||||
$content .= '<content:encoded xml:lang="' . $this->_lang . '"><![CDATA['
|
||||
$content .= '<content:encoded xml:lang="' . $this->lang . '"><![CDATA['
|
||||
. self::EOL .
|
||||
$item['content'] . self::EOL .
|
||||
']]></content:encoded>' . self::EOL;
|
||||
@@ -318,28 +307,27 @@ xmlns:wfw="http://wellformedweb.org/CommentAPI/">
|
||||
}
|
||||
}
|
||||
|
||||
$result .= '<title>' . htmlspecialchars($this->_title) . '</title>
|
||||
<link>' . $this->_baseUrl . '</link>
|
||||
<atom:link href="' . $this->_feedUrl . '" rel="self" type="application/rss+xml" />
|
||||
<language>' . $this->_lang . '</language>
|
||||
<description>' . htmlspecialchars($this->_subTitle) . '</description>
|
||||
$result .= '<title>' . htmlspecialchars($this->title) . '</title>
|
||||
<link>' . $this->baseUrl . '</link>
|
||||
<atom:link href="' . $this->feedUrl . '" rel="self" type="application/rss+xml" />
|
||||
<language>' . $this->lang . '</language>
|
||||
<description>' . htmlspecialchars($this->subTitle) . '</description>
|
||||
<lastBuildDate>' . $this->dateFormat($lastUpdate) . '</lastBuildDate>
|
||||
<pubDate>' . $this->dateFormat($lastUpdate) . '</pubDate>' . self::EOL;
|
||||
|
||||
$result .= $content . '</channel>
|
||||
</rss>';
|
||||
|
||||
} else if (self::ATOM1 == $this->_type) {
|
||||
} elseif (self::ATOM1 == $this->type) {
|
||||
$result .= '<feed xmlns="http://www.w3.org/2005/Atom"
|
||||
xmlns:thr="http://purl.org/syndication/thread/1.0"
|
||||
xml:lang="' . $this->_lang . '"
|
||||
xml:base="' . $this->_baseUrl . '"
|
||||
xml:lang="' . $this->lang . '"
|
||||
xml:base="' . $this->baseUrl . '"
|
||||
>' . self::EOL;
|
||||
|
||||
$content = '';
|
||||
$lastUpdate = 0;
|
||||
|
||||
foreach ($this->_items as $item) {
|
||||
foreach ($this->items as $item) {
|
||||
$content .= '<entry>' . self::EOL;
|
||||
$content .= '<title type="html"><![CDATA[' . $item['title'] . ']]></title>' . self::EOL;
|
||||
$content .= '<link rel="alternate" type="text/html" href="' . $item['link'] . '" />' . self::EOL;
|
||||
@@ -353,26 +341,31 @@ xml:base="' . $this->_baseUrl . '"
|
||||
|
||||
if (!empty($item['category']) && is_array($item['category'])) {
|
||||
foreach ($item['category'] as $category) {
|
||||
$content .= '<category scheme="' . $category['permalink'] . '" term="' . $category['name'] . '" />' . self::EOL;
|
||||
$content .= '<category scheme="' . $category['permalink'] . '" term="'
|
||||
. $category['name'] . '" />' . self::EOL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($item['excerpt'])) {
|
||||
$content .= '<summary type="html"><![CDATA[' . htmlspecialchars($item['excerpt']) . ']]></summary>' . self::EOL;
|
||||
$content .= '<summary type="html"><![CDATA[' . htmlspecialchars($item['excerpt'])
|
||||
. ']]></summary>' . self::EOL;
|
||||
}
|
||||
|
||||
if (!empty($item['content'])) {
|
||||
$content .= '<content type="html" xml:base="' . $item['link'] . '" xml:lang="' . $this->_lang . '"><![CDATA['
|
||||
$content .= '<content type="html" xml:base="' . $item['link']
|
||||
. '" xml:lang="' . $this->lang . '"><![CDATA['
|
||||
. self::EOL .
|
||||
$item['content'] . self::EOL .
|
||||
']]></content>' . self::EOL;
|
||||
}
|
||||
|
||||
if (isset($item['comments']) && strlen($item['comments']) > 0) {
|
||||
$content .= '<link rel="replies" type="text/html" href="' . $item['link'] . '#comments" thr:count="' . $item['comments'] . '" />' . self::EOL;
|
||||
$content .= '<link rel="replies" type="text/html" href="' . $item['link']
|
||||
. '#comments" thr:count="' . $item['comments'] . '" />' . self::EOL;
|
||||
|
||||
if (!empty($item['commentsFeedUrl'])) {
|
||||
$content .= '<link rel="replies" type="application/atom+xml" href="' . $item['commentsFeedUrl'] . '" thr:count="' . $item['comments'] . '"/>' . self::EOL;
|
||||
$content .= '<link rel="replies" type="application/atom+xml" href="'
|
||||
. $item['commentsFeedUrl'] . '" thr:count="' . $item['comments'] . '"/>' . self::EOL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,13 +380,13 @@ xml:base="' . $this->_baseUrl . '"
|
||||
}
|
||||
}
|
||||
|
||||
$result .= '<title type="text">' . htmlspecialchars($this->_title) . '</title>
|
||||
<subtitle type="text">' . htmlspecialchars($this->_subTitle) . '</subtitle>
|
||||
$result .= '<title type="text">' . htmlspecialchars($this->title) . '</title>
|
||||
<subtitle type="text">' . htmlspecialchars($this->subTitle) . '</subtitle>
|
||||
<updated>' . $this->dateFormat($lastUpdate) . '</updated>
|
||||
<generator uri="http://typecho.org/" version="' . $this->_version . '">Typecho</generator>
|
||||
<link rel="alternate" type="text/html" href="' . $this->_baseUrl . '" />
|
||||
<id>' . $this->_feedUrl . '</id>
|
||||
<link rel="self" type="application/atom+xml" href="' . $this->_feedUrl . '" />
|
||||
<generator uri="http://typecho.org/" version="' . $this->version . '">Typecho</generator>
|
||||
<link rel="alternate" type="text/html" href="' . $this->baseUrl . '" />
|
||||
<id>' . $this->feedUrl . '</id>
|
||||
<link rel="self" type="application/atom+xml" href="' . $this->feedUrl . '" />
|
||||
';
|
||||
$result .= $content . '</feed>';
|
||||
}
|
||||
@@ -412,10 +405,12 @@ xml:base="' . $this->_baseUrl . '"
|
||||
*/
|
||||
public function dateFormat(int $stamp): string
|
||||
{
|
||||
if (self::RSS2 == $this->_type) {
|
||||
if (self::RSS2 == $this->type) {
|
||||
return date(self::DATE_RFC822, $stamp);
|
||||
} else if (self::RSS1 == $this->_type || self::ATOM1 == $this->_type) {
|
||||
} elseif (self::RSS1 == $this->type || self::ATOM1 == $this->type) {
|
||||
return date(self::DATE_W3CDTF, $stamp);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
+22
-22
@@ -1,26 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Typecho Blog Platform
|
||||
*
|
||||
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
|
||||
* @license GNU General Public License 2.0
|
||||
* @version $Id: I18n.php 106 2008-04-11 02:23:54Z magike.net $
|
||||
*/
|
||||
|
||||
namespace Typecho;
|
||||
|
||||
use Typecho\I18n\GetTextMulti;
|
||||
|
||||
/**
|
||||
* 国际化字符翻译
|
||||
*
|
||||
* @package I18n
|
||||
*/
|
||||
class Typecho_I18n
|
||||
class I18n
|
||||
{
|
||||
/**
|
||||
* 是否已经载入的标志位
|
||||
*
|
||||
* @access private
|
||||
* @var boolean|Typecho_I18n_GetTextMulti
|
||||
* @var GetTextMulti
|
||||
*/
|
||||
private static $_loaded = false;
|
||||
private static $loaded;
|
||||
|
||||
/**
|
||||
* 语言文件
|
||||
@@ -28,7 +25,7 @@ class Typecho_I18n
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private static $_lang = null;
|
||||
private static $lang = null;
|
||||
|
||||
/**
|
||||
* 翻译文字
|
||||
@@ -42,7 +39,7 @@ class Typecho_I18n
|
||||
public static function translate(string $string): string
|
||||
{
|
||||
self::init();
|
||||
return self::$_loaded ? self::$_loaded->translate($string) : $string;
|
||||
return self::$loaded ? self::$loaded->translate($string) : $string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,8 +50,8 @@ class Typecho_I18n
|
||||
private static function init()
|
||||
{
|
||||
/** GetText支持 */
|
||||
if (false === self::$_loaded && self::$_lang && file_exists(self::$_lang)) {
|
||||
self::$_loaded = new Typecho_I18n_GetTextMulti(self::$_lang);
|
||||
if (!isset(self::$loaded) && self::$lang && file_exists(self::$lang)) {
|
||||
self::$loaded = new GetTextMulti(self::$lang);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +67,7 @@ class Typecho_I18n
|
||||
public static function ngettext(string $single, string $plural, int $number): string
|
||||
{
|
||||
self::init();
|
||||
return self::$_loaded ? self::$_loaded->ngettext($single, $plural, $number) : ($number > 1 ? $plural : $single);
|
||||
return self::$loaded ? self::$loaded->ngettext($single, $plural, $number) : ($number > 1 ? $plural : $single);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,8 +75,8 @@ class Typecho_I18n
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param string $from 起始时间
|
||||
* @param string $now 终止时间
|
||||
* @param int $from 起始时间
|
||||
* @param int $now 终止时间
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -109,9 +106,12 @@ class Typecho_I18n
|
||||
}
|
||||
|
||||
/** 如果是昨天 */
|
||||
if ($between > 0 && $between < 172800
|
||||
if (
|
||||
$between > 0
|
||||
&& $between < 172800
|
||||
&& (date('z', $from) + 1 == date('z', $now) // 在同一年的情况
|
||||
|| date('z', $from) + 1 == date('L') + 365 + date('z', $now))) { // 跨年的情况
|
||||
|| date('z', $from) + 1 == date('L') + 365 + date('z', $now))
|
||||
) { // 跨年的情况
|
||||
return _t('昨天 %s', date('H:i', $from));
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ class Typecho_I18n
|
||||
*/
|
||||
public static function addLang(string $lang)
|
||||
{
|
||||
self::$_loaded->addFile($lang);
|
||||
self::$loaded->addFile($lang);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,7 +151,7 @@ class Typecho_I18n
|
||||
*/
|
||||
public static function getLang(): ?string
|
||||
{
|
||||
return self::$_lang;
|
||||
return self::$lang;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,6 +165,6 @@ class Typecho_I18n
|
||||
*/
|
||||
public static function setLang(string $lang)
|
||||
{
|
||||
self::$_lang = $lang;
|
||||
self::$lang = $lang;
|
||||
}
|
||||
}
|
||||
|
||||
+170
-159
@@ -1,4 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Typecho\I18n;
|
||||
|
||||
/*
|
||||
Copyright (c) 2003 Danilo Segan <danilo@kvota.net>.
|
||||
Copyright (c) 2005 Nico Kaiser <nico@siriux.net>
|
||||
@@ -21,21 +24,6 @@
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides a simple gettext replacement that works independently from
|
||||
* the system's gettext abilities.
|
||||
* It can read MO files and use them for translating strings.
|
||||
* The files are passed to gettext_reader as a Stream (see streams.php)
|
||||
*
|
||||
* This version has the ability to cache all strings and translations to
|
||||
* speed up the string lookup.
|
||||
* While the cache is enabled by default, it can be switched off with the
|
||||
* second parameter in the constructor (e.g. whenusing very large MO files
|
||||
* that you don't want to keep in memory)
|
||||
*/
|
||||
|
||||
//reload by 70 (typecho group)
|
||||
|
||||
/**
|
||||
* This file is part of PHP-gettext
|
||||
*
|
||||
@@ -43,22 +31,32 @@
|
||||
* @category typecho
|
||||
* @package I18n
|
||||
*/
|
||||
class Typecho_I18n_GetText
|
||||
class GetText
|
||||
{
|
||||
//public:
|
||||
public $error = 0; // public variable that holds error code (0 if no error)
|
||||
|
||||
//private:
|
||||
private $BYTEORDER = 0; // 0: low endian, 1: big endian
|
||||
private $BYTE_ORDER = 0; // 0: low endian, 1: big endian
|
||||
|
||||
private $STREAM = null;
|
||||
|
||||
private $short_circuit = false;
|
||||
|
||||
private $enable_cache = false;
|
||||
|
||||
private $originals = null; // offset of original table
|
||||
|
||||
private $translations = null; // offset of translation table
|
||||
private $pluralheader = null; // cache header field for plural forms
|
||||
|
||||
private $pluralHeader = null; // cache header field for plural forms
|
||||
|
||||
private $total = 0; // total string count
|
||||
|
||||
private $table_originals = null; // table for original strings (offsets)
|
||||
|
||||
private $table_translations = null; // table for translated strings (offsets)
|
||||
|
||||
private $cache_translations = null; // original -> translation mapping
|
||||
|
||||
|
||||
@@ -69,7 +67,7 @@ class Typecho_I18n_GetText
|
||||
* @param string $file file name
|
||||
* @param boolean enable_cache Enable or disable caching of strings (default on)
|
||||
*/
|
||||
public function __construct($file, $enable_cache = true)
|
||||
public function __construct(string $file, $enable_cache = true)
|
||||
{
|
||||
// If there isn't a StreamReader, turn on short circuit mode.
|
||||
if (!file_exists($file)) {
|
||||
@@ -84,21 +82,114 @@ class Typecho_I18n_GetText
|
||||
$unpacked = unpack('c', $this->read(4));
|
||||
$magic = array_shift($unpacked);
|
||||
|
||||
if (- 34 == $magic) {
|
||||
$this->BYTEORDER = 0;
|
||||
} elseif (- 107 == $magic) {
|
||||
$this->BYTEORDER = 1;
|
||||
if (-34 == $magic) {
|
||||
$this->BYTE_ORDER = 0;
|
||||
} elseif (-107 == $magic) {
|
||||
$this->BYTE_ORDER = 1;
|
||||
} else {
|
||||
$this->error = 1; // not MO file
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: Do we care about revision? We should.
|
||||
$revision = $this->readint();
|
||||
$revision = $this->readInt();
|
||||
|
||||
$this->total = $this->readint();
|
||||
$this->originals = $this->readint();
|
||||
$this->translations = $this->readint();
|
||||
$this->total = $this->readInt();
|
||||
$this->originals = $this->readInt();
|
||||
$this->translations = $this->readInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a string
|
||||
*
|
||||
* @access public
|
||||
* @param string string to be translated
|
||||
* @param integer|null $num found string number
|
||||
* @return string translated string (or original, if not found)
|
||||
*/
|
||||
public function translate($string, ?int &$num): string
|
||||
{
|
||||
if ($this->short_circuit) {
|
||||
return $string;
|
||||
}
|
||||
$this->loadTables();
|
||||
|
||||
if ($this->enable_cache) {
|
||||
// Caching enabled, get translated string from cache
|
||||
if (array_key_exists($string, $this->cache_translations)) {
|
||||
return $this->cache_translations[$string];
|
||||
} else {
|
||||
return $string;
|
||||
}
|
||||
} else {
|
||||
// Caching not enabled, try to find string
|
||||
$num = $this->findString($string);
|
||||
if ($num == -1) {
|
||||
return $string;
|
||||
} else {
|
||||
return $this->getTranslationString($num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Plural version of gettext
|
||||
*
|
||||
* @access public
|
||||
* @param string single
|
||||
* @param string plural
|
||||
* @param string number
|
||||
* @param integer|null $num found string number
|
||||
* @return string plural form
|
||||
*/
|
||||
public function ngettext($single, $plural, $number, ?int &$num): string
|
||||
{
|
||||
$number = intval($number);
|
||||
|
||||
if ($this->short_circuit) {
|
||||
if ($number != 1) {
|
||||
return $plural;
|
||||
} else {
|
||||
return $single;
|
||||
}
|
||||
}
|
||||
|
||||
// find out the appropriate form
|
||||
$select = $this->selectString($number);
|
||||
|
||||
// this should contains all strings separated by NULLs
|
||||
$key = $single . chr(0) . $plural;
|
||||
|
||||
|
||||
if ($this->enable_cache) {
|
||||
if (!array_key_exists($key, $this->cache_translations)) {
|
||||
return ($number != 1) ? $plural : $single;
|
||||
} else {
|
||||
$result = $this->cache_translations[$key];
|
||||
$list = explode(chr(0), $result);
|
||||
return $list[$select];
|
||||
}
|
||||
} else {
|
||||
$num = $this->findString($key);
|
||||
if ($num == -1) {
|
||||
return ($number != 1) ? $plural : $single;
|
||||
} else {
|
||||
$result = $this->getTranslationString($num);
|
||||
$list = explode(chr(0), $result);
|
||||
return $list[$select];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭文件句柄
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
fclose($this->STREAM);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +197,7 @@ class Typecho_I18n_GetText
|
||||
*
|
||||
* @param mixed $count
|
||||
* @access private
|
||||
* @return void
|
||||
* @return false|string
|
||||
*/
|
||||
private function read($count)
|
||||
{
|
||||
@@ -116,7 +207,7 @@ class Typecho_I18n_GetText
|
||||
return fread($this->STREAM, $count);
|
||||
}
|
||||
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,42 +216,12 @@ class Typecho_I18n_GetText
|
||||
* @access private
|
||||
* @return Integer from the Stream
|
||||
*/
|
||||
private function readint()
|
||||
private function readInt(): int
|
||||
{
|
||||
$end = unpack($this->BYTEORDER == 0 ? 'V' : 'N', $this->read(4));
|
||||
$end = unpack($this->BYTE_ORDER == 0 ? 'V' : 'N', $this->read(4));
|
||||
return array_shift($end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a string
|
||||
*
|
||||
* @access public
|
||||
* @param string string to be translated
|
||||
* @param integer $num found string number
|
||||
* @return string translated string (or original, if not found)
|
||||
*/
|
||||
public function translate($string, &$num)
|
||||
{
|
||||
if ($this->short_circuit)
|
||||
return $string;
|
||||
$this->load_tables();
|
||||
|
||||
if ($this->enable_cache) {
|
||||
// Caching enabled, get translated string from cache
|
||||
if (array_key_exists($string, $this->cache_translations))
|
||||
return $this->cache_translations[$string];
|
||||
else
|
||||
return $string;
|
||||
} else {
|
||||
// Caching not enabled, try to find string
|
||||
$num = $this->find_string($string);
|
||||
if ($num == - 1)
|
||||
return $string;
|
||||
else
|
||||
return $this->get_translation_string($num);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the translation tables from the MO file into the cache
|
||||
* If caching is enabled, also loads all strings into a cache
|
||||
@@ -168,23 +229,26 @@ class Typecho_I18n_GetText
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
private function load_tables()
|
||||
private function loadTables()
|
||||
{
|
||||
if (is_array($this->cache_translations) &&
|
||||
if (
|
||||
is_array($this->cache_translations) &&
|
||||
is_array($this->table_originals) &&
|
||||
is_array($this->table_translations))
|
||||
is_array($this->table_translations)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* get original and translations tables */
|
||||
fseek($this->STREAM, $this->originals);
|
||||
$this->table_originals = $this->readintarray($this->total * 2);
|
||||
$this->table_originals = $this->readIntArray($this->total * 2);
|
||||
fseek($this->STREAM, $this->translations);
|
||||
$this->table_translations = $this->readintarray($this->total * 2);
|
||||
$this->table_translations = $this->readIntArray($this->total * 2);
|
||||
|
||||
if ($this->enable_cache) {
|
||||
$this->cache_translations = ['' => null];
|
||||
/* read all strings in the cache */
|
||||
for ($i = 0; $i < $this->total; $i ++) {
|
||||
for ($i = 0; $i < $this->total; $i++) {
|
||||
if ($this->table_originals[$i * 2 + 1] > 0) {
|
||||
fseek($this->STREAM, $this->table_originals[$i * 2 + 2]);
|
||||
$original = fread($this->STREAM, $this->table_originals[$i * 2 + 1]);
|
||||
@@ -200,11 +264,11 @@ class Typecho_I18n_GetText
|
||||
* Reads an array of Integers from the Stream
|
||||
*
|
||||
* @param int count How many elements should be read
|
||||
* @return Array of Integers
|
||||
* @return array of Integers
|
||||
*/
|
||||
private function readintarray($count)
|
||||
private function readIntArray($count): array
|
||||
{
|
||||
return unpack(($this->BYTEORDER == 0 ? 'V' : 'N') . $count, $this->read(4 * $count));
|
||||
return unpack(($this->BYTE_ORDER == 0 ? 'V' : 'N') . $count, $this->read(4 * $count));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,36 +280,37 @@ class Typecho_I18n_GetText
|
||||
* @param int end (internally used in recursive function)
|
||||
* @return int string number (offset in originals table)
|
||||
*/
|
||||
private function find_string($string, $start = - 1, $end = - 1)
|
||||
private function findString($string, $start = -1, $end = -1): int
|
||||
{
|
||||
if (($start == - 1) or ($end == - 1)) {
|
||||
// find_string is called with only one parameter, set start end end
|
||||
if (($start == -1) or ($end == -1)) {
|
||||
// findString is called with only one parameter, set start end end
|
||||
$start = 0;
|
||||
$end = $this->total;
|
||||
}
|
||||
if (abs($start - $end) <= 1) {
|
||||
// We're done, now we either found the string, or it doesn't exist
|
||||
$txt = $this->get_original_string($start);
|
||||
if ($string == $txt)
|
||||
$txt = $this->getOriginalString($start);
|
||||
if ($string == $txt) {
|
||||
return $start;
|
||||
else
|
||||
return - 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} elseif ($start > $end) {
|
||||
// start > end -> turn around and start over
|
||||
return $this->find_string($string, $end, $start);
|
||||
return $this->findString($string, $end, $start);
|
||||
} else {
|
||||
// Divide table in two parts
|
||||
$half = (int)(($start + $end) / 2);
|
||||
$cmp = strcmp($string, $this->get_original_string($half));
|
||||
if ($cmp == 0)
|
||||
$cmp = strcmp($string, $this->getOriginalString($half));
|
||||
if ($cmp == 0) {
|
||||
// string is exactly in the middle => return it
|
||||
return $half;
|
||||
elseif ($cmp < 0)
|
||||
} elseif ($cmp < 0) {
|
||||
// The string is in the upper half
|
||||
return $this->find_string($string, $start, $half);
|
||||
else
|
||||
// The string is in the lower half
|
||||
return $this->find_string($string, $half, $end);
|
||||
return $this->findString($string, $start, $half);
|
||||
} else { // The string is in the lower half
|
||||
return $this->findString($string, $half, $end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,12 +321,13 @@ class Typecho_I18n_GetText
|
||||
* @param int num Offset number of original string
|
||||
* @return string Requested string if found, otherwise ''
|
||||
*/
|
||||
private function get_original_string($num)
|
||||
private function getOriginalString($num): string
|
||||
{
|
||||
$length = $this->table_originals[$num * 2 + 1];
|
||||
$offset = $this->table_originals[$num * 2 + 2];
|
||||
if (!$length)
|
||||
if (!$length) {
|
||||
return '';
|
||||
}
|
||||
fseek($this->STREAM, $offset);
|
||||
$data = fread($this->STREAM, $length);
|
||||
return (string)$data;
|
||||
@@ -274,65 +340,18 @@ class Typecho_I18n_GetText
|
||||
* @param int num Offset number of original string
|
||||
* @return string Requested string if found, otherwise ''
|
||||
*/
|
||||
private function get_translation_string($num)
|
||||
private function getTranslationString($num): string
|
||||
{
|
||||
$length = $this->table_translations[$num * 2 + 1];
|
||||
$offset = $this->table_translations[$num * 2 + 2];
|
||||
if (!$length)
|
||||
if (!$length) {
|
||||
return '';
|
||||
}
|
||||
fseek($this->STREAM, $offset);
|
||||
$data = fread($this->STREAM, $length);
|
||||
return (string)$data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plural version of gettext
|
||||
*
|
||||
* @access public
|
||||
* @param string single
|
||||
* @param string plural
|
||||
* @param string number
|
||||
* @param integer $num found string number
|
||||
* @return translated plural form
|
||||
*/
|
||||
public function ngettext($single, $plural, $number, &$num)
|
||||
{
|
||||
$number = intval($number);
|
||||
|
||||
if ($this->short_circuit) {
|
||||
if ($number != 1)
|
||||
return $plural;
|
||||
else
|
||||
return $single;
|
||||
}
|
||||
|
||||
// find out the appropriate form
|
||||
$select = $this->select_string($number);
|
||||
|
||||
// this should contains all strings separated by NULLs
|
||||
$key = $single . chr(0) . $plural;
|
||||
|
||||
|
||||
if ($this->enable_cache) {
|
||||
if (!array_key_exists($key, $this->cache_translations)) {
|
||||
return ($number != 1) ? $plural : $single;
|
||||
} else {
|
||||
$result = $this->cache_translations[$key];
|
||||
$list = explode(chr(0), $result);
|
||||
return $list[$select];
|
||||
}
|
||||
} else {
|
||||
$num = $this->find_string($key);
|
||||
if ($num == - 1) {
|
||||
return ($number != 1) ? $plural : $single;
|
||||
} else {
|
||||
$result = $this->get_translation_string($num);
|
||||
$list = explode(chr(0), $result);
|
||||
return $list[$select];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects which plural form to take
|
||||
*
|
||||
@@ -340,9 +359,9 @@ class Typecho_I18n_GetText
|
||||
* @param n count
|
||||
* @return int array index of the right plural form
|
||||
*/
|
||||
private function select_string($n)
|
||||
private function selectString($n): int
|
||||
{
|
||||
$string = $this->get_plural_forms();
|
||||
$string = $this->getPluralForms();
|
||||
$string = str_replace('nplurals', "\$total", $string);
|
||||
$string = str_replace("n", $n, $string);
|
||||
$string = str_replace('plural', "\$plural", $string);
|
||||
@@ -351,7 +370,9 @@ class Typecho_I18n_GetText
|
||||
$plural = 0;
|
||||
|
||||
eval("$string");
|
||||
if ($plural >= $total) $plural = $total - 1;
|
||||
if ($plural >= $total) {
|
||||
$plural = $total - 1;
|
||||
}
|
||||
return $plural;
|
||||
}
|
||||
|
||||
@@ -361,36 +382,26 @@ class Typecho_I18n_GetText
|
||||
* @access private
|
||||
* @return string plural form header
|
||||
*/
|
||||
private function get_plural_forms()
|
||||
private function getPluralForms(): string
|
||||
{
|
||||
// lets assume message number 0 is header
|
||||
// this is true, right?
|
||||
$this->load_tables();
|
||||
$this->loadTables();
|
||||
|
||||
// cache header field for plural forms
|
||||
if (!is_string($this->pluralheader)) {
|
||||
if (!is_string($this->pluralHeader)) {
|
||||
if ($this->enable_cache) {
|
||||
$header = $this->cache_translations[""];
|
||||
} else {
|
||||
$header = $this->get_translation_string(0);
|
||||
$header = $this->getTranslationString(0);
|
||||
}
|
||||
if (preg_match("/plural\-forms: ([^\n]*)\n/i", $header, $regs))
|
||||
if (preg_match("/plural\-forms: ([^\n]*)\n/i", $header, $regs)) {
|
||||
$expr = $regs[1];
|
||||
else
|
||||
} else {
|
||||
$expr = "nplurals=2; plural=n == 1 ? 0 : 1;";
|
||||
$this->pluralheader = $expr;
|
||||
}
|
||||
$this->pluralHeader = $expr;
|
||||
}
|
||||
return $this->pluralheader;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭文件句柄
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
fclose($this->STREAM);
|
||||
return $this->pluralHeader;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Typecho Blog Platform
|
||||
*
|
||||
* @copyright Copyright (c) 2008 Typecho team (http://www.typecho.org)
|
||||
* @license GNU General Public License 2.0
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
namespace Typecho\I18n;
|
||||
|
||||
/**
|
||||
* 用于解决一个多个mo文件带来的读写问题
|
||||
@@ -15,15 +10,15 @@
|
||||
* @category typecho
|
||||
* @package I18n
|
||||
*/
|
||||
class Typecho_I18n_GetTextMulti
|
||||
class GetTextMulti
|
||||
{
|
||||
/**
|
||||
* 所有的文件读写句柄
|
||||
*
|
||||
* @access private
|
||||
* @var Typecho_I18n_GetText[]
|
||||
* @var GetText[]
|
||||
*/
|
||||
private $_handles = [];
|
||||
private $handlers = [];
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
@@ -32,7 +27,7 @@ class Typecho_I18n_GetTextMulti
|
||||
* @param string $fileName 语言文件名
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($fileName)
|
||||
public function __construct(string $fileName)
|
||||
{
|
||||
$this->addFile($fileName);
|
||||
}
|
||||
@@ -44,9 +39,9 @@ class Typecho_I18n_GetTextMulti
|
||||
* @param string $fileName 语言文件名
|
||||
* @return void
|
||||
*/
|
||||
public function addFile($fileName)
|
||||
public function addFile(string $fileName)
|
||||
{
|
||||
$this->_handles[] = new Typecho_I18n_GetText($fileName, true);
|
||||
$this->handlers[] = new GetText($fileName, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,9 +51,9 @@ class Typecho_I18n_GetTextMulti
|
||||
* @param string string to be translated
|
||||
* @return string translated string (or original, if not found)
|
||||
*/
|
||||
public function translate($string)
|
||||
public function translate(string $string): string
|
||||
{
|
||||
foreach ($this->_handles as $handle) {
|
||||
foreach ($this->handlers as $handle) {
|
||||
$string = $handle->translate($string, $count);
|
||||
if (- 1 != $count) {
|
||||
break;
|
||||
@@ -75,14 +70,14 @@ class Typecho_I18n_GetTextMulti
|
||||
* @param string single
|
||||
* @param string plural
|
||||
* @param string number
|
||||
* @return translated plural form
|
||||
* @return string translated plural form
|
||||
*/
|
||||
public function ngettext($single, $plural, $number)
|
||||
public function ngettext($single, $plural, $number): string
|
||||
{
|
||||
$count = - 1;
|
||||
|
||||
foreach ($this->_handles as $handle) {
|
||||
$string = $handle->ngettext($single, $plural, $number, $count);
|
||||
foreach ($this->handlers as $handler) {
|
||||
$string = $handler->ngettext($single, $plural, $number, $count);
|
||||
if (- 1 != $count) {
|
||||
break;
|
||||
}
|
||||
@@ -99,9 +94,9 @@ class Typecho_I18n_GetTextMulti
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
foreach ($this->_handles as $handle) {
|
||||
foreach ($this->handlers as $handler) {
|
||||
/** 显示的释放内存 */
|
||||
unset($handle);
|
||||
unset($handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,13 +41,13 @@ class Router
|
||||
*
|
||||
* @access public
|
||||
*
|
||||
* @param string $pathInfo 全路径
|
||||
* @param string|null $pathInfo 全路径
|
||||
* @param mixed $parameter 输入参数
|
||||
*
|
||||
* @return false|Widget
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function match(string $pathInfo, $parameter = null)
|
||||
public static function match(?string $pathInfo, $parameter = null)
|
||||
{
|
||||
foreach (self::$routingTable as $key => $route) {
|
||||
if (preg_match($route['regx'], $pathInfo, $matches)) {
|
||||
|
||||
Reference in New Issue
Block a user