Merge pull request #1131 from typecho/dev

Say goodbye to old install script. Now we support install from cli, and ready for container using.
This commit is contained in:
joyqi 2021-08-18 16:19:57 +08:00 committed by GitHub
commit 8f61e2155c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 2769 additions and 3040 deletions

24
admin/css/install.css Normal file
View File

@ -0,0 +1,24 @@
h1 { text-align: center; }
details summary { cursor: pointer; }
@keyframes fadein { from { opacity: 0; }
to { opacity: 1; } }
.fresh .keep-word { display: none; }
.keep .fresh-word { display: none; }
form > .message { display: none; padding: 20px; border-radius: 5px; }
.message textarea { width: 100%; height: 200px; resize: none; margin: 10px 0; }
.message.fade { display: block; animation: fadein .5s linear; }
.message *:last-child { margin-bottom: 0; }
.message p { margin-top: 10px; }
.message p button { margin-left: 5px; }
.message p button:first-child { margin-left: 0; }

View File

@ -237,27 +237,6 @@ select { border: 1px solid #CCC; height: 28px; }
.profile-avatar { width: 220px; height: 220px; border-radius: 10px; }
/** 增加配置面板内部的错误样式 by 70 */
/** 安装样式 @author mingcheng @date 2008-09-06 */
/** 安装向导 */
.typecho-install { padding-bottom: 2em; }
.typecho-install-patch { margin-bottom: 2em; padding: 2em 0; background-color: #292D33; color: #FFF; text-align: center; }
.typecho-install-patch ol { list-style: none; margin: 3em 0 1em; padding: 0; color: #999; }
.typecho-install-patch li { display: inline-block; margin: 0 .8em; }
.typecho-install-patch span { display: inline-block; margin-right: 5px; width: 20px; height: 20px; line-height: 20px; border: 2px solid #999; text-align: center; border-radius: 2em; }
.typecho-install-patch li.current { color: #FFF; font-weight: bold; }
.typecho-install-patch li.current span { border-color: #FFF; }
/** 安装主体内容 */
.typecho-install .typecho-install-body input { width: 100%; }
.typecho-install-body .typecho-option li { margin: 1em 0; }
/** 欢迎界面 */
#typecho-welcome { margin: 1em 0; padding: 1em 2em; background-color: #E9E9E6; }

View File

@ -5,20 +5,15 @@ if (!defined('__TYPECHO_ADMIN__')) {
$header = '<link rel="stylesheet" href="' . Typecho_Common::url('normalize.css?v=' . $suffixVersion, $options->adminStaticUrl('css')) . '">
<link rel="stylesheet" href="' . Typecho_Common::url('grid.css?v=' . $suffixVersion, $options->adminStaticUrl('css')) . '">
<link rel="stylesheet" href="' . Typecho_Common::url('style.css?v=' . $suffixVersion, $options->adminStaticUrl('css')) . '">
<!--[if lt IE 9]>
<script src="' . Typecho_Common::url('html5shiv.js?v=' . $suffixVersion, $options->adminStaticUrl('js')) . '"></script>
<script src="' . Typecho_Common::url('respond.js?v=' . $suffixVersion, $options->adminStaticUrl('js')) . '"></script>
<![endif]-->';
<link rel="stylesheet" href="' . Typecho_Common::url('style.css?v=' . $suffixVersion, $options->adminStaticUrl('css')) . '">';
/** 注册一个初始化插件 */
$header = Typecho_Plugin::factory('admin/header.php')->header($header);
?><!DOCTYPE HTML>
<html class="no-js">
<html>
<head>
<meta charset="<?php $options->charset(); ?>">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title><?php _e('%s - %s - Powered by Typecho', $menu->title, $options->title); ?></title>

View File

@ -1 +0,0 @@
!function(e,i){var l,m,t=e.html5||{},a=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,n="_html5shiv",c=0,o={};function s(){var e=f.elements;return"string"==typeof e?e.split(" "):e}function h(e){var t=o[e[n]];return t||(t={},c++,e[n]=c,o[c]=t),t}function u(e,t,n){return t=t||i,m?t.createElement(e):(t=(n=n||h(t)).cache[e]?n.cache[e].cloneNode():r.test(e)?(n.cache[e]=n.createElem(e)).cloneNode():n.createElem(e)).canHaveChildren&&!a.test(e)?n.frag.appendChild(t):t}function d(e){var t,n,a,r,c,o=h(e=e||i);return!f.shivCSS||l||o.hasCSS||(o.hasCSS=(n="article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}",a=(t=e).createElement("p"),t=t.getElementsByTagName("head")[0]||t.documentElement,a.innerHTML="x<style>"+n+"</style>",!!t.insertBefore(a.lastChild,t.firstChild))),m||(r=e,(c=o).cache||(c.cache={},c.createElem=r.createElement,c.createFrag=r.createDocumentFragment,c.frag=c.createFrag()),r.createElement=function(e){return f.shivMethods?u(e,r,c):c.createElem(e)},r.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+s().join().replace(/[\w\-]+/g,function(e){return c.createElem(e),c.frag.createElement(e),'c("'+e+'")'})+");return n}")(f,c.frag)),e}!function(){try{var e=i.createElement("a");e.innerHTML="<xyz></xyz>",l="hidden"in e,m=1==e.childNodes.length||function(){i.createElement("a");var e=i.createDocumentFragment();return void 0===e.cloneNode||void 0===e.createDocumentFragment||void 0===e.createElement}()}catch(e){m=l=!0}}();var f={elements:t.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:"3.7.0",shivCSS:!1!==t.shivCSS,supportsUnknownElements:m,shivMethods:!1!==t.shivMethods,type:"default",shivDocument:d,createElement:u,createDocumentFragment:function(e,t){if(e=e||i,m)return e.createDocumentFragment();for(var n=(t=t||h(e)).frag.cloneNode(),a=0,r=s(),c=r.length;a<c;a++)n.createElement(r[a]);return n}};e.html5=f,d(i)}(this,document);

View File

@ -1 +0,0 @@
!function(e){"use strict";var t,n,s,a,i;e.matchMedia=e.matchMedia||(e=e.document,n=e.documentElement,s=n.firstElementChild||n.firstChild,a=e.createElement("body"),(i=e.createElement("div")).id="mq-test-1",i.style.cssText="position:absolute;top:-100em",a.style.background="none",a.appendChild(i),function(e){return i.innerHTML='&shy;<style media="'+e+'"> #mq-test-1 { width: 42px; }</style>',n.insertBefore(a,s),t=42===i.offsetWidth,n.removeChild(a),{matches:t,media:e}})}(this),function(g){"use strict";var c={};(g.respond=c).update=function(){};var y,x,E,v,w,i,S,T,r,C,b,$,z,M,R,o,l,e,m=[],s=function(){var t=!1;try{t=new g.XMLHttpRequest}catch(e){t=new g.ActiveXObject("Microsoft.XMLHTTP")}return function(){return t}}(),n=function(e,t){var n=s();n&&(n.open("GET",e,!0),n.onreadystatechange=function(){4!==n.readyState||200!==n.status&&304!==n.status||t(n.responseText)},4!==n.readyState&&n.send(null))},p=function(e){return e.replace(c.regex.minmaxwh,"").match(c.regex.other)};function t(){R(!0)}c.ajax=n,c.queue=m,c.unsupportedmq=p,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,comments:/\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,maxw:/\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,minmaxwh:/\(\s*m(in|ax)\-(height|width)\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/gi,other:/\([^\)]*\)/g},c.mediaQueriesSupported=g.matchMedia&&null!==g.matchMedia("only all")&&g.matchMedia("only all").matches,c.mediaQueriesSupported||(y=g.document,x=y.documentElement,E=[],v=[],w=[],i={},S=30,T=y.getElementsByTagName("head")[0]||x,r=y.getElementsByTagName("base")[0],C=T.getElementsByTagName("link"),M=function(){var e,t=y.createElement("div"),n=y.body,s=x.style.fontSize,a=n&&n.style.fontSize,i=!1;return t.style.cssText="position:absolute;font-size:1em;width:1em",n||((n=i=y.createElement("body")).style.background="none"),x.style.fontSize="100%",n.style.fontSize="100%",n.appendChild(t),i&&x.insertBefore(n,x.firstChild),e=t.offsetWidth,i?x.removeChild(n):n.removeChild(t),x.style.fontSize=s,a&&(n.style.fontSize=a),z=parseFloat(e),z},R=function(e){var t,n,s,a,i,r,o,l,m,d,h="clientWidth",u=x[h],c="CSS1Compat"===y.compatMode&&u||y.body[h]||u,p={},f=C[C.length-1],u=(new Date).getTime();if(e&&b&&u-b<S)return g.clearTimeout($),void($=g.setTimeout(R,S));for(t in b=u,E)E.hasOwnProperty(t)&&(s=null===(i=(n=E[t]).minw),a=null===(r=n.maxw),i=i&&parseFloat(i)*(-1<i.indexOf("em")?z||M():1),r=r&&parseFloat(r)*(-1<r.indexOf("em")?z||M():1),n.hasquery&&(s&&a||!(s||i<=c)||!(a||c<=r))||(p[n.media]||(p[n.media]=[]),p[n.media].push(v[n.rules])));for(o in w)w.hasOwnProperty(o)&&w[o]&&w[o].parentNode===T&&T.removeChild(w[o]);for(l in w.length=0,p)p.hasOwnProperty(l)&&(m=y.createElement("style"),d=p[l].join("\n"),m.type="text/css",m.media=l,T.insertBefore(m,f.nextSibling),m.styleSheet?m.styleSheet.cssText=d:m.appendChild(y.createTextNode(d)),w.push(m))},o=function(e,t,n){function s(e){return e.replace(c.regex.urls,"$1"+t+"$2$3")}var a=e.replace(c.regex.comments,"").replace(c.regex.keyframes,"").match(c.regex.media),i=a&&a.length||0,r=!i&&n;(t=t.substring(0,t.lastIndexOf("/"))).length&&(t+="/"),r&&(i=1);for(var o,l,m=0;m<i;m++){r?(o=n,v.push(s(e))):(o=a[m].match(c.regex.findStyles)&&RegExp.$1,v.push(RegExp.$2&&s(RegExp.$2)));for(var d,h=(d=o.split(",")).length,u=0;u<h;u++)l=d[u],p(l)||E.push({media:l.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:v.length-1,hasquery:-1<l.indexOf("("),minw:l.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:l.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}R()},l=function(){var t;m.length&&(t=m.shift(),n(t.href,function(e){o(e,t.href,t.media),i[t.href]=!0,g.setTimeout(function(){l()},0)}))},(e=function(){for(var e=0;e<C.length;e++){var t=C[e],n=t.href,s=t.media,a=t.rel&&"stylesheet"===t.rel.toLowerCase();n&&a&&!i[n]&&(t.styleSheet&&t.styleSheet.rawCssText?(o(t.styleSheet.rawCssText,n,s),i[n]=!0):(/^([a-zA-Z:]*\/\/)/.test(n)||r)&&n.replace(RegExp.$1,"").split("/")[0]!==g.location.host||("//"===n.substring(0,2)&&(n=g.location.protocol+n),m.push({href:n,media:s})))}l()})(),c.update=e,c.getEmValue=M,g.addEventListener?g.addEventListener("resize",t,!1):g.attachEvent&&g.attachEvent("onresize",t))}(this);

View File

@ -1,301 +0,0 @@
/**
* @preserve HTML5 Shiv v3.7.0 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
;(function(window, document) {
/*jshint evil:true */
/** version */
var version = '3.7.0';
/** Preset options */
var options = window.html5 || {};
/** Used to skip problem elements */
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
/** Not all elements can be cloned in IE **/
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
/** Detect whether the browser supports default html5 styles */
var supportsHtml5Styles;
/** Name of the expando, to work with multiple documents or to re-shiv one document */
var expando = '_html5shiv';
/** The id for the the documents expando */
var expanID = 0;
/** Cached data for each document */
var expandoData = {};
/** Detect whether the browser supports unknown elements */
var supportsUnknownElements;
(function() {
try {
var a = document.createElement('a');
a.innerHTML = '<xyz></xyz>';
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
supportsHtml5Styles = ('hidden' in a);
supportsUnknownElements = a.childNodes.length == 1 || (function() {
// assign a false positive if unable to shiv
(document.createElement)('a');
var frag = document.createDocumentFragment();
return (
typeof frag.cloneNode == 'undefined' ||
typeof frag.createDocumentFragment == 'undefined' ||
typeof frag.createElement == 'undefined'
);
}());
} catch(e) {
// assign a false positive if detection fails => unable to shiv
supportsHtml5Styles = true;
supportsUnknownElements = true;
}
}());
/*--------------------------------------------------------------------------*/
/**
* Creates a style sheet with the given CSS text and adds it to the document.
* @private
* @param {Document} ownerDocument The document.
* @param {String} cssText The CSS text.
* @returns {StyleSheet} The style element.
*/
function addStyleSheet(ownerDocument, cssText) {
var p = ownerDocument.createElement('p'),
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
p.innerHTML = 'x<style>' + cssText + '</style>';
return parent.insertBefore(p.lastChild, parent.firstChild);
}
/**
* Returns the value of `html5.elements` as an array.
* @private
* @returns {Array} An array of shived element node names.
*/
function getElements() {
var elements = html5.elements;
return typeof elements == 'string' ? elements.split(' ') : elements;
}
/**
* Returns the data associated to the given document
* @private
* @param {Document} ownerDocument The document.
* @returns {Object} An object of data.
*/
function getExpandoData(ownerDocument) {
var data = expandoData[ownerDocument[expando]];
if (!data) {
data = {};
expanID++;
ownerDocument[expando] = expanID;
expandoData[expanID] = data;
}
return data;
}
/**
* returns a shived element for the given nodeName and document
* @memberOf html5
* @param {String} nodeName name of the element
* @param {Document} ownerDocument The context document.
* @returns {Object} The shived element.
*/
function createElement(nodeName, ownerDocument, data){
if (!ownerDocument) {
ownerDocument = document;
}
if(supportsUnknownElements){
return ownerDocument.createElement(nodeName);
}
if (!data) {
data = getExpandoData(ownerDocument);
}
var node;
if (data.cache[nodeName]) {
node = data.cache[nodeName].cloneNode();
} else if (saveClones.test(nodeName)) {
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
} else {
node = data.createElem(nodeName);
}
// Avoid adding some elements to fragments in IE < 9 because
// * Attributes like `name` or `type` cannot be set/changed once an element
// is inserted into a document/fragment
// * Link elements with `src` attributes that are inaccessible, as with
// a 403 response, will cause the tab/window to crash
// * Script elements appended to fragments will execute when their `src`
// or `text` property is set
return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node;
}
/**
* returns a shived DocumentFragment for the given document
* @memberOf html5
* @param {Document} ownerDocument The context document.
* @returns {Object} The shived DocumentFragment.
*/
function createDocumentFragment(ownerDocument, data){
if (!ownerDocument) {
ownerDocument = document;
}
if(supportsUnknownElements){
return ownerDocument.createDocumentFragment();
}
data = data || getExpandoData(ownerDocument);
var clone = data.frag.cloneNode(),
i = 0,
elems = getElements(),
l = elems.length;
for(;i<l;i++){
clone.createElement(elems[i]);
}
return clone;
}
/**
* Shivs the `createElement` and `createDocumentFragment` methods of the document.
* @private
* @param {Document|DocumentFragment} ownerDocument The document.
* @param {Object} data of the document.
*/
function shivMethods(ownerDocument, data) {
if (!data.cache) {
data.cache = {};
data.createElem = ownerDocument.createElement;
data.createFrag = ownerDocument.createDocumentFragment;
data.frag = data.createFrag();
}
ownerDocument.createElement = function(nodeName) {
//abort shiv
if (!html5.shivMethods) {
return data.createElem(nodeName);
}
return createElement(nodeName, ownerDocument, data);
};
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
'var n=f.cloneNode(),c=n.createElement;' +
'h.shivMethods&&(' +
// unroll the `createElement` calls
getElements().join().replace(/[\w\-]+/g, function(nodeName) {
data.createElem(nodeName);
data.frag.createElement(nodeName);
return 'c("' + nodeName + '")';
}) +
');return n}'
)(html5, data.frag);
}
/*--------------------------------------------------------------------------*/
/**
* Shivs the given document.
* @memberOf html5
* @param {Document} ownerDocument The document to shiv.
* @returns {Document} The shived document.
*/
function shivDocument(ownerDocument) {
if (!ownerDocument) {
ownerDocument = document;
}
var data = getExpandoData(ownerDocument);
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
data.hasCSS = !!addStyleSheet(ownerDocument,
// corrects block display not defined in IE6/7/8/9
'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
// adds styling not present in IE6/7/8/9
'mark{background:#FF0;color:#000}' +
// hides non-rendered elements
'template{display:none}'
);
}
if (!supportsUnknownElements) {
shivMethods(ownerDocument, data);
}
return ownerDocument;
}
/*--------------------------------------------------------------------------*/
/**
* The `html5` object is exposed so that more elements can be shived and
* existing shiving can be detected on iframes.
* @type Object
* @example
*
* // options can be changed before the script is included
* html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
*/
var html5 = {
/**
* An array or space separated string of node names of the elements to shiv.
* @memberOf html5
* @type Array|String
*/
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video',
/**
* current version of html5shiv
*/
'version': version,
/**
* A flag to indicate that the HTML5 style sheet should be inserted.
* @memberOf html5
* @type Boolean
*/
'shivCSS': (options.shivCSS !== false),
/**
* Is equal to true if a browser supports creating unknown/HTML5 elements
* @memberOf html5
* @type boolean
*/
'supportsUnknownElements': supportsUnknownElements,
/**
* A flag to indicate that the document's `createElement` and `createDocumentFragment`
* methods should be overwritten.
* @memberOf html5
* @type Boolean
*/
'shivMethods': (options.shivMethods !== false),
/**
* A string to describe the type of `html5` object ("default" or "default print").
* @memberOf html5
* @type String
*/
'type': 'default',
// shivs the document according to the specified `html5` object options
'shivDocument': shivDocument,
//creates a shived element
createElement: createElement,
//creates a shived documentFragment
createDocumentFragment: createDocumentFragment
};
/*--------------------------------------------------------------------------*/
// expose html5
window.html5 = html5;
// shiv the document
shivDocument(document);
}(this, document));

View File

@ -1,237 +0,0 @@
/*! Respond.js v1.4.2: min/max-width media query polyfill
* Copyright 2013 Scott Jehl
* Licensed under MIT
* http://j.mp/respondjs */
/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
/*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
(function(w) {
"use strict";
w.matchMedia = w.matchMedia || function(doc, undefined) {
var bool, docElem = doc.documentElement, refNode = docElem.firstElementChild || docElem.firstChild, fakeBody = doc.createElement("body"), div = doc.createElement("div");
div.id = "mq-test-1";
div.style.cssText = "position:absolute;top:-100em";
fakeBody.style.background = "none";
fakeBody.appendChild(div);
return function(q) {
div.innerHTML = '&shy;<style media="' + q + '"> #mq-test-1 { width: 42px; }</style>';
docElem.insertBefore(fakeBody, refNode);
bool = div.offsetWidth === 42;
docElem.removeChild(fakeBody);
return {
matches: bool,
media: q
};
};
}(w.document);
})(this);
(function(w) {
"use strict";
var respond = {};
w.respond = respond;
respond.update = function() {};
var requestQueue = [], xmlHttp = function() {
var xmlhttpmethod = false;
try {
xmlhttpmethod = new w.XMLHttpRequest();
} catch (e) {
xmlhttpmethod = new w.ActiveXObject("Microsoft.XMLHTTP");
}
return function() {
return xmlhttpmethod;
};
}(), ajax = function(url, callback) {
var req = xmlHttp();
if (!req) {
return;
}
req.open("GET", url, true);
req.onreadystatechange = function() {
if (req.readyState !== 4 || req.status !== 200 && req.status !== 304) {
return;
}
callback(req.responseText);
};
if (req.readyState === 4) {
return;
}
req.send(null);
}, isUnsupportedMediaQuery = function(query) {
return query.replace(respond.regex.minmaxwh, "").match(respond.regex.other);
};
respond.ajax = ajax;
respond.queue = requestQueue;
respond.unsupportedmq = isUnsupportedMediaQuery;
respond.regex = {
media: /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,
keyframes: /@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,
comments: /\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,
urls: /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,
findStyles: /@media *([^\{]+)\{([\S\s]+?)$/,
only: /(only\s+)?([a-zA-Z]+)\s?/,
minw: /\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,
maxw: /\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,
minmaxwh: /\(\s*m(in|ax)\-(height|width)\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/gi,
other: /\([^\)]*\)/g
};
respond.mediaQueriesSupported = w.matchMedia && w.matchMedia("only all") !== null && w.matchMedia("only all").matches;
if (respond.mediaQueriesSupported) {
return;
}
var doc = w.document, docElem = doc.documentElement, mediastyles = [], rules = [], appendedEls = [], parsedSheets = {}, resizeThrottle = 30, head = doc.getElementsByTagName("head")[0] || docElem, base = doc.getElementsByTagName("base")[0], links = head.getElementsByTagName("link"), lastCall, resizeDefer, eminpx, getEmValue = function() {
var ret, div = doc.createElement("div"), body = doc.body, originalHTMLFontSize = docElem.style.fontSize, originalBodyFontSize = body && body.style.fontSize, fakeUsed = false;
div.style.cssText = "position:absolute;font-size:1em;width:1em";
if (!body) {
body = fakeUsed = doc.createElement("body");
body.style.background = "none";
}
docElem.style.fontSize = "100%";
body.style.fontSize = "100%";
body.appendChild(div);
if (fakeUsed) {
docElem.insertBefore(body, docElem.firstChild);
}
ret = div.offsetWidth;
if (fakeUsed) {
docElem.removeChild(body);
} else {
body.removeChild(div);
}
docElem.style.fontSize = originalHTMLFontSize;
if (originalBodyFontSize) {
body.style.fontSize = originalBodyFontSize;
}
ret = eminpx = parseFloat(ret);
return ret;
}, applyMedia = function(fromResize) {
var name = "clientWidth", docElemProp = docElem[name], currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[name] || docElemProp, styleBlocks = {}, lastLink = links[links.length - 1], now = new Date().getTime();
if (fromResize && lastCall && now - lastCall < resizeThrottle) {
w.clearTimeout(resizeDefer);
resizeDefer = w.setTimeout(applyMedia, resizeThrottle);
return;
} else {
lastCall = now;
}
for (var i in mediastyles) {
if (mediastyles.hasOwnProperty(i)) {
var thisstyle = mediastyles[i], min = thisstyle.minw, max = thisstyle.maxw, minnull = min === null, maxnull = max === null, em = "em";
if (!!min) {
min = parseFloat(min) * (min.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
}
if (!!max) {
max = parseFloat(max) * (max.indexOf(em) > -1 ? eminpx || getEmValue() : 1);
}
if (!thisstyle.hasquery || (!minnull || !maxnull) && (minnull || currWidth >= min) && (maxnull || currWidth <= max)) {
if (!styleBlocks[thisstyle.media]) {
styleBlocks[thisstyle.media] = [];
}
styleBlocks[thisstyle.media].push(rules[thisstyle.rules]);
}
}
}
for (var j in appendedEls) {
if (appendedEls.hasOwnProperty(j)) {
if (appendedEls[j] && appendedEls[j].parentNode === head) {
head.removeChild(appendedEls[j]);
}
}
}
appendedEls.length = 0;
for (var k in styleBlocks) {
if (styleBlocks.hasOwnProperty(k)) {
var ss = doc.createElement("style"), css = styleBlocks[k].join("\n");
ss.type = "text/css";
ss.media = k;
head.insertBefore(ss, lastLink.nextSibling);
if (ss.styleSheet) {
ss.styleSheet.cssText = css;
} else {
ss.appendChild(doc.createTextNode(css));
}
appendedEls.push(ss);
}
}
}, translate = function(styles, href, media) {
var qs = styles.replace(respond.regex.comments, "").replace(respond.regex.keyframes, "").match(respond.regex.media), ql = qs && qs.length || 0;
href = href.substring(0, href.lastIndexOf("/"));
var repUrls = function(css) {
return css.replace(respond.regex.urls, "$1" + href + "$2$3");
}, useMedia = !ql && media;
if (href.length) {
href += "/";
}
if (useMedia) {
ql = 1;
}
for (var i = 0; i < ql; i++) {
var fullq, thisq, eachq, eql;
if (useMedia) {
fullq = media;
rules.push(repUrls(styles));
} else {
fullq = qs[i].match(respond.regex.findStyles) && RegExp.$1;
rules.push(RegExp.$2 && repUrls(RegExp.$2));
}
eachq = fullq.split(",");
eql = eachq.length;
for (var j = 0; j < eql; j++) {
thisq = eachq[j];
if (isUnsupportedMediaQuery(thisq)) {
continue;
}
mediastyles.push({
media: thisq.split("(")[0].match(respond.regex.only) && RegExp.$2 || "all",
rules: rules.length - 1,
hasquery: thisq.indexOf("(") > -1,
minw: thisq.match(respond.regex.minw) && parseFloat(RegExp.$1) + (RegExp.$2 || ""),
maxw: thisq.match(respond.regex.maxw) && parseFloat(RegExp.$1) + (RegExp.$2 || "")
});
}
}
applyMedia();
}, makeRequests = function() {
if (requestQueue.length) {
var thisRequest = requestQueue.shift();
ajax(thisRequest.href, function(styles) {
translate(styles, thisRequest.href, thisRequest.media);
parsedSheets[thisRequest.href] = true;
w.setTimeout(function() {
makeRequests();
}, 0);
});
}
}, ripCSS = function() {
for (var i = 0; i < links.length; i++) {
var sheet = links[i], href = sheet.href, media = sheet.media, isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
if (!!href && isCSS && !parsedSheets[href]) {
if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
translate(sheet.styleSheet.rawCssText, href, media);
parsedSheets[href] = true;
} else {
if (!/^([a-zA-Z:]*\/\/)/.test(href) && !base || href.replace(RegExp.$1, "").split("/")[0] === w.location.host) {
if (href.substring(0, 2) === "//") {
href = w.location.protocol + href;
}
requestQueue.push({
href: href,
media: media
});
}
}
}
}
makeRequests();
};
ripCSS();
respond.update = ripCSS;
respond.getEmValue = getEmValue;
function callMedia() {
applyMedia(true);
}
if (w.addEventListener) {
w.addEventListener("resize", callMedia, false);
} else if (w.attachEvent) {
w.attachEvent("onresize", callMedia);
}
})(this);

View File

@ -0,0 +1,63 @@
h1 {
text-align: center;
}
details {
summary {
cursor: pointer;
}
}
@keyframes fadein {
from { opacity: 0; }
to { opacity: 1; }
}
.fresh {
.keep-word {
display: none;
}
}
.keep {
.fresh-word {
display: none;
}
}
.message {
form > & {
display: none;
padding: 20px;
border-radius: 5px;
}
textarea {
width: 100%;
height: 200px;
resize: none;
margin: 10px 0;
}
&.fade {
display: block;
animation: fadein .5s linear;
}
*:last-child {
margin-bottom: 0;
}
p {
margin-top: 10px;
button {
margin-left: 5px;
}
button:first-child {
margin-left: 0;
}
}
}

View File

@ -179,68 +179,6 @@ a.button:hover, a.balloon-button:hover {
/** 增加配置面板内部的错误样式 by 70 */
/**
* 安装样式
*
* @author mingcheng
* @date 2008-09-06
*/
/**
* 安装向导
*/
.typecho-install {
padding-bottom: 2em;
}
.typecho-install-patch {
margin-bottom: 2em;
padding: 2em 0;
background-color: #292D33;
color: #FFF;
text-align: center;
}
.typecho-install-patch ol {
list-style: none;
margin: 3em 0 1em;
padding: 0;
color: #999;
}
.typecho-install-patch li {
display: inline-block;
margin: 0 .8em;
}
.typecho-install-patch span {
display: inline-block;
margin-right: 5px;
width: 20px;
height: 20px;
line-height: 20px;
border: 2px solid #999;
text-align: center;
border-radius: 2em;
}
.typecho-install-patch li.current {
color: #FFF;
font-weight: bold;
}
.typecho-install-patch li.current span {
border-color: #FFF;
}
/**
* 安装主体内容
*/
.typecho-install .typecho-install-body input {
width: 100%;
}
.typecho-install-body .typecho-option li {
margin: 1em 0;
}
/**
* 欢迎界面
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,165 +1,66 @@
<?php if(!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<?php
$engine = '';
if (defined('SAE_MYSQL_DB') && SAE_MYSQL_DB != "app_") {
$engine = 'SAE';
} else if (!!getenv('HTTP_BAE_ENV_ADDR_SQL_IP')) {
$engine = 'BAE';
} else if (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'],'Google App Engine') !== false) {
$engine = 'GAE';
}
?>
<?php if (!empty($engine)): ?>
<h3 class="warning"><?php _e('系统将为您自动匹配 %s 环境的安装选项', $engine); ?></h3>
<?php endif; ?>
<?php if ('SAE' == $engine): ?>
<!-- SAE -->
<input type="hidden" name="config" value="array (
'host' => SAE_MYSQL_HOST_M,
'user' => SAE_MYSQL_USER,
'password' => SAE_MYSQL_PASS,
'charset' => '{charset}',
'port' => SAE_MYSQL_PORT,
'database' => SAE_MYSQL_DB
)" />
<input type="hidden" name="dbHost" value="<?php echo SAE_MYSQL_HOST_M; ?>" />
<input type="hidden" name="dbPort" value="<?php echo SAE_MYSQL_PORT; ?>" />
<input type="hidden" name="dbUser" value="<?php echo SAE_MYSQL_USER; ?>" />
<input type="hidden" name="dbPassword" value="<?php echo SAE_MYSQL_PASS; ?>" />
<input type="hidden" name="dbDatabase" value="<?php echo SAE_MYSQL_DB; ?>" />
<?php elseif ('BAE' == $engine):
$baeDbUser = "getenv('HTTP_BAE_ENV_AK')";
$baeDbPassword = "getenv('HTTP_BAE_ENV_SK')";
?>
<!-- BAE -->
<?php if (!getenv('HTTP_BAE_ENV_AK')): $baeDbUser = "'{user}'"; ?>
<li>
<label class="typecho-label" for="dbUser"><?php _e('应用API Key'); ?></label>
<input type="text" class="text" name="dbUser" id="dbUser" value="<?php _v('dbUser'); ?>" />
</li>
<?php else: ?>
<input type="hidden" name="dbUser" value="<?php echo getenv('HTTP_BAE_ENV_AK'); ?>" />
<?php endif; ?>
<?php if (!getenv('HTTP_BAE_ENV_SK')): $baeDbPassword = "'{password}'"; ?>
<li>
<label class="typecho-label" for="dbPassword"><?php _e('应用Secret Key'); ?></label>
<input type="text" class="text" name="dbPassword" id="dbPassword" value="<?php _v('dbPassword'); ?>" />
</li>
<?php else: ?>
<input type="hidden" name="dbPassword" value="<?php echo getenv('HTTP_BAE_ENV_SK'); ?>" />
<?php endif; ?>
<li>
<label class="typecho-label" for="dbDatabase"><?php _e('数据库名'); ?></label>
<input type="text" class="text" id="dbDatabase" name="dbDatabase" value="<?php _v('dbDatabase'); ?>" />
<p class="description"><?php _e('可以在MySQL服务的管理页面看到您创建的数据库名称'); ?></p>
</li>
<input type="hidden" name="config" value="array (
'host' => getenv('HTTP_BAE_ENV_ADDR_SQL_IP'),
'user' => <?php echo $baeDbUser; ?>,
'password' => <?php echo $baeDbPassword; ?>,
'charset' => '{charset}',
'port' => getenv('HTTP_BAE_ENV_ADDR_SQL_PORT'),
'database' => '{database}'
)" />
<input type="hidden" name="dbHost" value="<?php echo getenv('HTTP_BAE_ENV_ADDR_SQL_IP'); ?>" />
<input type="hidden" name="dbPort" value="<?php echo getenv('HTTP_BAE_ENV_ADDR_SQL_PORT'); ?>" />
<?php elseif ('GAE' == $engine): ?>
<!-- GAE -->
<h3 class="warning"><?php _e('系统将为您自动匹配 %s 环境的安装选项', 'GAE'); ?></h3>
<?php if (0 === strpos($adapter, 'Pdo_')): ?>
<li>
<label class="typecho-label" for="dbHost"><?php _e('数据库实例名'); ?></label>
<input type="text" class="text" name="dbHost" id="dbHost" value="<?php _v('dbHost'); ?>"/>
<p class="description"><?php _e('请填入您在Cloud SQL面板中创建的数据库实例名称, 示例: %s', '<em class="warning">/cloudsql/typecho-gae:typecho</em>'); ?></p>
</li>
<?php else: ?>
<li>
<label class="typecho-label" for="dbHost"><?php _e('数据库实例名'); ?></label>
<input type="text" class="text" name="dbHost" id="dbHost" value="<?php _v('dbHost'); ?>"/>
<p class="description"><?php _e('请填入您在Cloud SQL面板中创建的数据库实例名称, 示例: %s', '<em class="warning">:/cloudsql/typecho-gae:typecho</em>'); ?></p>
</li>
<?php endif; ?>
<li>
<label class="typecho-label" for="dbUser"><?php _e('数据库用户名'); ?></label>
<input type="text" class="text" name="dbUser" id="dbUser" value="<?php _v('dbUser'); ?>" />
</li>
<li>
<label class="typecho-label" for="dbPassword"><?php _e('数据库密码'); ?></label>
<input type="password" class="text" name="dbPassword" id="dbPassword" value="<?php _v('dbPassword'); ?>" />
</li>
<li>
<label class="typecho-label" for="dbDatabase"><?php _e('数据库名'); ?></label>
<input type="text" class="text" name="dbDatabase" id="dbDatabase" value="<?php _v('dbDatabase', 'typecho'); ?>" />
<p class="description"><?php _e('请填入您在Cloud SQL的实例中创建的数据库名称'); ?></p>
</li>
<?php if (0 === strpos($adapter, 'Pdo_')): ?>
<input type="hidden" name="dbDsn" value="mysql:dbname={database};unix_socket={host};charset={charset}" />
<input type="hidden" name="config" value="array (
'dsn' => '{dsn}',
'user' => '{user}',
'password' => '{password}'
)" />
<?php else: ?>
<input type="hidden" name="config" value="array (
'host' => '{host}',
'database' => '{database}',
'user' => '{user}',
'password' => '{password}'
)" />
<?php endif; ?>
<?php else: ?>
<ul class="typecho-option">
<li>
<label class="typecho-label" for="dbHost"><?php _e('数据库地址'); ?></label>
<input type="text" class="text" name="dbHost" id="dbHost" value="<?php _v('dbHost', 'localhost'); ?>"/>
<input type="text" class="text" name="dbHost" id="dbHost" value="localhost"/>
<p class="description"><?php _e('您可能会使用 "%s"', 'localhost'); ?></p>
</li>
<li>
<label class="typecho-label" for="dbPort"><?php _e('数据库端口'); ?></label>
<input type="text" class="text" name="dbPort" id="dbPort" value="<?php _v('dbPort', '3306'); ?>"/>
<p class="description"><?php _e('如果您不知道此选项的意义, 请保留默认设置'); ?></p>
</li>
</ul>
<ul class="typecho-option">
<li>
<label class="typecho-label" for="dbUser"><?php _e('数据库用户名'); ?></label>
<input type="text" class="text" name="dbUser" id="dbUser" value="<?php _v('dbUser', 'root'); ?>" />
<input type="text" class="text" name="dbUser" id="dbUser" value="" />
<p class="description"><?php _e('您可能会使用 "%s"', 'root'); ?></p>
</li>
</ul>
<ul class="typecho-option">
<li>
<label class="typecho-label" for="dbPassword"><?php _e('数据库密码'); ?></label>
<input type="password" class="text" name="dbPassword" id="dbPassword" value="<?php _v('dbPassword'); ?>" />
<input type="password" class="text" name="dbPassword" id="dbPassword" value="" />
</li>
</ul>
<ul class="typecho-option">
<li>
<label class="typecho-label" for="dbDatabase"><?php _e('数据库名'); ?></label>
<input type="text" class="text" name="dbDatabase" id="dbDatabase" value="<?php _v('dbDatabase', 'typecho'); ?>" />
<input type="text" class="text" name="dbDatabase" id="dbDatabase" value="" />
<p class="description"><?php _e('请您指定数据库名称'); ?></p>
</li>
<?php endif; ?>
<input type="hidden" name="dbCharset" value="<?php _e('utf8'); ?>" />
</ul>
<li>
<label class="typecho-label" for="dbCharset"><?php _e('数据库编码'); ?></label>
<select name="dbCharset" id="dbCharset">
<option value="utf8mb4"<?php if (_r('dbCharset') == 'utf8mb4'): ?> selected<?php endif; ?>>utf8mb4</option>
<option value="utf8"<?php if (_r('dbCharset') == 'utf8'): ?> selected<?php endif; ?>>utf8</option>
</select>
<p class="description"><?php _e('选择 utf8mb4 编码至少需要 MySQL 5.5.3 版本'); ?></p>
</li>
<details>
<summary>
<strong><?php _e('高级选项'); ?></strong>
</summary>
<ul class="typecho-option">
<li>
<label class="typecho-label" for="dbPort"><?php _e('数据库端口'); ?></label>
<input type="text" class="text" name="dbPort" id="dbPort" value="3306"/>
<p class="description"><?php _e('如果您不知道此选项的意义, 请保留默认设置'); ?></p>
</li>
</ul>
<li>
<label class="typecho-label" for="dbEngine"><?php _e('数据库引擎'); ?></label>
<select name="dbEngine" id="dbEngine">
<option value="InnoDB"<?php if (_r('dbEngine') == 'InnoDB'): ?> selected<?php endif; ?>>InnoDB</option>
<option value="MyISAM"<?php if (_r('dbEngine') == 'MyISAM'): ?> selected<?php endif; ?>>MyISAM</option>
</select>
</li>
<ul class="typecho-option">
<li>
<label class="typecho-label" for="dbCharset"><?php _e('数据库编码'); ?></label>
<select name="dbCharset" id="dbCharset">
<option value="utf8mb4">utf8mb4</option>
<option value="utf8">utf8</option>
</select>
<p class="description"><?php _e('选择 utf8mb4 编码至少需要 MySQL 5.5.3 版本'); ?></p>
</li>
</ul>
<ul class="typecho-option">
<li>
<label class="typecho-label" for="dbEngine"><?php _e('数据库引擎'); ?></label>
<select name="dbEngine" id="dbEngine">
<option value="InnoDB">InnoDB</option>
<option value="MyISAM">MyISAM</option>
</select>
</li>
</ul>
</details>

View File

@ -1,26 +1,37 @@
<?php if(!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<li>
<label class="typecho-label" for="dbHost"><?php _e('数据库地址'); ?></label>
<input type="text" class="text" name="dbHost" id="dbHost" value="<?php _v('dbHost', 'localhost'); ?>"/>
<p class="description"><?php _e('您可能会使用 "%s"', 'localhost'); ?></p>
</li>
<li>
<label class="typecho-label" for="dbPort"><?php _e('数据库端口'); ?></label>
<input type="text" class="text" name="dbPort" id="dbPort" value="<?php _v('dbPort', '5432'); ?>"/>
<p class="description"><?php _e('如果您不知道此选项的意义, 请保留默认设置'); ?></p>
</li>
<li>
<label class="typecho-label" for="dbUser"><?php _e('数据库用户名'); ?></label>
<input type="text" class="text" name="dbUser" id="dbUser" value="<?php _v('dbUser', 'postgres'); ?>" />
<p class="description"><?php _e('您可能会使用 "%s"', 'postgres'); ?></p>
</li>
<li>
<label class="typecho-label" for="dbPassword"><?php _e('数据库密码'); ?></label>
<input type="password" class="text" name="dbPassword" id="dbPassword" value="<?php _v('dbPassword'); ?>" />
</li>
<li>
<label class="typecho-label" for="dbDatabase"><?php _e('数据库名'); ?></label>
<input type="text" class="text" name="dbDatabase" id="dbDatabase" value="<?php _v('dbDatabase', 'typecho'); ?>" />
<p class="description"><?php _e('请您指定数据库名称'); ?></p>
</li>
<input type="hidden" name="dbCharset" value="<?php _e('utf8'); ?>" />
<ul class="typecho-option">
<li>
<label class="typecho-label" for="dbHost"><?php _e('数据库地址'); ?></label>
<input type="text" class="text" name="dbHost" id="dbHost" value="localhost"/>
<p class="description"><?php _e('您可能会使用 "%s"', 'localhost'); ?></p>
</li>
</ul>
<ul class="typecho-option">
<li>
<label class="typecho-label" for="dbPort"><?php _e('数据库端口'); ?></label>
<input type="text" class="text" name="dbPort" id="dbPort" value="5432"/>
<p class="description"><?php _e('如果您不知道此选项的意义, 请保留默认设置'); ?></p>
</li>
</ul>
<ul class="typecho-option">
<li>
<label class="typecho-label" for="dbUser"><?php _e('数据库用户名'); ?></label>
<input type="text" class="text" name="dbUser" id="dbUser" value="postgres" />
<p class="description"><?php _e('您可能会使用 "%s"', 'postgres'); ?></p>
</li>
</ul>
<ul class="typecho-option">
<li>
<label class="typecho-label" for="dbPassword"><?php _e('数据库密码'); ?></label>
<input type="password" class="text" name="dbPassword" id="dbPassword" value="" />
</li
</ul>
<ul class="typecho-option">
<li>
<label class="typecho-label" for="dbDatabase"><?php _e('数据库名'); ?></label>
<input type="text" class="text" name="dbDatabase" id="dbDatabase" value="" />
<p class="description"><?php _e('请您指定数据库名称'); ?></p>
</li
</ul>
<input type="hidden" name="dbCharset" value="utf8" />

View File

@ -1,7 +1,9 @@
<?php if(!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<?php $defaultDir = dirname($_SERVER['SCRIPT_FILENAME']) . '/usr/' . uniqid() . '.db'; ?>
<li>
<label class="typecho-label" for="dbFile"><?php _e('数据库文件路径'); ?></label>
<input type="text" class="text" name="dbFile" id="dbFile" value="<?php _v('dbFile', $defaultDir); ?>"/>
<p class="description"><?php _e('"%s" 是我们为您自动生成的地址', $defaultDir); ?></p>
</li>
<?php $defaultDir = __TYPECHO_ROOT_DIR__ . '/usr/' . uniqid() . '.db'; ?>
<ul class="typecho-option">
<li>
<label class="typecho-label" for="dbFile"><?php _e('数据库文件路径'); ?></label>
<input type="text" class="text" name="dbFile" id="dbFile" value="<?php echo $defaultDir; ?>"/>
<p class="description"><?php _e('"%s" 是我们为您自动生成的地址', $defaultDir); ?></p>
</li>
</ul>

2337
tools/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,9 @@
"version": "1.0.0",
"description": "Typecho build tools",
"main": "build.js",
"engines": {
"node": "16.x"
},
"scripts": {
"build_js": "node build.js js",
"build_css": "node build.js css"

View File

@ -1,6 +1,6 @@
<?php if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<!DOCTYPE HTML>
<html class="no-js">
<html>
<head>
<meta charset="<?php $this->options->charset(); ?>">
<meta http-equiv="X-UA-Compatible" content="IE=edge">

View File

@ -437,22 +437,6 @@ EOF;
return false;
}
/**
* 检测是否在app engine上运行屏蔽某些功能
*
* @static
* @access public
* @return boolean
*/
public static function isAppEngine()
{
return !empty($_SERVER['HTTP_APPNAME']) // SAE
|| !!getenv('HTTP_BAE_ENV_APPID') // BAE
|| !!getenv('HTTP_BAE_LOGID') // BAE 3.0
|| (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'],'Google App Engine') !== false) // GAE
;
}
/**
* 抽取多维数组的某个元素,组成一个新数组,使这个数组变成一个扁平数组
* 使用方法:
@ -981,7 +965,11 @@ EOF;
public static function url($path, $prefix)
{
$path = (0 === strpos($path, './')) ? substr($path, 2) : $path;
return rtrim($prefix, '/') . '/' . str_replace('//', '/', ltrim($path, '/'));
return rtrim(
rtrim($prefix, '/') . '/'
. str_replace('//', '/', ltrim($path, '/')),
'/'
);
}
/**

View File

@ -25,7 +25,7 @@ class Typecho_Config implements Iterator
* @access private
* @var array
*/
private $_currentConfig = array();
private $_currentConfig = [];
/**
* 实例化一个当前配置
@ -33,7 +33,7 @@ class Typecho_Config implements Iterator
* @access public
* @param mixed $config 配置列表
*/
public function __construct($config = array())
public function __construct($config = [])
{
/** 初始化参数 */
$this->setDefault($config);
@ -43,10 +43,12 @@ class Typecho_Config implements Iterator
* 工厂模式实例化一个当前配置
*
* @access public
* @param array $config 配置列表
*
* @param array|string $config 配置列表
*
* @return Typecho_Config
*/
public static function factory($config = array())
public static function factory($config = []): Typecho_Config
{
return new Typecho_Config($config);
}
@ -55,11 +57,13 @@ class Typecho_Config implements Iterator
* 设置默认的配置
*
* @access public
*
* @param mixed $config 配置信息
* @param boolean $replace 是否替换已经存在的信息
*
* @return void
*/
public function setDefault($config, $replace = false)
public function setDefault($config, bool $replace = false)
{
if (empty($config)) {
return;
@ -130,7 +134,7 @@ class Typecho_Config implements Iterator
* @access public
* @return boolean
*/
public function valid()
public function valid(): bool
{
return false !== $this->current();
}
@ -142,9 +146,9 @@ class Typecho_Config implements Iterator
* @param string $name 配置名称
* @return mixed
*/
public function __get($name)
public function __get(string $name)
{
return isset($this->_currentConfig[$name]) ? $this->_currentConfig[$name] : NULL;
return $this->_currentConfig[$name] ?? null;
}
/**
@ -155,7 +159,7 @@ class Typecho_Config implements Iterator
* @param mixed $value 配置值
* @return void
*/
public function __set($name, $value)
public function __set(string $name, $value)
{
$this->_currentConfig[$name] = $value;
}
@ -165,10 +169,10 @@ class Typecho_Config implements Iterator
*
* @access public
* @param string $name 配置名称
* @param array $args 参数
* @param array|null $args 参数
* @return void
*/
public function __call($name, $args)
public function __call(string $name, ?array $args)
{
echo $this->_currentConfig[$name];
}
@ -180,7 +184,7 @@ class Typecho_Config implements Iterator
* @param string $name 配置名称
* @return boolean
*/
public function __isSet($name)
public function __isSet(string $name): bool
{
return isset($this->_currentConfig[$name]);
}
@ -191,8 +195,16 @@ class Typecho_Config implements Iterator
* @access public
* @return string
*/
public function __toString()
public function __toString(): string
{
return serialize($this->_currentConfig);
}
/**
* @return array
*/
public function toArray(): array
{
return $this->_currentConfig;
}
}

View File

@ -61,8 +61,7 @@ class Typecho_Db
/**
* 默认配置
*
* @access private
* @var Typecho_Config
* @var array
*/
private $_config;
@ -109,9 +108,10 @@ class Typecho_Db
*
* @param mixed $adapterName 适配器名称
* @param string $prefix 前缀
*
* @throws Typecho_Db_Exception
*/
public function __construct($adapterName, $prefix = 'typecho_')
public function __construct($adapterName, string $prefix = 'typecho_')
{
/** 获取适配器名称 */
$this->_adapterName = $adapterName;
@ -119,16 +119,20 @@ class Typecho_Db
/** 数据库适配器 */
$adapterName = 'Typecho_Db_Adapter_' . $adapterName;
if (!call_user_func(array($adapterName, 'isAvailable'))) {
if (!call_user_func([$adapterName, 'isAvailable'])) {
throw new Typecho_Db_Exception("Adapter {$adapterName} is not available");
}
$this->_prefix = $prefix;
/** 初始化内部变量 */
$this->_pool = array();
$this->_connectedPool = array();
$this->_config = array();
$this->_pool = [];
$this->_connectedPool = [];
$this->_config = [
self::READ => [],
self::WRITE => []
];
//实例化适配器对象
$this->_adapter = new $adapterName();
@ -140,7 +144,7 @@ class Typecho_Db
* @access public
* @return string
*/
public function getAdapterName()
public function getAdapterName(): string
{
return $this->_adapterName;
}
@ -151,54 +155,69 @@ class Typecho_Db
* @access public
* @return string
*/
public function getPrefix()
public function getPrefix(): string
{
return $this->_prefix;
}
/**
* getConfig
*
* @access public
* @return array
* @param Typecho_Config $config
* @param int $op
*/
public function getConfig()
public function addConfig(Typecho_Config $config, int $op)
{
return $this->_config;
if ($op & self::READ) {
$this->_config[self::READ][] = $config;
}
if ($op & self::WRITE) {
$this->_config[self::WRITE][] = $config;
}
}
/**
* getConfig
*
* @param int $op
*
* @return Typecho_Config
* @throws Typecho_Db_Exception
*/
public function getConfig(int $op): Typecho_Config
{
if (empty($this->_config[$op])) {
/** Typecho_Db_Exception */
throw new Typecho_Db_Exception('Missing Database Connection');
}
$key = array_rand($this->_config[$op]);
return $this->_config[$op][$key];
}
/**
* 重置连接池
*
*
* @return void
*/
public function flushPool()
{
$this->_connectedPool = array();
$this->_connectedPool = [];
}
/**
* 选择数据库
*
* @param int $op
* @return Typecho_Db_Adapter
*
* @param int $op
*
* @return mixed
* @throws Typecho_Db_Exception
*/
public function selectDb($op)
public function selectDb(int $op)
{
if (!isset($this->_connectedPool[$op])) {
if (empty($this->_pool[$op])) {
/** Typecho_Db_Exception */
throw new Typecho_Db_Exception('Missing Database Connection');
}
//获取相应读或写服务器连接池中的一个
$selectConnection = rand(0, count($this->_pool[$op]) - 1);
//获取随机获得的连接池配置
$selectConnectionConfig = $this->_config[$this->_pool[$op][$selectConnection]];
$selectConnectionConfig = $this->getConfig($op);
$selectConnectionHandle = $this->_adapter->connect($selectConnectionConfig);
$this->_connectedPool[$op] = &$selectConnectionHandle;
$this->_connectedPool[$op] = $selectConnectionHandle;
}
return $this->_connectedPool[$op];
@ -209,7 +228,7 @@ class Typecho_Db
*
* @return Typecho_Db_Query
*/
public function sql()
public function sql(): Typecho_Db_Query
{
return new Typecho_Db_Query($this->_adapter, $this->_prefix);
}
@ -218,35 +237,25 @@ class Typecho_Db
* 为多数据库提供支持
*
* @access public
* @param Typecho_Db $db 数据库实例
* @param array $config 数据库实例
* @param integer $op 数据库操作
* @return void
*/
public function addServer($config, $op)
public function addServer(array $config, int $op)
{
$this->_config[] = Typecho_Config::factory($config);
$key = count($this->_config) - 1;
/** 将连接放入池中 */
switch ($op) {
case self::READ:
case self::WRITE:
$this->_pool[$op][] = $key;
break;
default:
$this->_pool[self::READ][] = $key;
$this->_pool[self::WRITE][] = $key;
break;
}
$this->addConfig(Typecho_Config::factory($config), $op);
$this->flushPool();
}
/**
* 获取版本
*
* @param int $op
*
* @param int $op
*
* @return string
* @throws Typecho_Db_Exception
*/
public function getVersion($op = self::READ)
public function getVersion(int $op = self::READ): string
{
return $this->_adapter->getVersion($this->selectDb($op));
}
@ -270,7 +279,7 @@ class Typecho_Db
* @return Typecho_Db
* @throws Typecho_Db_Exception
*/
public static function get()
public static function get(): Typecho_Db
{
if (empty(self::$_instance)) {
/** Typecho_Db_Exception */
@ -283,24 +292,31 @@ class Typecho_Db
/**
* 选择查询字段
*
* @access public
* @param mixed $field 查询字段
* @param ...$ags
*
* @return Typecho_Db_Query
* @throws Typecho_Db_Exception
*/
public function select()
public function select(...$ags): Typecho_Db_Query
{
$this->selectDb(self::READ);
$args = func_get_args();
return call_user_func_array(array($this->sql(), 'select'), $args ? $args : array('*'));
return call_user_func_array([$this->sql(), 'select'], $args ?: ['*']);
}
/**
* 更新记录操作(UPDATE)
*
* @param string $table 需要更新记录的表
*
* @return Typecho_Db_Query
* @throws Typecho_Db_Exception
*/
public function update($table)
public function update(string $table): Typecho_Db_Query
{
$this->selectDb(self::WRITE);
return $this->sql()->update($table);
}
@ -308,10 +324,14 @@ class Typecho_Db
* 删除记录操作(DELETE)
*
* @param string $table 需要删除记录的表
*
* @return Typecho_Db_Query
* @throws Typecho_Db_Exception
*/
public function delete($table)
public function delete(string $table): Typecho_Db_Query
{
$this->selectDb(self::WRITE);
return $this->sql()->delete($table);
}
@ -319,10 +339,14 @@ class Typecho_Db
* 插入记录操作(INSERT)
*
* @param string $table 需要插入记录的表
*
* @return Typecho_Db_Query
* @throws Typecho_Db_Exception
*/
public function insert($table)
public function insert(string $table): Typecho_Db_Query
{
$this->selectDb(self::WRITE);
return $this->sql()->insert($table);
}
@ -342,19 +366,20 @@ class Typecho_Db
* @param mixed $query 查询语句或者查询对象
* @param int $op 数据库读写状态
* @param string $action 操作动作
*
* @return mixed
* @throws Typecho_Db_Exception
*/
public function query($query, $op = self::READ, $action = self::SELECT)
public function query($query, int $op = self::READ, string $action = self::SELECT)
{
$table = NULL;
$table = null;
/** 在适配器中执行查询 */
if ($query instanceof Typecho_Db_Query) {
$action = $query->getAttribute('action');
$table = $query->getAttribute('table');
$op = (self::UPDATE == $action || self::DELETE == $action
|| self::INSERT == $action) ? self::WRITE : self::READ;
|| self::INSERT == $action) ? self::WRITE : self::READ;
} else if (!is_string($query)) {
/** 如果query不是对象也不是字符串,那么将其判断为查询资源句柄,直接返回 */
return $query;
@ -389,24 +414,26 @@ class Typecho_Db
* 一次取出所有行
*
* @param mixed $query 查询对象
* @param array $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
* @param array|null $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
*
* @return array
* @throws Typecho_Db_Exception
*/
public function fetchAll($query, array $filter = NULL)
public function fetchAll($query, ?array $filter = null): array
{
//执行查询
$resource = $this->query($query, self::READ);
$result = array();
$result = [];
/** 取出过滤器 */
if (!empty($filter)) {
list($object, $method) = $filter;
[$object, $method] = $filter;
}
//取出每一行
while ($rows = $this->_adapter->fetch($resource)) {
//判断是否有过滤器
$result[] = $filter ? call_user_func(array(&$object, $method), $rows) : $rows;
$result[] = $filter ? call_user_func([&$object, $method], $rows) : $rows;
}
return $result;
@ -416,41 +443,45 @@ class Typecho_Db
* 一次取出一行
*
* @param mixed $query 查询对象
* @param array $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
* @param array|null $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
*
* @return mixed
* @throws Typecho_Db_Exception
*/
public function fetchRow($query, array $filter = NULL)
public function fetchRow($query, ?array $filter = null)
{
$resource = $this->query($query, self::READ);
/** 取出过滤器 */
if ($filter) {
list($object, $method) = $filter;
[$object, $method] = $filter;
}
return ($rows = $this->_adapter->fetch($resource)) ?
($filter ? $object->$method($rows) : $rows) :
array();
($filter ? $object->$method($rows) : $rows) :
[];
}
/**
* 一次取出一个对象
*
* @param mixed $query 查询对象
* @param array $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
* @param array|null $filter 行过滤器函数,将查询的每一行作为第一个参数传入指定的过滤器中
*
* @return mixed
* @throws Typecho_Db_Exception
*/
public function fetchObject($query, array $filter = NULL)
public function fetchObject($query, ?array $filter = null)
{
$resource = $this->query($query, self::READ);
/** 取出过滤器 */
if ($filter) {
list($object, $method) = $filter;
[$object, $method] = $filter;
}
return ($rows = $this->_adapter->fetchObject($resource)) ?
($filter ? $object->$method($rows) : $rows) :
new stdClass();
($filter ? $object->$method($rows) : $rows) :
new stdClass();
}
}

View File

@ -27,7 +27,7 @@ interface Typecho_Db_Adapter
* 数据库连接函数
*
* @param Typecho_Config $config 数据库配置
* @return resource
* @return mixed
*/
public function connect(Typecho_Config $config);

View File

@ -39,7 +39,7 @@ class Typecho_Db_Adapter_Mysql implements Typecho_Db_Adapter
*
* @param Typecho_Config $config 数据库配置
* @throws Typecho_Db_Exception
* @return resource
* @return mixed
*/
public function connect(Typecho_Config $config)
{

View File

@ -19,7 +19,7 @@ class Typecho_Db_Adapter_Mysqli implements Typecho_Db_Adapter
* 数据库连接字符串标示
*
* @access private
* @var resource
* @var mysqli
*/
private $_dbLink;
@ -39,12 +39,18 @@ class Typecho_Db_Adapter_Mysqli implements Typecho_Db_Adapter
*
* @param Typecho_Config $config 数据库配置
* @throws Typecho_Db_Exception
* @return resource
* @return mixed
*/
public function connect(Typecho_Config $config)
{
if ($this->_dbLink = @new MySQLi($config->host, $config->user, $config->password, $config->database, (empty($config->port) ? '' : $config->port))) {
if ($this->_dbLink = @mysqli_connect(
$config->host,
$config->user,
$config->password,
$config->database,
(empty($config->port) ? null : $config->port))
) {
if ($config->charset) {
$this->_dbLink->query("SET NAMES '{$config->charset}'");
}

View File

@ -22,7 +22,7 @@ class Typecho_Request
* @access private
* @var array
*/
private $_params = array();
private $_params = [];
/**
* 路径信息
@ -30,7 +30,7 @@ class Typecho_Request
* @access private
* @var string
*/
private $_pathInfo = NULL;
private $_pathInfo = null;
/**
* 服务端参数
@ -38,31 +38,31 @@ class Typecho_Request
* @access private
* @var array
*/
private $_server = array();
private $_server = [];
/**
* _requestUri
*
* _requestUri
*
* @var string
* @access private
*/
private $_requestUri = NULL;
private $_requestUri = null;
/**
* _requestRoot
*
* _requestRoot
*
* @var mixed
* @access private
*/
private $_requestRoot = NULL;
private $_requestRoot = null;
/**
* 获取baseurl
*
*
* @var string
* @access private
*/
private $_baseUrl = NULL;
private $_baseUrl = null;
/**
* 客户端ip地址
@ -70,7 +70,7 @@ class Typecho_Request
* @access private
* @var string
*/
private $_ip = NULL;
private $_ip = null;
/**
* 客户端字符串
@ -78,7 +78,7 @@ class Typecho_Request
* @access private
* @var string
*/
private $_agent = NULL;
private $_agent = null;
/**
* 来源页
@ -86,7 +86,7 @@ class Typecho_Request
* @access private
* @var string
*/
private $_referer = NULL;
private $_referer = null;
/**
* 单例句柄
@ -94,7 +94,7 @@ class Typecho_Request
* @access private
* @var Typecho_Request
*/
private static $_instance = NULL;
private static $_instance;
/**
* 全部的http数据
@ -103,13 +103,13 @@ class Typecho_Request
*/
private static $_httpParams = false;
/**
* 域名前缀
*
* @var string
*/
private static $_urlPrefix = NULL;
private $_urlPrefix = null;
/**
* 当前过滤器
@ -117,7 +117,7 @@ class Typecho_Request
* @access private
* @var array
*/
private $_filter = array();
private $_filter = [];
/**
* 支持的过滤器列表
@ -125,14 +125,14 @@ class Typecho_Request
* @access private
* @var string
*/
private static $_supportFilters = array(
'int' => 'intval',
'integer' => 'intval',
'search' => array('Typecho_Common', 'filterSearchQuery'),
'xss' => array('Typecho_Common', 'removeXSS'),
'url' => array('Typecho_Common', 'safeUrl'),
'slug' => array('Typecho_Common', 'slugName')
);
private static $_supportFilters = [
'int' => 'intval',
'integer' => 'intval',
'search' => ['Typecho_Common', 'filterSearchQuery'],
'xss' => ['Typecho_Common', 'removeXSS'],
'url' => ['Typecho_Common', 'safeUrl'],
'slug' => ['Typecho_Common', 'slugName']
];
/**
* 获取单例句柄
@ -140,9 +140,9 @@ class Typecho_Request
* @access public
* @return Typecho_Request
*/
public static function getInstance()
public static function getInstance(): Typecho_Request
{
if (NULL === self::$_instance) {
if (!isset(self::$_instance)) {
self::$_instance = new Typecho_Request();
}
@ -153,7 +153,9 @@ class Typecho_Request
* 应用过滤器
*
* @access private
*
* @param mixed $value
*
* @return mixed
*/
private function _applyFilter($value)
@ -161,10 +163,10 @@ class Typecho_Request
if ($this->_filter) {
foreach ($this->_filter as $filter) {
$value = is_array($value) ? array_map($filter, $value) :
call_user_func($filter, $value);
call_user_func($filter, $value);
}
$this->_filter = array();
$this->_filter = [];
}
return $value;
@ -174,13 +176,14 @@ class Typecho_Request
* 检查ip地址是否合法
*
* @param string $ip ip地址
*
* @return boolean
*/
private function _checkIp($ip)
private function _checkIp(string $ip): bool
{
if (__TYPECHO_FILTER_SUPPORTED__) {
return false !== (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)
|| filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
|| filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
}
return preg_match("/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/", $ip)
@ -191,12 +194,13 @@ class Typecho_Request
* 检查ua是否合法
*
* @param string $agent ua字符串
*
* @return boolean
*/
private function _checkAgent($agent)
private function _checkAgent(string $agent): bool
{
return preg_match("/^[_a-z0-9- ,:;=#@\.\(\)\/\+\*\?]+$/i", $agent);
}
}
/**
* 初始化变量
@ -205,28 +209,28 @@ class Typecho_Request
{
if (false === self::$_httpParams) {
self::$_httpParams = array_filter(array_merge($_POST, $_GET),
array('Typecho_Common', 'checkStrEncoding'));
['Typecho_Common', 'checkStrEncoding']);
}
}
/**
* 获取url前缀
*
* 获取url前缀
*
* @access public
* @return string
*/
public static function getUrlPrefix()
public function getUrlPrefix(): string
{
if (empty(self::$_urlPrefix)) {
if (empty($this->_urlPrefix)) {
if (defined('__TYPECHO_URL_PREFIX__')) {
self::$_urlPrefix = __TYPECHO_URL_PREFIX__;
$this->_urlPrefix = __TYPECHO_URL_PREFIX__;
} else if (!defined('__TYPECHO_CLI__')) {
self::$_urlPrefix = (self::isSecure() ? 'https' : 'http') . '://'
. (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME']);
$this->_urlPrefix = ($this->isSecure() ? 'https' : 'http') . '://'
. ($_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME']);
}
}
return self::$_urlPrefix;
return $this->_urlPrefix;
}
/**
@ -235,7 +239,7 @@ class Typecho_Request
* @access public
* @return boolean
*/
public static function isSecure()
public function isSecure(): bool
{
return (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && !strcasecmp('https', $_SERVER['HTTP_X_FORWARDED_PROTO']))
|| (!empty($_SERVER['HTTP_X_FORWARDED_PORT']) && 443 == $_SERVER['HTTP_X_FORWARDED_PORT'])
@ -250,13 +254,13 @@ class Typecho_Request
* @access public
* @return Typecho_Request
*/
public function filter()
public function filter(): Typecho_Request
{
$filters = func_get_args();
foreach ($filters as $filter) {
$this->_filter[] = is_string($filter) && isset(self::$_supportFilters[$filter])
? self::$_supportFilters[$filter] : $filter;
? self::$_supportFilters[$filter] : $filter;
}
return $this;
@ -266,10 +270,12 @@ class Typecho_Request
* 获取实际传递参数(magic)
*
* @access public
*
* @param string $key 指定参数
*
* @return mixed
*/
public function __get($key)
public function __get(string $key)
{
return $this->get($key);
}
@ -278,24 +284,28 @@ class Typecho_Request
* 判断参数是否存在
*
* @access public
*
* @param string $key 指定参数
*
* @return boolean
*/
public function __isset($key)
public function __isset(string $key)
{
return isset(self::$_httpParams[$key])
|| isset($this->_params[$key]);
|| isset($this->_params[$key]);
}
/**
* 获取实际传递参数
*
* @access public
*
* @param string $key 指定参数
* @param mixed $default 默认参数 (default: NULL)
*
* @return mixed
*/
public function get($key, $default = NULL)
public function get(string $key, $default = null)
{
switch (true) {
case isset($this->_params[$key]):
@ -317,15 +327,15 @@ class Typecho_Request
* 获取一个数组
*
* @param $key
*
* @return array
*/
public function getArray($key)
public function getArray($key): array
{
$result = isset($this->_params[$key]) ? $this->_params[$key] :
(isset(self::$_httpParams[$key]) ? self::$_httpParams[$key] : array());
$result = $this->_params[$key] ?? (self::$_httpParams[$key] ?? []);
$result = is_array($result) ? $result
: (strlen($result) > 0 ? array($result) : array());
: (strlen($result) > 0 ? [$result] : []);
return $this->_applyFilter($result);
}
@ -333,12 +343,14 @@ class Typecho_Request
* 从参数列表指定的值中获取http传递参数
*
* @access public
*
* @param mixed $params 指定的参数
*
* @return array
*/
public function from($params)
public function from($params): array
{
$result = array();
$result = [];
$args = is_array($params) ? $params : func_get_args();
foreach ($args as $arg) {
@ -352,11 +364,13 @@ class Typecho_Request
* 设置http传递参数
*
* @access public
*
* @param string $name 指定的参数
* @param mixed $value 参数值
*
* @return void
*/
public function setParam($name, $value)
public function setParam(string $name, $value)
{
if (Typecho_Common::checkStrEncoding($value)) {
$this->_params[$name] = $value;
@ -367,7 +381,9 @@ class Typecho_Request
* 设置多个参数
*
* @access public
*
* @param mixed $params 参数列表
*
* @return void
*/
public function setParams($params)
@ -379,20 +395,20 @@ class Typecho_Request
}
$this->_params = array_merge($this->_params,
array_filter($params, array('Typecho_Common', 'checkStrEncoding')));
array_filter($params, ['Typecho_Common', 'checkStrEncoding']));
}
/**
* getRequestRoot
*
* getRequestRoot
*
* @access public
* @return string
*/
public function getRequestRoot()
public function getRequestRoot(): string
{
if (NULL === $this->_requestRoot) {
$root = rtrim(self::getUrlPrefix() . $this->getBaseUrl(), '/') . '/';
if (null === $this->_requestRoot) {
$root = rtrim($this->getUrlPrefix() . $this->getBaseUrl(), '/') . '/';
$pos = strrpos($root, '.php/');
if ($pos) {
$root = dirname(substr($root, 0, $pos));
@ -406,22 +422,22 @@ class Typecho_Request
/**
* 获取当前请求url
*
*
* @access public
* @return string
*/
public function getRequestUrl()
public function getRequestUrl(): string
{
return self::getUrlPrefix() . $this->getRequestUri();
return $this->getUrlPrefix() . $this->getRequestUri();
}
/**
* 获取请求地址
*
*
* @access public
* @return string
*/
public function getRequestUri()
public function getRequestUri(): ?string
{
if (!empty($this->_requestUri)) {
return $this->_requestUri;
@ -438,16 +454,16 @@ class Typecho_Request
&& $_SERVER['IIS_WasUrlRewritten'] == '1'
&& isset($_SERVER['UNENCODED_URL'])
&& $_SERVER['UNENCODED_URL'] != ''
) {
) {
$requestUri = $_SERVER['UNENCODED_URL'];
} elseif (isset($_SERVER['REQUEST_URI'])) {
$requestUri = $_SERVER['REQUEST_URI'];
$parts = @parse_url($requestUri);
$parts = @parse_url($requestUri);
if (isset($_SERVER['HTTP_HOST']) && strstr($requestUri, $_SERVER['HTTP_HOST'])) {
if (false !== $parts) {
$requestUri = (empty($parts['path']) ? '' : $parts['path'])
. ((empty($parts['query'])) ? '' : '?' . $parts['query']);
$requestUri = (empty($parts['path']) ? '' : $parts['path'])
. ((empty($parts['query'])) ? '' : '?' . $parts['query']);
}
} elseif (!empty($_SERVER['QUERY_STRING']) && empty($parts['query'])) {
// fix query missing
@ -464,14 +480,14 @@ class Typecho_Request
}
/**
* getBaseUrl
*
* getBaseUrl
*
* @access public
* @return string
*/
public function getBaseUrl()
public function getBaseUrl(): ?string
{
if (NULL !== $this->_baseUrl) {
if (null !== $this->_baseUrl) {
return $this->_baseUrl;
}
@ -487,22 +503,22 @@ class Typecho_Request
} else {
// Backtrack up the script_filename to find the portion matching
// php_self
$path = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : '';
$file = isset($_SERVER['SCRIPT_FILENAME']) ? $_SERVER['SCRIPT_FILENAME'] : '';
$segs = explode('/', trim($file, '/'));
$segs = array_reverse($segs);
$index = 0;
$last = count($segs);
$path = $_SERVER['PHP_SELF'] ?? '';
$file = $_SERVER['SCRIPT_FILENAME'] ?? '';
$segs = explode('/', trim($file, '/'));
$segs = array_reverse($segs);
$index = 0;
$last = count($segs);
$baseUrl = '';
do {
$seg = $segs[$index];
$seg = $segs[$index];
$baseUrl = '/' . $seg . $baseUrl;
++$index;
} while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos));
}
// Does the baseUrl have anything in common with the request_uri?
$finalBaseUrl = NULL;
$finalBaseUrl = null;
$requestUri = $this->getRequestUri();
if (0 === strpos($requestUri, $baseUrl)) {
@ -515,25 +531,26 @@ class Typecho_Request
// no match whatsoever; set it blank
$finalBaseUrl = '';
} else if ((strlen($requestUri) >= strlen($baseUrl))
&& ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0)))
{
&& ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0))) {
// If using mod_rewrite or ISAPI_Rewrite strip the script filename
// out of baseUrl. $pos !== 0 makes sure it is not matching a value
// from PATH_INFO or QUERY_STRING
$baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
}
return ($this->_baseUrl = (NULL === $finalBaseUrl) ? rtrim($baseUrl, '/') : $finalBaseUrl);
return ($this->_baseUrl = (null === $finalBaseUrl) ? rtrim($baseUrl, '/') : $finalBaseUrl);
}
/**
* 根据当前uri构造指定参数的uri
*
* @access public
*
* @param mixed $parameter 指定的参数
*
* @return string
*/
public function makeUriByRequest($parameter = NULL)
public function makeUriByRequest($parameter = null): string
{
/** 初始化地址 */
$requestUri = $this->getRequestUrl();
@ -563,19 +580,21 @@ class Typecho_Request
* 获取当前pathinfo
*
* @access public
* @param string $inputEncoding 输入编码
* @param string $outputEncoding 输出编码
*
* @param string|null $inputEncoding 输入编码
* @param string|null $outputEncoding 输出编码
*
* @return string
*/
public function getPathInfo($inputEncoding = NULL, $outputEncoding = NULL)
public function getPathInfo(string $inputEncoding = null, string $outputEncoding = null): ?string
{
/** 缓存信息 */
if (NULL !== $this->_pathInfo) {
if (null !== $this->_pathInfo) {
return $this->_pathInfo;
}
//参考Zend Framework对pahtinfo的处理, 更好的兼容性
$pathInfo = NULL;
$pathInfo = null;
//处理requestUri
$requestUri = $this->getRequestUri();
@ -586,12 +605,11 @@ class Typecho_Request
$requestUri = substr($requestUri, 0, $pos);
}
if ((NULL !== $finalBaseUrl)
&& (false === ($pathInfo = substr($requestUri, strlen($finalBaseUrl)))))
{
if ((null !== $finalBaseUrl)
&& (false === ($pathInfo = substr($requestUri, strlen($finalBaseUrl))))) {
// If substr() returns false then PATH_INFO is set to an empty string
$pathInfo = '/';
} elseif (NULL === $finalBaseUrl) {
} elseif (null === $finalBaseUrl) {
$pathInfo = $requestUri;
}
@ -599,8 +617,8 @@ class Typecho_Request
//针对iis的utf8编码做强制转换
//参考http://docs.moodle.org/ja/%E5%A4%9A%E8%A8%80%E8%AA%9E%E5%AF%BE%E5%BF%9C%EF%BC%9A%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AE%E8%A8%AD%E5%AE%9A
if (!empty($inputEncoding) && !empty($outputEncoding) &&
(stripos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false
|| stripos($_SERVER['SERVER_SOFTWARE'], 'ExpressionDevServer') !== false)) {
(stripos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false
|| stripos($_SERVER['SERVER_SOFTWARE'], 'ExpressionDevServer') !== false)) {
if (function_exists('mb_convert_encoding')) {
$pathInfo = mb_convert_encoding($pathInfo, $outputEncoding, $inputEncoding);
} else if (function_exists('iconv')) {
@ -615,62 +633,46 @@ class Typecho_Request
return ($this->_pathInfo = '/' . ltrim(urldecode($pathInfo), '/'));
}
/**
* 设置服务端参数
*
* @access public
* @param string $name 参数名称
* @param mixed $value 参数值
* @return void
*/
public function setServer($name, $value = NULL)
{
if (NULL == $value) {
if (isset($_SERVER[$name])) {
$value = $_SERVER[$name];
} else if (isset($_ENV[$name])) {
$value = $_ENV[$name];
}
}
$this->_server[$name] = $value;
}
/**
* 获取环境变量
*
* @access public
*
* @param string $name 获取环境变量名
* @return string
* @param string|null $default
*
* @return string|null
*/
public function getServer($name)
public function getServer(string $name, string $default = null): ?string
{
if (!isset($this->_server[$name])) {
$this->setServer($name);
}
return $this->_server[$name];
return $_SERVER[$name] ?? $default;
}
/**
* 设置ip地址
*
* @access public
* @param string $ip
*
* @param string|null $ip
*/
public function setIp($ip = NULL)
public function setIp(string $ip = null)
{
if (!empty($ip)) {
$this->_ip = $ip;
} else {
switch (true) {
case defined('__TYPECHO_IP_SOURCE__') && NULL !== $this->getServer(__TYPECHO_IP_SOURCE__):
list($this->_ip) = array_map('trim', explode(',', $this->getServer(__TYPECHO_IP_SOURCE__)));
case defined('__TYPECHO_IP_SOURCE__')
&& null !== $this->getServer(__TYPECHO_IP_SOURCE__):
list($this->_ip) = array_map(
'trim',
explode(',',
$this->getServer(__TYPECHO_IP_SOURCE__))
);
break;
case NULL !== $this->getServer('REMOTE_ADDR'):
case null !== $this->getServer('REMOTE_ADDR'):
$this->_ip = $this->getServer('REMOTE_ADDR');
break;
case NULL !== $this->getServer('HTTP_CLIENT_IP'):
case null !== $this->getServer('HTTP_CLIENT_IP'):
$this->_ip = $this->getServer('HTTP_CLIENT_IP');
break;
default:
@ -689,9 +691,9 @@ class Typecho_Request
* @access public
* @return string
*/
public function getIp()
public function getIp(): string
{
if (NULL === $this->_ip) {
if (null === $this->_ip) {
$this->setIp();
}
@ -702,12 +704,14 @@ class Typecho_Request
* 设置客户端
*
* @access public
* @param string $agent 客户端字符串
*
* @param string|null $agent 客户端字符串
*
* @return void
*/
public function setAgent($agent = NULL)
public function setAgent(string $agent = null)
{
$agent = (NULL === $agent) ? $this->getServer('HTTP_USER_AGENT') : $agent;
$agent = (null === $agent) ? $this->getServer('HTTP_USER_AGENT') : $agent;
$this->_agent = self::_checkAgent($agent) ? $agent : '';
}
@ -717,9 +721,9 @@ class Typecho_Request
* @access public
* @return string
*/
public function getAgent()
public function getAgent(): ?string
{
if (NULL === $this->_agent) {
if (null === $this->_agent) {
$this->setAgent();
}
@ -730,23 +734,25 @@ class Typecho_Request
* 设置来源页
*
* @access public
* @param string $referer 客户端字符串
*
* @param string|null $referer 客户端字符串
*
* @return void
*/
public function setReferer($referer = NULL)
public function setReferer(string $referer = null)
{
$this->_referer = (NULL === $referer) ? $this->getServer('HTTP_REFERER') : $referer;
$this->_referer = (null === $referer) ? $this->getServer('HTTP_REFERER') : $referer;
}
/**
* 获取客户端
*
* @access public
* @return string
* @return string|null
*/
public function getReferer()
public function getReferer(): ?string
{
if (NULL === $this->_referer) {
if (null === $this->_referer) {
$this->setReferer();
}
@ -759,7 +765,7 @@ class Typecho_Request
* @access public
* @return boolean
*/
public function isGet()
public function isGet(): bool
{
return 'GET' == $this->getServer('REQUEST_METHOD');
}
@ -770,7 +776,7 @@ class Typecho_Request
* @access public
* @return boolean
*/
public function isPost()
public function isPost(): bool
{
return 'POST' == $this->getServer('REQUEST_METHOD');
}
@ -781,10 +787,10 @@ class Typecho_Request
* @access public
* @return boolean
*/
public function isPut()
public function isPut(): bool
{
return 'PUT' == $this->getServer('REQUEST_METHOD');
}
}
/**
* 判断是否为ajax
@ -792,43 +798,21 @@ class Typecho_Request
* @access public
* @return boolean
*/
public function isAjax()
public function isAjax(): bool
{
return 'XMLHttpRequest' == $this->getServer('HTTP_X_REQUESTED_WITH');
}
/**
* 判断是否为flash
*
* @access public
* @return boolean
*/
public function isFlash()
{
return 'Shockwave Flash' == $this->getServer('USER_AGENT');
}
/**
* isMobile
*
* @static
* @access public
* @return boolean
*/
public function isMobile()
{
$userAgent = $this->getAgent();
return preg_match('/android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i',$userAgent) || preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',substr($userAgent,0,4));
}
/**
* 判断输入是否满足要求
*
* @access public
*
* @param mixed $query 条件
*
* @return boolean
*/
public function is($query)
public function is($query): bool
{
$validated = false;
@ -840,7 +824,7 @@ class Typecho_Request
}
/** 验证串 */
if ($params) {
if (!empty($params)) {
$validated = true;
foreach ($params as $key => $val) {
$validated = empty($val) ? $this->__isset($key) : ($val == $this->get($key));

View File

@ -25,7 +25,7 @@ class Typecho_Response
* @access private
* @var array
*/
private static $_httpCode = array(
private static $_httpCode = [
100 => 'Continue',
101 => 'Switching Protocols',
200 => 'OK',
@ -66,7 +66,7 @@ class Typecho_Response
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported'
);
];
/**
* 字符编码
@ -85,14 +85,14 @@ class Typecho_Response
* @access private
* @var Typecho_Response
*/
private static $_instance = null;
private static $_instance;
/**
* 结束前回调函数
*
* @var array
*/
private static $_callbacks = array();
private static $_callbacks = [];
/**
* 获取单例句柄
@ -100,9 +100,9 @@ class Typecho_Response
* @access public
* @return Typecho_Response
*/
public static function getInstance()
public static function getInstance(): Typecho_Response
{
if (null === self::$_instance) {
if (!isset(self::$_instance)) {
self::$_instance = new Typecho_Response();
}
@ -116,7 +116,7 @@ class Typecho_Response
* @param mixed $message 格式化数据
* @return string
*/
private function _parseXml($message)
private function _parseXml($message): string
{
/** 对于数组型则继续递归 */
if (is_array($message)) {
@ -164,10 +164,10 @@ class Typecho_Response
* 设置默认回执编码
*
* @access public
* @param string $charset 字符集
* @param string|null $charset 字符集
* @return void
*/
public function setCharset($charset = null)
public function setCharset(string $charset = null)
{
$this->_charset = empty($charset) ? self::CHARSET : $charset;
}
@ -178,7 +178,7 @@ class Typecho_Response
* @access public
* @return string
*/
public function getCharset()
public function getCharset(): string
{
if (empty($this->_charset)) {
$this->setCharset();
@ -194,7 +194,7 @@ class Typecho_Response
* @param string $contentType 文档类型
* @return void
*/
public function setContentType($contentType = 'text/html')
public function setContentType(string $contentType = 'text/html')
{
header('Content-Type: ' . $contentType . '; charset=' . $this->getCharset(), true);
}
@ -207,7 +207,7 @@ class Typecho_Response
* @param string $value 对应值
* @return void
*/
public function setHeader($name, $value)
public function setHeader(string $name, string $value)
{
header($name . ': ' . $value, true);
}
@ -219,10 +219,11 @@ class Typecho_Response
* @param integer $code http代码
* @return void
*/
public static function setStatus($code)
public static function setStatus(int $code)
{
if (isset(self::$_httpCode[$code])) {
header((isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1') . ' ' . $code . ' ' . self::$_httpCode[$code], true, $code);
header(($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1')
. ' ' . $code . ' ' . self::$_httpCode[$code], true, $code);
}
}
@ -233,7 +234,7 @@ class Typecho_Response
* @param string $message 消息体
* @return void
*/
public function throwXml($message)
public function throwXml(string $message)
{
/** 设置http头信息 */
$this->setContentType('text/xml');
@ -276,33 +277,33 @@ class Typecho_Response
* @param boolean $isPermanently 是否为永久重定向
* @return void
*/
public function redirect($location, $isPermanently = false)
public function redirect(string $location, bool $isPermanently = false)
{
/** Typecho_Common */
$location = Typecho_Common::safeUrl($location);
self::callback();
if ($isPermanently) {
self::callback();
header('Location: ' . $location, false, 301);
exit;
} else {
self::callback();
header('Location: ' . $location, false, 302);
exit;
}
exit;
}
/**
* 返回来路
*
* @access public
* @param string $suffix 附加地址
* @param string $default 默认来路
* @param string|null $suffix 附加地址
* @param string|null $default 默认来路
*/
public function goBack($suffix = NULL, $default = NULL)
public function goBack(string $suffix = null, string $default = null)
{
//获取来源
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
$referer = $_SERVER['HTTP_REFERER'] ?? '';
//判断来源
if (!empty($referer)) {
@ -316,7 +317,7 @@ class Typecho_Response
}
if (isset($myParts['query'])) {
$args = array();
$args = [];
if (isset($parts['query'])) {
parse_str($parts['query'], $args);
}

View File

@ -62,16 +62,16 @@ class Typecho_Validate
* @param string $key 数值键值
* @param string $rule 规则名称
* @param string $message 错误字符串
* @return Typecho_Validation
* @return $this
*/
public function addRule($key, $rule, $message)
public function addRule(string $key, string $rule, string $message): Typecho_Validate
{
if (func_num_args() <= 3) {
$this->_rules[$key][] = array($rule, $message);
$this->_rules[$key][] = [$rule, $message];
} else {
$params = func_get_args();
$params = array_splice($params, 3);
$this->_rules[$key][] = array_merge(array($rule, $message), $params);
$this->_rules[$key][] = array_merge([$rule, $message], $params);
}
return $this;
@ -94,13 +94,12 @@ class Typecho_Validate
*
* @access public
* @param array $data 需要验证的数据
* @param array $rules 验证数据遵循的规则
* @param array|null $rules 验证数据遵循的规则
* @return array
* @throws Typecho_Validate_Exception
*/
public function run(array $data, $rules = NULL)
public function run(array $data, array $rules = null): array
{
$result = array();
$result = [];
$this->_data = $data;
$rules = empty($rules) ? $this->_rules : $rules;
@ -108,7 +107,7 @@ class Typecho_Validate
foreach ($rules as $key => $rules) {
$this->_key = $key;
$data[$key] = (is_array($data[$key]) ? 0 == count($data[$key])
: 0 == strlen($data[$key])) ? NULL : $data[$key];
: 0 == strlen($data[$key])) ? null : $data[$key];
foreach ($rules as $params) {
$method = $params[0];
@ -121,7 +120,7 @@ class Typecho_Validate
$params[1] = $data[$key];
$params = array_slice($params, 1);
if (!call_user_func_array(is_array($method) ? $method : array($this, $method), $params)) {
if (!call_user_func_array(is_array($method) ? $method : [$this, $method], $params)) {
$result[$key] = $message;
break;
}
@ -144,7 +143,7 @@ class Typecho_Validate
* @param integer $length 最小长度
* @return boolean
*/
public static function minLength($str, $length)
public static function minLength(string $str, int $length): bool
{
return (Typecho_Common::strLen($str) >= $length);
}
@ -153,11 +152,11 @@ class Typecho_Validate
* 验证输入是否一致
*
* @access public
* @param string $str 待处理的字符串
* @param string|null $str 待处理的字符串
* @param string $key 需要一致性检查的键值
* @return boolean
*/
public function confirm($str, $key)
public function confirm(?string $str, string $key): bool
{
return !empty($this->_data[$key]) ? ($str == $this->_data[$key]) : empty($str);
}
@ -166,10 +165,10 @@ class Typecho_Validate
* 是否为空
*
* @access public
* @param string $str 待处理的字符串
* @param string|null $str 待处理的字符串
* @return boolean
*/
public function required($str)
public function required(?string $str): bool
{
return !empty($this->_data[$this->_key]);
}
@ -180,9 +179,9 @@ class Typecho_Validate
* @access public
* @param string $str 待处理的字符串
* @param array $params 枚举值
* @return unknown
* @return bool
*/
public static function enum($str, array $params)
public static function enum(string $str, array $params): bool
{
$keys = array_flip($params);
return isset($keys[$str]);
@ -191,11 +190,11 @@ class Typecho_Validate
/**
* Max Length
*
* @param $str
* @param $length
* @param string $str
* @param int $length
* @return bool
*/
public static function maxLength($str, $length)
public static function maxLength(string $str, int $length): bool
{
return (Typecho_Common::strLen($str) < $length);
}
@ -204,10 +203,10 @@ class Typecho_Validate
* Valid Email
*
* @access public
* @param string
* @param string $str
* @return boolean
*/
public static function email($str)
public static function email(string $str): bool
{
return preg_match("/^[_a-z0-9-\.+]+@([-a-z0-9]+\.)+[a-z]{2,}$/i", $str);
}
@ -219,7 +218,7 @@ class Typecho_Validate
* @param string $str
* @return boolean
*/
public static function url($str)
public static function url(string $str): bool
{
$parts = @parse_url($str);
if (!$parts) {
@ -227,8 +226,8 @@ class Typecho_Validate
}
return isset($parts['scheme']) &&
in_array($parts['scheme'], array('http', 'https', 'ftp')) &&
!preg_match('/(\(|\)|\\\|"|<|>|[\x00-\x08]|[\x0b-\x0c]|[\x0e-\x19])/', $str);
in_array($parts['scheme'], ['http', 'https', 'ftp']) &&
!preg_match('/(\(|\)|\\\|"|<|>|[\x00-\x08]|[\x0b-\x0c]|[\x0e-\x19])/', $str);
}
/**
@ -238,7 +237,7 @@ class Typecho_Validate
* @param string
* @return boolean
*/
public static function alpha($str)
public static function alpha(string $str): bool
{
return preg_match("/^([a-z])+$/i", $str) ? true : false;
}
@ -250,7 +249,7 @@ class Typecho_Validate
* @param string
* @return boolean
*/
public static function alphaNumeric($str)
public static function alphaNumeric(string $str): bool
{
return preg_match("/^([a-z0-9])+$/i", $str);
}
@ -262,7 +261,7 @@ class Typecho_Validate
* @param string
* @return boolean
*/
public static function alphaDash($str)
public static function alphaDash(string $str): bool
{
return preg_match("/^([_a-z0-9-])+$/i", $str) ? true : false;
}
@ -274,7 +273,7 @@ class Typecho_Validate
* @param string $str
* @return boolean
*/
public static function xssCheck($str)
public static function xssCheck(string $str): bool
{
$search = 'abcdefghijklmnopqrstuvwxyz';
$search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
@ -298,10 +297,10 @@ class Typecho_Validate
* Numeric
*
* @access public
* @param integer
* @param mixed $str
* @return boolean
*/
public static function isFloat($str)
public static function isFloat($str): bool
{
return preg_match("/^[0-9\.]+$/", $str);
}
@ -310,10 +309,10 @@ class Typecho_Validate
* Is Numeric
*
* @access public
* @param string
* @param mixed $str
* @return boolean
*/
public static function isInteger($str)
public static function isInteger($str): bool
{
return is_numeric($str);
}

View File

@ -117,7 +117,7 @@ class Widget_Contents_Attachment_Edit extends Widget_Contents_Post_Edit implemen
Typecho_Widget_Helper_Form::POST_METHOD);
/** 文件名称 */
$name = new Typecho_Widget_Helper_Form_Element_Text('name', NULL, $this->title, _t('标题 *'));
$name = new Typecho_Widget_Helper_Form_Element_Text('name', NULL, $this->title, _t('标题') . ' *');
$form->addInput($name);
/** 文件缩略名 */

View File

@ -27,7 +27,7 @@ class Widget_Init extends Typecho_Widget
$options = $this->widget('Widget_Options');
/** 检查安装状态 */
if (!$options->installed) {
if (!defined('__TYPECHO_INSTALL__') && !$options->installed) {
$options->update(array('value' => 1), Typecho_Db::get()->sql()->where('name = ?', 'installed'));
}
@ -74,7 +74,7 @@ class Widget_Init extends Typecho_Widget
Typecho_Date::setTimezoneOffset($options->timezone);
/** 开始会话, 减小负载只针对后台打开session支持 */
if ($this->widget('Widget_User')->hasLogin()) {
if (!defined('__TYPECHO_INSTALL__') && $this->widget('Widget_User')->hasLogin()) {
@session_start();
}

View File

@ -128,7 +128,7 @@ class Widget_Metas_Category_Edit extends Widget_Abstract_Metas implements Widget
Typecho_Widget_Helper_Form::POST_METHOD);
/** 分类名称 */
$name = new Typecho_Widget_Helper_Form_Element_Text('name', NULL, NULL, _t('分类名称 *'));
$name = new Typecho_Widget_Helper_Form_Element_Text('name', NULL, NULL, _t('分类名称') . ' *');
$form->addInput($name);
/** 分类缩略名 */

View File

@ -130,7 +130,7 @@ class Widget_Metas_Tag_Edit extends Widget_Abstract_Metas implements Widget_Inte
/** 标签名称 */
$name = new Typecho_Widget_Helper_Form_Element_Text('name', NULL, NULL,
_t('标签名称 *'), _t('这是标签在站点中显示的名称.可以使用中文,如 "地球".'));
_t('标签名称') . ' *', _t('这是标签在站点中显示的名称.可以使用中文,如 "地球".'));
$form->addInput($name);
/** 标签缩略名 */

View File

@ -52,12 +52,17 @@ class Widget_Options extends Typecho_Widget
* @param mixed $response response对象
* @param mixed $params 参数列表
*/
public function __construct($request, $response, $params = NULL)
public function __construct($request, $response, $params = null)
{
parent::__construct($request, $response, $params);
parent::__construct($request, $response, null);
/** 初始化数据库 */
$this->db = Typecho_Db::get();
if (!empty($params)) {
// 使用参数初始化而不使用数据库
$this->row = $params;
} else {
/** 初始化数据库 */
$this->db = Typecho_Db::get();
}
}
/**
@ -335,7 +340,7 @@ class Widget_Options extends Typecho_Widget
{
$attachmentTypesResult = array();
if (NULL != $this->attachmentTypes) {
if (null != $this->attachmentTypes) {
$attachmentTypes = str_replace(
array('@image@', '@media@', '@doc@'),
array('gif,jpg,jpeg,png,tiff,bmp', 'mp3,mp4,mov,wmv,wma,rmvb,rm,avi,flv,ogg,oga,ogv',
@ -355,12 +360,20 @@ class Widget_Options extends Typecho_Widget
*/
public function execute()
{
$this->db->fetchAll($this->db->select()->from('table.options')
->where('user = 0'), array($this, 'push'));
if (!empty($this->db)) {
$values = $this->db->fetchAll($this->db->select()->from('table.options')
->where('user = 0'), array($this, 'push'));
// finish install
if (empty($values)) {
$this->response->redirect(defined('__TYPECHO_ADMIN__')
? '../install.php?step=3' : 'install.php?step=3');
}
}
/** 支持皮肤变量重载 */
if (!empty($this->row['theme:' . $this->row['theme']])) {
$themeOptions = NULL;
$themeOptions = null;
/** 解析变量 */
if ($themeOptions = unserialize($this->row['theme:' . $this->row['theme']])) {
@ -387,7 +400,7 @@ class Widget_Options extends Typecho_Widget
}
$this->originalSiteUrl = $this->siteUrl;
$this->siteUrl = Typecho_Common::url(NULL, $this->siteUrl);
$this->siteUrl = Typecho_Common::url(null, $this->siteUrl);
$this->plugins = unserialize($this->plugins);
/** 动态判断皮肤目录 */
@ -400,7 +413,7 @@ class Widget_Options extends Typecho_Widget
/** 自动初始化路由表 */
$this->routingTable = unserialize($this->routingTable);
if (!isset($this->routingTable[0])) {
if (!empty($this->db) && !isset($this->routingTable[0])) {
/** 解析路由并缓存 */
$parser = new Typecho_Router_Parser($this->routingTable);
$parsedRoutingTable = $parser->parse();
@ -431,7 +444,7 @@ class Widget_Options extends Typecho_Widget
* @param string $path 子路径
* @return void
*/
public function siteUrl($path = NULL)
public function siteUrl($path = null)
{
echo Typecho_Common::url($path, $this->siteUrl);
}
@ -443,7 +456,7 @@ class Widget_Options extends Typecho_Widget
* @param string $path 子路径
* @return void
*/
public function index($path = NULL)
public function index($path = null)
{
echo Typecho_Common::url($path, $this->index);
}
@ -456,7 +469,7 @@ class Widget_Options extends Typecho_Widget
* @param string $theme 模版名称
* @return string
*/
public function themeUrl($path = NULL, $theme = NULL)
public function themeUrl($path = null, $theme = null)
{
if (empty($theme)) {
echo Typecho_Common::url($path, $this->themeUrl);
@ -475,7 +488,7 @@ class Widget_Options extends Typecho_Widget
* @param string $path 子路径
* @return void
*/
public function pluginUrl($path = NULL)
public function pluginUrl($path = null)
{
echo Typecho_Common::url($path, $this->pluginUrl);
}
@ -498,7 +511,7 @@ class Widget_Options extends Typecho_Widget
* @param $plugin
* @return string
*/
public function pluginDir($plugin = NULL)
public function pluginDir($plugin = null)
{
return __TYPECHO_ROOT_DIR__ . '/' . __TYPECHO_PLUGIN_DIR__;
}
@ -510,7 +523,7 @@ class Widget_Options extends Typecho_Widget
* @param string $path 子路径
* @return void
*/
public function adminUrl($path = NULL)
public function adminUrl($path = null)
{
echo Typecho_Common::url($path, $this->adminUrl);
}
@ -522,7 +535,7 @@ class Widget_Options extends Typecho_Widget
* @param string $file
* @return void|string
*/
public function adminStaticUrl($type, $file = NULL)
public function adminStaticUrl($type, $file = null)
{
$url = Typecho_Common::url($type, $this->adminUrl);

View File

@ -122,7 +122,7 @@ class Widget_Options_Permalink extends Widget_Abstract_Options implements Widget
$hasWrote = false;
if (!file_exists(__TYPECHO_ROOT_DIR__ . '/.htaccess')
&& !Typecho_Common::isAppEngine()) {
&& strpos(php_sapi_name(), 'apache') !== false) {
if (is_writeable(__TYPECHO_ROOT_DIR__)) {
$parsed = parse_url($this->options->siteUrl);
$basePath = empty($parsed['path']) ? '/' : $parsed['path'];

View File

@ -95,9 +95,10 @@ class Widget_Security extends Typecho_Widget
* 生成带token的路径
*
* @param $path
* @param string|null $url
* @return string
*/
public function getTokenUrl($path)
public function getTokenUrl($path, ?string $url = null)
{
$parts = parse_url($path);
$params = array();
@ -106,7 +107,7 @@ class Widget_Security extends Typecho_Widget
parse_str($parts['query'], $params);
}
$params['_'] = $this->getToken($this->request->getRequestUrl());
$params['_'] = $this->getToken($url ?: $this->request->getRequestUrl());
$parts['query'] = http_build_query($params);
return Typecho_Common::buildUrl($parts);

View File

@ -84,7 +84,7 @@ class Widget_Themes_Edit extends Widget_Abstract_Options implements Widget_Inter
{
$path = $this->options->themeFile($theme, $file);
if (file_exists($path) && is_writeable($path) && !Typecho_Common::isAppEngine()
if (file_exists($path) && is_writeable($path)
&& (!defined('__TYPECHO_THEME_WRITEABLE__') || __TYPECHO_THEME_WRITEABLE__)) {
$handle = fopen($path, 'wb');
if ($handle && fwrite($handle, $this->request->content)) {

View File

@ -112,7 +112,7 @@ class Widget_Themes_Files extends Typecho_Widget
public function currentIsWriteable()
{
return is_writeable($this->widget('Widget_Options')
->themeFile($this->_currentTheme, $this->_currentFile)) && !Typecho_Common::isAppEngine()
->themeFile($this->_currentTheme, $this->_currentFile))
&& (!defined('__TYPECHO_THEME_WRITEABLE__') || __TYPECHO_THEME_WRITEABLE__);
}

View File

@ -94,7 +94,7 @@ class Widget_Upload extends Widget_Abstract_Contents implements Widget_Interface
$ext = self::getSafeName($file['name']);
if (!self::checkFileType($ext) || Typecho_Common::isAppEngine()) {
if (!self::checkFileType($ext)) {
return false;
}
@ -172,7 +172,7 @@ class Widget_Upload extends Widget_Abstract_Contents implements Widget_Interface
$ext = self::getSafeName($file['name']);
if ($content['attachment']->type != $ext || Typecho_Common::isAppEngine()) {
if ($content['attachment']->type != $ext) {
return false;
}
@ -243,8 +243,7 @@ class Widget_Upload extends Widget_Abstract_Contents implements Widget_Interface
return $result;
}
return !Typecho_Common::isAppEngine()
&& @unlink(__TYPECHO_ROOT_DIR__ . '/' . $content['attachment']->path);
return @unlink(__TYPECHO_ROOT_DIR__ . '/' . $content['attachment']->path);
}
/**

View File

@ -286,8 +286,8 @@ class Widget_User extends Typecho_Widget
} else {
//防止循环重定向
$this->response->redirect(defined('__TYPECHO_ADMIN__') ? $this->options->loginUrl .
(0 === strpos($this->request->getReferer(), $this->options->loginUrl) ? '' :
'?referer=' . urlencode($this->request->makeUriByRequest())) : $this->options->siteUrl, false);
(0 === strpos($this->request->getReferer(), $this->options->loginUrl) ? '' :
'?referer=' . urlencode($this->request->makeUriByRequest())) : $this->options->siteUrl, false);
}
}

View File

@ -95,12 +95,12 @@ class Widget_Users_Edit extends Widget_Abstract_Users implements Widget_Interfac
Typecho_Widget_Helper_Form::POST_METHOD);
/** 用户名称 */
$name = new Typecho_Widget_Helper_Form_Element_Text('name', NULL, NULL, _t('用户名 *'), _t('此用户名将作为用户登录时所用的名称.')
$name = new Typecho_Widget_Helper_Form_Element_Text('name', NULL, NULL, _t('用户名') . ' *', _t('此用户名将作为用户登录时所用的名称.')
. '<br />' . _t('请不要与系统中现有的用户名重复.'));
$form->addInput($name);
/** 电子邮箱地址 */
$mail = new Typecho_Widget_Helper_Form_Element_Text('mail', NULL, NULL, _t('电子邮箱地址 *'), _t('电子邮箱地址将作为此用户的主要联系方式.')
$mail = new Typecho_Widget_Helper_Form_Element_Text('mail', NULL, NULL, _t('邮件地址') . ' *', _t('电子邮箱地址将作为此用户的主要联系方式.')
. '<br />' . _t('请不要与系统中现有的电子邮箱地址重复.'));
$form->addInput($mail);
@ -180,8 +180,8 @@ class Widget_Users_Edit extends Widget_Abstract_Users implements Widget_Interfac
$name->addRule('required', _t('必须填写用户名称'));
$name->addRule('xssCheck', _t('请不要在用户名中使用特殊字符'));
$name->addRule(array($this, 'nameExists'), _t('用户名已经存在'));
$password->label(_t('用户密码 *'));
$confirm->label(_t('用户密码确认 *'));
$password->label(_t('用户密码') . ' *');
$confirm->label(_t('用户密码确认') . ' *');
$password->addRule('required', _t('必须填写密码'));
}

View File

@ -55,7 +55,7 @@ class Widget_Users_Profile extends Widget_Users_Edit implements Widget_Interface
$form->addInput($url);
/** 电子邮箱地址 */
$mail = new Typecho_Widget_Helper_Form_Element_Text('mail', NULL, NULL, _t('电子邮箱地址 *'), _t('电子邮箱地址将作为此用户的主要联系方式.')
$mail = new Typecho_Widget_Helper_Form_Element_Text('mail', NULL, NULL, _t('邮件地址') . ' *', _t('电子邮箱地址将作为此用户的主要联系方式.')
. '<br />' . _t('请不要与系统中现有的电子邮箱地址重复.'));
$form->addInput($mail);