| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923 |
- <?php
- /**
- * 此文件包括ZenTaoPHP框架的三个类:baseRouter, config, lang。
- * The router, config and lang class file of ZenTaoPHP framework.
- *
- * @package framework
- *
- * The author disclaims copyright to this source code. In place of
- * a legal notice, here is a blessing:
- *
- * May you do good and not evil.
- * May you find forgiveness for yourself and forgive others.
- * May you share freely, never taking more than you give.
- */
- class baseRouter
- {
- /**
- * ZenTaoPHP的基础目录,一般是程序的根目录。
- * The base path of the ZenTaoPHP framework.
- *
- * @var string
- * @access public
- */
- public $basePath;
- /**
- * 框架的根目录。
- * The root directory of the framwork($this->basePath/framework)
- *
- * @var string
- * @access public
- */
- public $frameRoot;
- /**
- * 类库的根目录。{$this->basePath/lib}
- * The root directory of the library($this->basePath/lib).
- *
- * @var string
- * @access public
- */
- public $coreLibRoot;
- /**
- * 应用名称
- * The appName.
- *
- * @var string
- * @access public
- */
- public $appName = '';
- /**
- * 应用程序的根目录。
- * The root directory of the app.
- *
- * @var string
- * @access public
- */
- public $appRoot;
- /**
- * 临时文件的根目录。
- * The root directory of temp.
- *
- * @var string
- * @access public
- */
- public $tmpRoot;
- /**
- * 缓存的根目录。
- * The root directory of cache.
- *
- * @var string
- * @access public
- */
- public $cacheRoot;
- /**
- * WWW目录。
- * The root directory of www.
- *
- * @var string
- * @access public
- */
- public $wwwRoot;
- /**
- * 附件存放目录。
- * The root directory of data.
- *
- * @var string
- * @access public
- */
- public $dataRoot;
- /**
- * 日志文件的根目录。
- * The root directory of log.
- *
- * @var string
- * @access public
- */
- public $logRoot;
- /**
- * 配置文件的根目录。
- * The root directory of config.
- *
- * @var string
- * @access public
- */
- public $configRoot;
- /**
- * 模块的根目录。
- * The root directory of module.
- *
- * @var string
- * @access public
- */
- public $moduleRoot;
- /**
- * 主题的根目录。
- * The root directory of theme.
- *
- * @var string
- * @access public
- */
- public $themeRoot;
- /**
- * 用户使用的语言。
- * The lang of the client user.
- *
- * @var string
- * @access public
- */
- public $clientLang;
- /**
- * 请求的原始模块名。
- * The requestd module name parsed from a URL.
- *
- * @var string
- * @access public
- */
- public $rawModule;
- /**
- * 请求的原始方法名。
- * The requested method name parsed from a URL.
- *
- * @var string
- * @access public
- */
- public $rawMethod;
- /**
- * 当前页面所在的应用,用于左侧菜单栏判断。
- * The current app code(url: '#app=?'), highlight left menu.
- *
- * @var string
- * @access public
- */
- public $tab;
- /**
- * API版本号
- * The version of API.
- *
- * @var string
- * @access public
- */
- public $apiVersion = '';
- /**
- * 用户使用的主题。
- * The theme of the client user.
- *
- * @var string
- * @access public
- */
- public $clientTheme;
- /**
- * 客户端设备类型。
- * The device type of client.
- *
- * @var string
- * @access public
- */
- public $clientDevice;
- /**
- * 当前模块的control对象。
- * The control object of current module.
- *
- * @var object
- * @access public
- */
- public $control;
- /**
- * 模块名。
- * The module name
- *
- * @var string
- * @access public
- */
- public $moduleName;
- /**
- * 当前访问模块的control文件。
- * The control file of the module current visiting.
- *
- * @var string
- * @access public
- */
- public $controlFile;
- /**
- * 当前访问的方法名。
- * The name of the method current visiting.
- *
- * @var string
- * @access public
- */
- public $methodName;
- /**
- * 当前方法的扩展文件。
- * The action extension file of current method.
- *
- * @var string
- * @access public
- */
- public $extActionFile;
- /**
- * 访问的URI。
- * The URI.
- *
- * @var string
- * @access public
- */
- public $uri;
- /**
- * url地址传递的参数。
- * The params passed in through url.
- *
- * @var array
- * @access public
- */
- public $params;
- /**
- * 视图类型。
- * The view type.
- *
- * @var string
- * @access public
- */
- public $viewType = 'html';
- /**
- * 全局$config对象。
- * The global $config object.
- *
- * @var object
- * @access public
- */
- public $config;
- /**
- * 已加载的配置文件.
- * Configs loaded.
- *
- * @static
- * @var array
- * @access public
- */
- static $loadedConfigs = array();
- /**
- * 已加载的语言文件.
- * Languages loaded.
- *
- * @static
- * @var array
- * @access public
- */
- static $loadedLangs = array();
- /**
- * 已加载的目标,可能是 model,tao 或者 zen 的实例化对象。
- * Targets loaded, maybe instance of model, tao or zen.
- *
- * @static
- * @var array
- * @access public
- */
- static $loadedTargets = array();
- /**
- * 全局$lang对象。
- * The global $lang object.
- *
- * @var object
- * @access public
- */
- public $lang;
- /**
- * 全局缓存对象,用于操作缓存。
- * The global cache object, used to operate cache.
- *
- * @var object
- * @access public
- */
- public $cache = null;
- /**
- * 全局$dbh对象,数据库连接句柄。
- * The global $dbh object, the database connection handler.
- *
- * @var object
- * @access public
- */
- public $dbh;
- /**
- * $dao对象,用于访问或者更新数据库。
- * The $dao object, used to access or update database.
- *
- * @var dao
- * @access public
- */
- public $dao;
- /**
- * $mao对象,用于访问或者更新缓存。
- * The $mao object, used to access or update cache.
- *
- * @var mao
- * @access public
- */
- public $mao;
- /**
- * 从数据库的句柄。
- * The slave database handler.
- *
- * @var object
- * @access public
- */
- public $slaveDBH;
- /**
- * $post对象,用于访问$_POST变量。
- * The $post object, used to access the $_POST var.
- *
- * @var object
- * @access public
- */
- public $post;
- /**
- * $get对象,用于访问$_GET变量。
- * The $get object, used to access the $_GET var.
- *
- * @var object
- * @access public
- */
- public $get;
- /**
- * $session对象,用于访问$_SESSION变量。
- * The $session object, used to access the $_SESSION var.
- *
- * @var object
- * @access public
- */
- public $session;
- /**
- * $server对象,用于访问$_SERVER变量。
- * The $server object, used to access the $_SERVER var.
- *
- * @var object
- * @access public
- */
- public $server;
- /**
- * $cookie对象,用于访问$_COOKIE变量。
- * The $cookie object, used to access the $_COOKIE var.
- *
- * @var object
- * @access public
- */
- public $cookie;
- /**
- * 原始SESSIONID
- * SESSIONID
- *
- * @var int
- * @access public
- */
- public $sessionID;
- /**
- * 网站代号。
- * The code of current site.
- *
- * @var string
- * @access public
- */
- public $siteCode;
- /**
- * 请求开始时间。
- * The start time of the request.
- *
- * @var float
- */
- public $startTime;
- /**
- * zin 请求时发生的错误信息。
- * The errors occurred when zin request.
- *
- * @var array
- */
- public $zinErrors = array();
- /**
- * 是否将mysql的错误作为异常抛出。
- * Whether to throw mysql error as exception.
- *
- * @var bool
- */
- public $throwError = false;
- /**
- * 是否使用客户端缓存。
- * Whether to use client cache.
- *
- * @var bool
- */
- public $useClientCache = true;
- /**
- * 客户端缓存时间。
- * The client cache time.
- *
- * @var int
- */
- public $clientCacheTime = 0;
- /**
- * 缓存Model。
- * The cache model.
- *
- * @var object
- */
- public $cacheModel;
- /**
- * 是否需要对htmlspecialchars进行解码。
- * Whether need to decode htmlspecialchars.
- *
- * @var bool
- */
- public $needDecodeHtmlSpecialChars = null;
- /**
- * 构造方法, 设置路径,类,超级变量等。注意:
- * 1.应该使用createApp()方法实例化router类;
- * 2.如果$appRoot为空,框架会根据$appName计算应用路径。
- *
- * The construct function.
- * Prepare all the paths, classes, super objects and so on.
- * Notice:
- * 1. You should use the createApp() method to get an instance of the router.
- * 2. If the $appRoot is empty, the framework will compute the appRoot according the $appName
- *
- * @param string $appName the name of the app
- * @param string $appRoot the root path of the app
- * @param string $mode the mode of the app running|installing|upgrading
- * @access public
- * @return void
- */
- public function __construct($appName = 'demo', $appRoot = '', $mode = 'running')
- {
- if($mode != 'running') $this->{$mode} = true;
- $this->setPathFix();
- $this->setBasePath();
- $this->setFrameRoot();
- $this->setCoreLibRoot();
- $this->setAppRoot($appName, $appRoot);
- $this->setTmpRoot();
- $this->setCacheRoot();
- $this->setLogRoot();
- $this->setConfigRoot();
- $this->setModuleRoot();
- $this->setWwwRoot();
- $this->setThemeRoot();
- $this->setDataRoot();
- $this->loadMainConfig();
- $this->loadClass('front', $static = true);
- $this->loadClass('filter', $static = true);
- $this->loadClass('form', $static = true);
- $this->loadClass('dbh', $static = true);
- $this->loadClass('sqlite', $static = true);
- $this->loadClass('dao', $static = true);
- $this->loadClass('mobile', $static = true);
- $this->setCookieSecure();
- $this->setDebug();
- $this->setErrorHandler();
- $this->setTimezone();
- if($this->config->framework->autoConnectDB) $this->connectDB();
- $this->setupXhprof();
- $this->setEdition();
- $this->setClient();
- $this->loadCache();
- }
- /**
- * 设置客户端信息
- * Set info of client: session, lang, device, theme...
- *
- * @access public
- * @return void
- */
- public function setClient()
- {
- $this->startSession();
- if($this->config->framework->multiSite) $this->setSiteCode() && $this->loadExtraConfig();
- if($this->config->framework->multiLanguage) $this->setClientLang();
- $this->setVision();
- $needDetectDevice = zget($this->config->framework->detectDevice, $this->clientLang, false);
- $this->clientDevice = $needDetectDevice ? $this->setClientDevice() : 'desktop';
- if($this->config->framework->multiLanguage) $this->loadLang('common');
- if($this->config->framework->multiTheme) $this->setClientTheme();
- $this->setOpenApp();
- $this->setSuperVars();
- if(isset($_SERVER['HTTP_X_ZIN_CACHE_TIME'])) $this->clientCacheTime = (int) $_SERVER['HTTP_X_ZIN_CACHE_TIME'];
- }
- /**
- * 创建一个应用。
- * Create an application.
- *
- * @param string $appName 应用名称。 The name of the app.
- * @param string $appRoot 应用根路径。The root path of the app.
- * @param string $className 应用类名,如果对router类做了扩展,需要指定类名。When extends router class, you should pass in the child router class name.
- * @param string $mode 应用模式。 The mode of the app. running|installing|upgrading
- * @static
- * @access public
- * @return baseRouter
- */
- public static function createApp($appName = 'demo', $appRoot = '', $className = '', $mode = 'running')
- {
- if(empty($className)) $className = self::class;
- return new $className($appName, $appRoot, $mode);
- }
- /**
- * 设置请求开始时间。
- * The start time of the request.
- *
- * @param float $startTime
- * @access public
- * @return void
- */
- public function setStartTime($startTime)
- {
- $this->startTime = $startTime;
- }
- //-------------------- 路径相关方法(Path related methods)--------------------//
- /**
- * 设置应用名称。
- * Set app name.
- *
- * @param string $appName
- * @access public
- * @return void
- */
- public function setAppName($appName)
- {
- $this->appName = $appName;
- }
- /**
- * 设置目录分隔符。
- * Set the path directory separator.
- *
- * @access public
- * @return void
- */
- public function setPathFix()
- {
- define('DS', DIRECTORY_SEPARATOR);
- }
- /**
- * 设置基础目录。
- * Set the base path.
- *
- * @access public
- * @return void
- */
- public function setBasePath()
- {
- $this->basePath = realpath(dirname(__FILE__, 3)) . DS;
- }
- /**
- * 设置框架根目录。
- * Set the frame root.
- *
- * @access public
- * @return void
- */
- public function setFrameRoot()
- {
- $this->frameRoot = $this->basePath . 'framework' . DS;
- }
- /**
- * 设置类库的根目录。
- * Set the app lib root.
- *
- * @access public
- * @return void
- */
- public function setCoreLibRoot()
- {
- $this->coreLibRoot = $this->basePath . 'lib' . DS;
- }
- /**
- * 设置应用的根目录。
- * Set the app root.
- *
- * @param string $appName
- * @param string $appRoot
- * @access public
- * @return void
- */
- public function setAppRoot($appName = 'demo', $appRoot = '')
- {
- if(empty($appRoot)) $this->appRoot = $this->basePath . 'app' . DS . $appName . DS;
- if(!empty($appRoot)) $this->appRoot = realpath($appRoot) . DS;
- if(!is_dir($this->appRoot)) $this->triggerError("The app you call not found in {$this->appRoot}", __FILE__, __LINE__, true);
- }
- /**
- * 设置临时文件的根目录。
- * Set the tmp root.
- *
- * @access public
- * @return void
- */
- public function setTmpRoot()
- {
- $this->tmpRoot = $this->basePath . 'tmp' . DS;
- }
- /**
- * 设置缓存的根目录。
- * Set the cache root.
- *
- * @access public
- * @return void
- */
- public function setCacheRoot()
- {
- $this->cacheRoot = $this->tmpRoot . 'cache' . DS;
- }
- /**
- * 设置log的根目录。
- * Set the log root.
- *
- * @access public
- * @return void
- */
- public function setLogRoot()
- {
- $this->logRoot = $this->tmpRoot . 'log' . DS;
- }
- /**
- * 设置config配置文件的根目录。
- * Set the config root.
- *
- * @access public
- * @return void
- */
- public function setConfigRoot()
- {
- $this->configRoot = $this->basePath . 'config' . DS;
- }
- /**
- * 设置模块的根目录。
- * Set the module root.
- *
- * @access public
- * @return void
- */
- public function setModuleRoot()
- {
- $this->moduleRoot = $this->basePath . 'module' . DS;
- }
- /**
- * 设置www的根目录。
- * Set the www root.
- *
- * @access public
- * @return void
- */
- public function setWwwRoot()
- {
- $this->wwwRoot = rtrim(dirname((string) $_SERVER['SCRIPT_FILENAME']), DS) . DS;
- }
- /**
- * 设置主题根目录。
- * Set the theme root.
- *
- * @access public
- * @return void
- */
- public function setThemeRoot()
- {
- $this->themeRoot = $this->wwwRoot . 'theme' . DS;
- }
- /**
- * 设置data根目录。
- * Set the data root.
- *
- * @access public
- * @return void
- */
- public function setDataRoot()
- {
- $this->dataRoot = $this->wwwRoot . 'data' . DS;
- }
- /**
- * 设置超级变量。
- * Set the super vars.
- *
- * @access public
- * @return void
- */
- public function setSuperVars()
- {
- if(isset($_SERVER['REQUEST_URI']))
- {
- $uri = $_SERVER['REQUEST_URI'];
- if(strpos((string) $uri, '?') !== false)
- {
- $parsedURL = parse_url((string) $uri);
- if(isset($parsedURL['query']))
- {
- parse_str($parsedURL['query'], $parsedQuery);
- foreach($parsedQuery as $key => $value)
- {
- if(!isset($_GET[$key])) $_GET[$key] = $value;
- }
- }
- }
- }
- $this->post = new super('post');
- $this->get = new super('get');
- $this->server = new super('server');
- $this->cookie = new super('cookie');
- $this->session = new super('session', $this->tab);
- unset($_REQUEST);
- /* Change for CSRF. */
- if($this->config->framework->filterCSRF)
- {
- $httpType = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on') ? 'https' : 'http';
- if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) and strtolower((string) $_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') $httpType = 'https';
- if(isset($_SERVER['REQUEST_SCHEME']) and strtolower((string) $_SERVER['REQUEST_SCHEME']) == 'https') $httpType = 'https';
- $httpHost = zget($_SERVER, 'HTTP_HOST', '');
- $apiMode = $this->apiVersion || isset($_GET[$this->config->sessionVar]);
- if(!$apiMode && (empty($httpHost) or strncmp((string) $this->server->http_referer, "$httpType://$httpHost", strlen("$httpType://$httpHost")) !== 0)) $_FILES = $_POST = array();
- }
- $_FILES = validater::filterFiles();
- $_POST = validater::filterSuper($_POST);
- $_GET = validater::filterSuper($_GET);
- $_COOKIE = validater::filterSuper($_COOKIE);
- $_SERVER = validater::filterSuper($_SERVER);
- /* Filter common get and cookie vars. */
- if($this->config->framework->filterParam == 2)
- {
- global $filter;
- foreach($filter->default->get as $key => $rules)
- {
- if(isset($_GET[$key]) and !validater::checkByRule($_GET[$key], $rules)) unset($_GET[$key]);
- }
- foreach($filter->default->cookie as $key => $rules)
- {
- if(isset($_COOKIE[$key]) and !validater::checkByRule($_COOKIE[$key], $rules)) unset($_COOKIE[$key]);
- }
- }
- }
- /**
- * Set cookieSecure config.
- *
- * @access public
- * @return void
- */
- public function setCookieSecure()
- {
- $this->config->cookieSecure = false;
- if($this->config->framework->setCookieSecure and isHttps()) $this->config->cookieSecure = true;
- }
- /**
- * 设置Debug模式。
- * set Debug.
- *
- * @access public
- * @return void
- */
- public function setDebug()
- {
- if(!empty($this->config->debug)) error_reporting(E_ALL);
- }
- /**
- * 启用Xhprof。
- * Setup xhprof.
- *
- * @return void
- */
- protected function setupXhprof()
- {
- if(!empty($this->config->debug) && $this->config->debug >= 4 && extension_loaded('xhprof')) xhprof_enable();
- }
- /**
- * 输出Xhprof结果。
- * Output xhprof.
- *
- * @return bool
- */
- public function outputXhprof()
- {
- if(empty($this->config->debug) || $this->config->debug < 4 || !extension_loaded('xhprof')) return false;
- $log = xhprof_disable();
- $xhprofPath = $this->getWwwRoot() . 'xhprof';
- $libUtilsPath = $xhprofPath . DS . 'xhprof_lib' . DS . 'utils' . DS;
- $outputDir = ini_get('xhprof.output_dir');
- if(!is_dir($xhprofPath)) return false;
- if(!$outputDir) $outputDir = $xhprofPath . DS . 'xhprof_runs';
- if(!is_dir($outputDir)) mkdir($outputDir, 0777, true);
- include_once $libUtilsPath . 'xhprof_lib.php';
- include_once $libUtilsPath . 'xhprof_runs.php';
- $xhprofRuns = new \XHProfRuns_Default($outputDir);
- $type = "{$this->moduleName}_{$this->methodName}";
- $runID = $xhprofRuns->save_run($log, $type);
- if(!headers_sent()) helper::header('Xhprof-RunID', $runID);
- return true;
- }
- /**
- * 设置版本。
- * Set edition.
- *
- * @access public
- * @return void
- */
- public function setEdition()
- {
- if(isset($this->config->edition)) return $this->config->edition;
- $edition = substr((string) $this->config->version, 0, 3);
- if(in_array($edition, array('pro', 'biz', 'max'))) return $this->config->edition = $edition;
- $this->config->edition = 'open';
- }
- /**
- * 设置vision。
- * set Debug.
- *
- * @access public
- * @return void
- */
- public function setVision()
- {
- $account = isset($_SESSION['user']) ? $_SESSION['user']->account : '';
- if(empty($account) and isset($_POST['account'])) $account = $_POST['account'];
- if(empty($account) and isset($_GET['account'])) $account = $_GET['account'];
- if(empty($account) and isset($_COOKIE['za'])) $account = $_COOKIE['za'];
- $vision = '';
- if($this->config->installed and validater::checkAccount($account) and !$this->upgrading)
- {
- if(!empty($_COOKIE['vision']))
- {
- $vision = $_COOKIE['vision'];
- }
- else
- {
- $vision = $this->dao->select("value")->from(TABLE_CONFIG)->where('owner')->eq($account)->andWhere('`key`')->eq('vision')->limit(1)->fetch('value');
- }
- $user = $this->dao->select('*')->from(TABLE_USER)->where('account')->eq($account)->andWhere('deleted')->eq('0')->limit(1)->fetch();
- if(!empty($user->visions))
- {
- $userVisions = explode(',', $user->visions);
- if(!in_array($vision, $userVisions)) $vision = '';
- if(empty($vision)) [$vision] = $userVisions;
- }
- }
- [$defaultVision] = explode(',', trim((string) $this->config->visions, ','));
- if($defaultVision != 'lite' && $defaultVision != 'or') $defaultVision = 'rnd';
- if($vision and strpos((string) $this->config->visions, ",{$vision},") === false) $vision = $defaultVision;
- $vision = $vision ?: $defaultVision;
- if(empty($_COOKIE['vision'])) setcookie('vision', $vision, $this->config->cookieLife, $this->config->webRoot, '', false, false);
- $this->config->vision = $vision;
- }
- /**
- * Get installed version.
- *
- * @access public
- * @return string
- */
- public function getInstalledVersion()
- {
- if(!isset($this->config->installed) || !$this->config->installed) return false;
- $version = $this->dao->select('`value`')->from(TABLE_CONFIG)->where('`owner`')->eq('system')->andWhere('`key`')->eq('version')->andWhere('`module`')->eq('common')->andWhere('`section`')->eq('global')->limit(1)->fetch('value');
- if(!$version && ($this->config->inContainer || $this->config->inQuickon)) return false;
- if(!$version) $version = '0.3.beta'; // No version, set as 0.3.beta.
- if($version == '3.0.stable') $version = '3.0'; // convert 3.0.stable to 3.0.
- return $version;
- }
- /**
- * 设置错误处理句柄。
- * Set the error handler.
- *
- * @access public
- * @return void
- */
- public function setErrorHandler()
- {
- set_error_handler(\Closure::fromCallable([$this, 'saveError']));
- register_shutdown_function(array($this, 'shutdown'));
- }
- /**
- * 获取应用名称
- * Get app name
- *
- * @access public
- * @return string
- */
- public function getAppName()
- {
- return $this->appName;
- }
- /**
- * 获取$basePath,即基础路径。
- * Get the $basePath var.
- *
- * @access public
- * @return string
- */
- public function getBasePath()
- {
- return $this->basePath;
- }
- /**
- * 获取$frameRoot,即框架根目录。
- * Get the $frameRoot var.
- *
- * @access public
- * @return string
- */
- public function getFrameRoot()
- {
- return $this->frameRoot;
- }
- /**
- * 获取$appRoot变量,即应用的根目录。
- * Get the $appRoot var.
- *
- * @access public
- * @return string
- */
- public function getAppRoot()
- {
- return $this->appRoot;
- }
- /**
- * 获取$wwwRoot变量。
- * Get the $wwwRoot var
- *
- * @access public
- * @return string
- */
- public function getWwwRoot()
- {
- return $this->wwwRoot;
- }
- /**
- * 获取$coreLibRoot变量,即应用类库的根目录。
- * Get the $coreLibRoot var.
- *
- * @access public
- * @return string
- */
- public function getCoreLibRoot()
- {
- return $this->coreLibRoot;
- }
- /**
- * 获取$tmpRoot变量,即临时文件的根目录。
- * Get the $tmpRoot var.
- *
- * @access public
- * @return string
- */
- public function getTmpRoot()
- {
- return $this->tmpRoot;
- }
- /**
- * 获取$cacheRoot变量,即缓存文件的根目录。
- * Get the $cacheRoot var.
- *
- * @access public
- * @return string
- */
- public function getCacheRoot()
- {
- return $this->cacheRoot;
- }
- /**
- * 获取$logRoot变量,即日志文件的根目录。
- * Get the $logRoot var.
- *
- * @access public
- * @return string
- */
- public function getLogRoot()
- {
- return $this->logRoot;
- }
- /**
- * 获取$configRoot变量,即配置文件的根目录。
- * Get the $configRoot var.
- *
- * @access public
- * @return string
- */
- public function getConfigRoot()
- {
- return $this->configRoot;
- }
- /**
- * 获取$moduleRoot变量,即应用模块的根目录。
- * Get the $moduleRoot var.
- *
- * @param string $appName
- * @access public
- * @return string
- */
- public function getModuleRoot($appName = '')
- {
- if($appName == '') return $this->moduleRoot;
- return dirname($this->moduleRoot) . DS . $appName . DS;
- }
- /**
- * 获取扩展根目录。
- * Get the root of extension.
- *
- * @access public
- * @return string
- */
- public function getExtensionRoot()
- {
- return $this->basePath . 'extension' . DS;
- }
- /**
- * 获取$webRoot,即应用的路径。
- * Get the $webRoot var.
- *
- * @access public
- * @return string
- */
- public function getWebRoot()
- {
- return $this->config->webRoot;
- }
- /**
- * 获取$themeRoot变量,即主题的根目录。
- * Get the $themeRoot var.
- *
- * @access public
- * @return string
- */
- public function getThemeRoot()
- {
- return $this->themeRoot;
- }
- /**
- * 获取$dataRoot目录
- * Get the $dataRoot var
- *
- * @access public
- * @return string
- */
- public function getDataRoot()
- {
- return $this->dataRoot;
- }
- //------ 客户端环境有关的函数(Client environment related functions) ------//
- /**
- * 根据配置设置当前时区。
- * Set the time zone according to the config.
- *
- * @access public
- * @return void
- */
- public function setTimezone()
- {
- if(isset($this->config->timezone)) date_default_timezone_set($this->config->timezone);
- }
- /**
- * 开启 session
- * Start the session.
- *
- * @access public
- * @return void
- */
- public function startSession()
- {
- if(defined('SESSION_STARTED')) return;
- /* API session use tmp/apisession directory. */
- $apiMode = $this->apiVersion || isset($_GET[$this->config->sessionVar]);
- if(ini_get('session.save_handler') == 'files' || $apiMode)
- {
- $savePath = $this->getTmpRoot() . ($apiMode ? 'apisession' : 'session');
- if(!is_dir($savePath)) mkdir($savePath, 0777, true);
- if(is_writable($savePath))
- {
- session_save_path($savePath);
- $ztSessionHandler = new ztSessionHandler();
- session_set_save_handler($ztSessionHandler, true);
- }
- }
- $sessionName = $this->config->sessionVar;
- session_name($sessionName);
- session_set_cookie_params(0, $this->config->webRoot, '', $this->config->cookieSecure, true);
- if(!session_id()) session_start();
- $this->sessionID = isset($ztSessionHandler) ? $ztSessionHandler->getSessionID() : session_id();
- if(isset($_SERVER['HTTP_TOKEN'])) // If request header has token, use it as session for authentication.
- {
- helper::restartSession($_SERVER['HTTP_TOKEN']);
- $this->sessionID = isset($ztSessionHandler) ? $ztSessionHandler->getSessionID() : session_id();
- }
- elseif(isset($_GET[$this->config->sessionVar]))
- {
- /* 为了避免安全漏洞,必须在从GET参数恢复会话之前记录sessionID,以便在index.php判断session_id() != $app->sessionID后重启会话。*/
- /* To avoid security issue, we have to record sessionID before restart session from GET param, so that we can restart session in index.php when session_id() != $app->sessionID. */
- $this->sessionID = $_GET[$this->config->sessionVar];
- helper::restartSession($_GET[$this->config->sessionVar]);
- }
- define('SESSION_STARTED', true);
- }
- /**
- * 从cookie中获取当前的group, 即URL锚链接'#app=?'。
- * Get current group from cookie, original source is url '#tab=?'.
- *
- * @access public
- * @return void
- */
- public function setOpenApp()
- {
- $module = $this->rawModule;
- $this->tab = 'my';
- if(isset($this->lang->navGroup)) $this->tab = zget($this->lang->navGroup, $module, 'my');
- if(isset($_COOKIE['tab']) && $_COOKIE['tab'] && preg_match('/^\w+$/', $_COOKIE['tab'])) $this->tab = $_COOKIE['tab'];
- if(isset($this->config->zin) && isset($_SERVER['HTTP_X_ZIN_APP'])) $this->tab = $_SERVER['HTTP_X_ZIN_APP'];
- if(!isset($this->lang->mainNav->{$this->tab})) $this->tab = 'my';
- }
- /**
- * 根据用户浏览器的语言设置和服务器配置,选择显示的语言。
- * 优先级:$lang参数 > session > cookie > 浏览器 > 配置文件。
- *
- * Set the language.
- * Using the order of method $lang param, session, cookie, browser and the default lang.
- *
- * @param string $lang zh-cn|zh-tw|zh-hk|en
- * @access public
- * @return void
- */
- public function setClientLang($lang = '')
- {
- if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) $this->clientLang = $this->parseHttpAcceptLang();
- if(isset($_COOKIE['lang'])) $this->clientLang = $_COOKIE['lang'];
- if(isset($_SESSION['lang'])) $this->clientLang = $_SESSION['lang'];
- if(!empty($lang)) $this->clientLang = $lang;
- if(!empty($this->clientLang))
- {
- $this->clientLang = strtolower($this->clientLang);
- if(!isset($this->config->langs[$this->clientLang])) $this->clientLang = $this->config->default->lang;
- }
- else
- {
- $this->clientLang = $this->config->default->lang;
- }
- helper::setcookie('lang', (string) $this->clientLang, $this->config->cookieLife, (string) $this->config->webRoot, '', $this->config->cookieSecure, false);
- if(!isset($_COOKIE['lang'])) $_COOKIE['lang'] = $this->clientLang;
- return true;
- }
- /**
- * 从HTTP_ACCEPT_LANGUAGE中剔除去支持的语言。
- * Parse the lang str from HTTP_ACCEPT_LANGUAGE header.
- *
- * @access public
- * @return string
- */
- public function parseHttpAcceptLang()
- {
- if(empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) return '';
- $raw = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
- $pos = strpos((string) $raw, ',');
- $lang = $pos === false ? $raw : substr((string) $raw, 0, $pos);
- /* Fix clientLang for ie >= 10. https://www.drupal.org/node/365615. */
- if(stripos((string) $lang, 'hans')) $lang = 'zh-cn';
- if(stripos((string) $lang, 'hant')) $lang = 'zh-tw';
- return $lang;
- }
- /**
- * 设置客户端使用的主题,判断逻辑与客户端的语言相同。
- * 主题的css和图片文件应该存放在www/theme/$themeName路径。
- *
- * Set the theme the client user using. The logic is same as the clientLang.
- * The css and images files of an theme should saved at www/theme/$themeName
- *
- * @param string $theme
- * @access public
- * @return void
- */
- public function setClientTheme($theme = '')
- {
- if(isset($this->config->client->theme)) $this->clientTheme = $this->config->client->theme;
- if(isset($_COOKIE['theme'])) $this->clientTheme = $_COOKIE['theme'];
- if(!empty($theme)) $this->clientTheme = $theme;
- if(!empty($this->clientTheme))
- {
- $this->clientTheme = strtolower($this->clientTheme);
- if(!isset($this->lang->themes[$this->clientTheme])) $this->clientTheme = $this->config->default->theme;
- }
- else
- {
- $this->clientTheme = $this->config->default->theme;
- }
- helper::setcookie('theme', (string) $this->clientTheme, $this->config->cookieLife, (string) $this->config->webRoot, '', $this->config->cookieSecure, false);
- if(!isset($_COOKIE['theme'])) $_COOKIE['theme'] = $this->clientTheme;
- return true;
- }
- /**
- * 设置客户端的设备类型。
- * Set client device.
- *
- * @access public
- * @return void
- */
- public function setClientDevice()
- {
- $this->clientDevice = 'desktop';
- $cookieDevice = zget($_COOKIE, 'device', 'desktop');
- if($cookieDevice == 'mobile') $this->clientDevice = 'mobile';
- if($cookieDevice == 'desktop') $this->clientDevice = 'desktop';
- if(empty($this->cookie->device) || strpos('mobile,desktop', (string) $this->cookie->device) === false)
- {
- $mobile = new mobile();
- $this->clientDevice = ($mobile->isMobile() and !$mobile->isTablet()) ? 'mobile' : 'desktop';
- }
- helper::setcookie('device', $this->clientDevice, $this->config->cookieLife, (string) $this->config->webRoot, '', $this->config->cookieSecure, true);
- if(!isset($_COOKIE['device'])) $_COOKIE['device'] = $this->clientDevice;
- return $this->clientDevice;
- }
- /**
- * 设置站点代号,可以针对不同的站点来加载不同的扩展。
- * Set the code of current site, thus can load different extension of different site.
- *
- * @access public
- * @return void
- */
- public function setSiteCode()
- {
- return $this->siteCode = helper::parseSiteCode($this->server->http_host);
- }
- /**
- * 获取$clientLang变量,即客户端的语言。
- * Get the $clientLang var.
- *
- * @access public
- * @return string
- */
- public function getClientLang()
- {
- return $this->clientLang;
- }
- /**
- * 获取$clientTheme变量。
- * Get the $clientTheme var.
- *
- * @access public
- * @return string
- */
- public function getClientTheme()
- {
- return $this->config->webRoot . 'theme/' . $this->clientTheme . '/';
- }
- /**
- * 获得客户端的终端设备。
- * Get the client device.
- *
- * @access public
- * @return void
- */
- public function getClientDevice()
- {
- return $this->clientDevice;
- }
- //-------------------- 请求相关的方法(Request related methods) --------------------//
- /**
- * 解析本次请求的入口方法,根据请求的类型(PATH_INFO GET),调用相应的方法。
- * The entrance of parsing request. According to the requestType, call related methods.
- *
- * @access public
- * @return void
- */
- public function parseRequest()
- {
- if(strncmp($_SERVER['REQUEST_URI'], '/data/upload', strlen('/data/upload')) === 0 && !is_file($this->wwwRoot . $_SERVER['REQUEST_URI']))
- {
- helper::setStatus(404);
- helper::end();
- }
- if($this->config->requestType == 'PATH_INFO' or $this->config->requestType == 'PATH_INFO2')
- {
- $this->parsePathInfo();
- $this->setRouteByPathInfo();
- }
- elseif($this->config->requestType == 'GET')
- {
- $this->parseGET();
- $this->setRouteByGET();
- }
- else
- {
- $this->triggerError("The request type {$this->config->requestType} not supported", __FILE__, __LINE__, true);
- }
- }
- /**
- * PATH_INFO方式解析,获取$uri和$viewType。
- * Parse PATH_INFO, get the $uri and $viewType.
- *
- * @access public
- * @return void
- */
- public function parsePathInfo()
- {
- $pathInfo = $this->getPathInfo();
- if(!empty($pathInfo))
- {
- $dotPos = strrpos($pathInfo, '.');
- if($dotPos)
- {
- $this->uri = substr($pathInfo, 0, $dotPos);
- $this->viewType = substr($pathInfo, $dotPos + 1);
- if(strpos((string) $this->config->views, ',' . $this->viewType . ',') === false)
- {
- $this->viewType = $this->config->default->view;
- }
- }
- else
- {
- $this->uri = $pathInfo;
- $this->viewType = $this->config->default->view;
- }
- }
- else
- {
- $this->viewType = $this->config->default->view;
- }
- }
- /**
- * 从$_SERVER或者$_ENV全局变量根据pathinfo变量名获取$PATH_INFO值。
- * PATH_INFO的变量名几乎都是'PATH_INFO',但也有可能是ORIG_PATH_INFO。
- *
- * Get $PATH_INFO from $_SERVER or $_ENV by the pathinfo var name.
- * Mostly, the var name of PATH_INFO is PATH_INFO, but may be ORIG_PATH_INFO.
- *
- * @access public
- * @return string the PATH_INFO
- */
- public function getPathInfo()
- {
- if(isset($_SERVER['PATH_INFO']))
- {
- $value = $_SERVER['PATH_INFO'];
- }
- elseif(isset($_SERVER['ORIG_PATH_INFO']))
- {
- $value = $_SERVER['ORIG_PATH_INFO'];
- }
- elseif(isset($this->uri))
- {
- $value = $this->uri;
- $subpath = str_replace($_SERVER['DOCUMENT_ROOT'], '', dirname((string) $_SERVER['SCRIPT_FILENAME']));
- if($subpath != '/') $subpath = '/' . $subpath;
- if($subpath != '' and $subpath != '/' and strncmp($value, $subpath, strlen($subpath)) === 0) $value = substr($value, strlen($subpath));
- }
- else
- {
- $value = getenv('PATH_INFO');
- if(empty($value)) $value = getenv('ORIG_PATH_INFO');
- }
- if(strpos((string) $value, (string) $_SERVER['SCRIPT_NAME']) !== false) $value = str_replace($_SERVER['SCRIPT_NAME'], '', (string) $value);
- if(strpos((string) $value, '?') === false) return trim((string) $value, '/');
- $value = parse_url((string) $value);
- $pathInfo = trim((string) zget($value, 'path', ''), '/');
- if(trim($pathInfo, '/') == trim((string) $this->config->webRoot, '/')) $pathInfo = '';
- return $pathInfo;
- }
- /**
- * GET请求方式解析,获取$uri和$viewType。
- * Parse GET, get $uri and $viewType.
- *
- * @access public
- * @return void
- */
- public function parseGET()
- {
- if(isset($_GET[$this->config->viewVar]))
- {
- $this->viewType = $_GET[$this->config->viewVar];
- if(strpos((string) $this->config->views, ',' . $this->viewType . ',') === false) $this->viewType = $this->config->default->view;
- }
- else
- {
- $this->viewType = $this->config->default->view;
- }
- $this->uri = $_SERVER['REQUEST_URI'];
- }
- /**
- * 获取$URL。
- * Get the $URL.
- *
- * @param bool $full The URI contains the webRoot if $full is true else only the URI will be return.
- * @access public
- * @return string
- */
- public function getURI($full = false)
- {
- if($full and $this->config->requestType == 'PATH_INFO')
- {
- if($this->uri) return $this->config->webRoot . $this->uri . '.' . $this->viewType;
- return $this->config->webRoot;
- }
- return $this->uri;
- }
- /**
- * 获取$viewType变量。
- * Get the $viewType var.
- *
- * @access public
- * @return string
- */
- public function getViewType()
- {
- return $this->viewType;
- }
- //-------------------- 模块及扩展设置(Module and extension) --------------------//
- /**
- * 加载common模块。
- *
- * common模块比较特别,它会执行几乎每次请求都需要执行的操作,例如:
- * 打开session,检查权限等等。
- * 加载完$lang, $config, $dbh后,需要在入口文件(www/index.php)中手动调用该方法。
- *
- * Load the common module
- *
- * The common module is a special module, which can be used to do some common things. For example:
- * start session, check privilege and so on.
- * This method should called manually in the router file(www/index.php) after the $lang, $config, $dbh loaded.
- *
- * @access public
- * @return commonModel|extcommonModel|object|bool the common model object or false if not exits.
- */
- public function loadCommon()
- {
- $this->setModuleName('common');
- $commonModelFile = $this->setModelFile('common');
- if(!file_exists($commonModelFile)) return false;
- helper::import($commonModelFile);
- if($this->config->framework->extensionLevel == 0 and class_exists('commonModel'))
- {
- $common = new commonModel();
- }
- elseif($this->config->framework->extensionLevel > 0 and class_exists('extCommonModel'))
- {
- $common = new extCommonModel();
- }
- elseif(class_exists('commonModel'))
- {
- $common = new commonModel();
- }
- else
- {
- return false;
- }
- $this->loadLang('company');
- $common->setUserConfig();
- $this->setDebug();
- return $common;
- }
- /**
- * 设置要被调用的模块名。
- * Set the name of the module to be called.
- *
- * @param string $moduleName the module name
- * @access public
- * @return void
- */
- public function setModuleName($moduleName = '')
- {
- if($this->checkModuleName($moduleName)) $this->moduleName = strtolower($moduleName);
- }
- /**
- * 设置要被调用的控制器文件。
- * Set the control file of the module to be called.
- *
- * @param bool $exitIfNone 没有找到该控制器文件的情况:如果该参数为true,则终止程序;如果为false,则打印错误日志
- * The control file was not found: if the parameter is true, the program is terminated;
- * if false, the error log is printed.
- * @access public
- * @return bool
- */
- public function setControlFile($exitIfNone = true)
- {
- $this->controlFile = $this->getModulePath() . 'control.php';
- if(file_exists($this->controlFile)) return true;
- if(!$this->tryResetVision()) $this->triggerError("the control file $this->controlFile not found.", __FILE__, __LINE__, $exitIfNone);
- }
- /**
- * 设置要被调用的方法名。
- * Set the name of the method calling.
- *
- * @param string $methodName
- * @access public
- * @return void
- */
- public function setMethodName($methodName = '')
- {
- if($this->checkMethodName($methodName)) $this->methodName = strtolower($methodName);
- }
- /**
- * 引入 control 文件。
- * Import control file.
- *
- * @access public
- * @return string
- */
- public function importControlFile()
- {
- $moduleName = $this->moduleName;
- /**
- * 引入该模块的control文件。
- * Include the control file of the module.
- */
- $isExt = $this->setActionExtFile();
- if($isExt)
- {
- $controlFile = $this->controlFile;
- spl_autoload_register(function($class) use ($moduleName, $controlFile)
- {
- if($class == $moduleName) helper::import($controlFile);
- });
- }
- $file2Included = $isExt ? $this->extActionFile : $this->controlFile;
- chdir(dirname($file2Included));
- helper::import($file2Included);
- return $file2Included;
- }
- /**
- * 获取要被调用的方法的参数和类型。
- * Get the default valve and param type of the method calling.
- *
- * @access public
- * @return array
- */
- public function getDefaultParams()
- {
- $appName = $this->appName;
- $moduleName = $this->moduleName;
- $methodName = $this->methodName;
- $file2Included = $this->importControlFile();
- $className = class_exists("my$moduleName") ? "my$moduleName" : $moduleName;
- if(!class_exists($className)) $this->triggerError("the control $className not found", __FILE__, __LINE__, true);
- /**
- * 创建control类的实例。
- * Create an instance of the control.
- */
- $module = new $className();
- if(!method_exists($module, $methodName)) $this->triggerError("the module $moduleName has no $methodName method", __FILE__, __LINE__, true);
- $this->control = $module;
- /* Check file is encode by ioncube. */
- $isEncrypted = false;
- if(preg_match('/extension\\' . DS . '(custom|xuan|biz|max|ipd|or)\\' . DS . '/', $file2Included))
- {
- $fp = fopen($file2Included, 'r');
- $line1 = fgets($fp);
- fclose($fp);
- if(strpos($line1, '<?php //') === 0) $isEncrypted = true;
- }
- /* include default value for module. */
- $defaultValueFiles = glob($this->getTmpRoot() . "defaultvalue/*.php");
- if($defaultValueFiles) foreach($defaultValueFiles as $file) include $file;
- /* include default type for module. */
- $defaultTypeFiles = glob($this->getTmpRoot() . "defaulttype/*.php");
- if($defaultTypeFiles) foreach($defaultTypeFiles as $typeFile) include $typeFile;
- /**
- * 使用反射机制获取函数参数的默认值。
- * Get the default settings of the method to be called using the reflecting.
- */
- $defaultParams = array();
- $methodReflect = new reflectionMethod($className, $methodName);
- foreach($methodReflect->getParameters() as $param)
- {
- $name = $param->getName();
- $default = '_NOT_SET';
- if(isset($paramDefaultValue[$appName][$className][$methodName][$name]))
- {
- $default = $paramDefaultValue[$appName][$className][$methodName][$name];
- }
- elseif(isset($paramDefaultValue[$className][$methodName][$name]))
- {
- $default = $paramDefaultValue[$className][$methodName][$name];
- }
- elseif(!$isEncrypted && $param->isDefaultValueAvailable())
- {
- $default = $param->getDefaultValue();
- }
- $type = 'string';
- if(isset($paramDefaultType[$appName][$className][$methodName][$name]))
- {
- $type = $paramDefaultType[$appName][$className][$methodName][$name];
- }
- elseif(isset($paramDefaultType[$className][$methodName][$name]))
- {
- $type = $paramDefaultType[$className][$methodName][$name];
- }
- elseif(!$isEncrypted && method_exists($param, 'hasType') && $param->hasType())
- {
- $paramType = $param->getType();
- if(method_exists($paramType, 'getName')) $type = $paramType->getName();
- }
- $type = strpos($type, '|') ? 'string' : $type;
- $defaultParams[$name] = array('default' => $default, 'type' => $type);
- }
- return $defaultParams;
- }
- /**
- * 设置要被调用方法的参数。
- * Set the params of method calling.
- *
- * @access public
- * @return void
- */
- public function setParams()
- {
- $defaultParams = $this->getDefaultParams();
- /**
- * 根据PATH_INFO或者GET方式设置请求的参数。
- * Set params according PATH_INFO or GET.
- */
- if($this->config->requestType != 'GET')
- {
- $this->setParamsByPathInfo($defaultParams);
- }
- else
- {
- $this->setParamsByGET($defaultParams);
- }
- if ('cli' === PHP_SAPI)
- {
- if ($this->params)
- {
- $this->params = array_merge($defaultParams, $this->params);
- }
- else
- {
- $this->params = $defaultParams;
- }
- }
- else
- {
- if($this->config->framework->filterParam == 2)
- {
- $_GET = validater::filterParam($_GET, 'get');
- $_COOKIE = validater::filterParam($_COOKIE, 'cookie');
- }
- }
- $this->rawParams = $this->params;
- return true;
- }
- /**
- * 获取一个模块的路径。
- * Get the path of one module.
- *
- * @param string $appName the app name
- * @param string $moduleName the module name
- * @access public
- * @return string the module path
- */
- public function getModulePath($appName = '', $moduleName = '')
- {
- if($moduleName == '') $moduleName = $this->moduleName;
- $moduleName = strtolower($moduleName);
- if($this->checkModuleName($moduleName))
- {
- $modulePath = $this->getExtensionRoot() . 'saas' . DS . $moduleName . DS;
- if(is_dir($modulePath) and (file_exists($modulePath . 'control.php') or file_exists($modulePath . 'model.php'))) return $modulePath;
- /* 1. 尝试在定制开发中寻找。 Finally, try to find the module in the custom dir. */
- $modulePath = $this->getExtensionRoot() . 'custom' . DS . $moduleName . DS;
- if(is_dir($modulePath) and (file_exists($modulePath . 'control.php') or file_exists($modulePath . 'model.php'))) return $modulePath;
- /* 2. 如果设置过vision,尝试在vision中查找。 If vision is set, try to find the module in the vision. */
- if($this->config->vision != 'rnd')
- {
- $modulePath = $this->getExtensionRoot() . $this->config->vision . DS . $moduleName . DS;
- if(is_dir($modulePath) and (file_exists($modulePath . 'control.php') or file_exists($modulePath . 'model.php'))) return $modulePath;
- }
- /* 3. 尝试查找商业版本是否有此模块。 Try to find the module in other editon. */
- if($this->config->edition != 'open')
- {
- $modulePath = $this->getExtensionRoot() . $this->config->edition . DS . $moduleName . DS;
- if(is_dir($modulePath) and (file_exists($modulePath . 'control.php') or file_exists($modulePath . 'model.php'))) return $modulePath;
- }
- /* 4. 尝试查找喧喧是否有此模块。 Try to find the module in xuan. */
- $modulePath = $this->getExtensionRoot() . 'xuan' . DS . $moduleName . DS;
- if(is_dir($modulePath) and (file_exists($modulePath . 'control.php') or file_exists($modulePath . 'model.php'))) return $modulePath;
- /* 5. 使用通用版本里的模块。 If module is in the open edition, use it. */
- return $this->getModuleRoot($appName) . $moduleName . DS;
- }
- }
- /**
- * 获取一个模块的扩展路径。 Get extension path of one module.
- *
- * If the extensionLevel == 0, return empty array.
- * If the extensionLevel == 1, return the common extension directory.
- * If the extensionLevel == 2, return the common and site extension directories.
- *
- * @param string $appName the app name
- * @param string $moduleName the module name
- * @param string $ext the extension type, can be control|model|view|lang|config|zen|tao
- * @access public
- * @return array the extension path.
- */
- public function getModuleExtPath($moduleName, $ext)
- {
- $saasExtPath = $this->getExtensionRoot() . 'saas' . DS . $moduleName . DS . 'ext' . DS . $ext . DS;
- /* 检查失败或者extensionLevel为0,直接返回空。If check failed or extensionLevel == 0, return empty array. */
- if(!$this->checkModuleName($moduleName) or $this->config->framework->extensionLevel == 0) return array('saas' => $saasExtPath);
- $paths = array();
- /* When extensionLevel == 1. */
- $paths['common'] = $this->config->edition != 'open' ? $this->getExtensionRoot() . $this->config->edition . DS . $moduleName . DS . 'ext' . DS . $ext . DS : '';
- $paths['xuan'] = $this->getExtensionRoot() . 'xuan' . DS . $moduleName . DS . 'ext' . DS . $ext . DS;
- $paths['vision'] = $this->config->vision == 'rnd' ? '' : $this->basePath . 'extension' . DS . $this->config->vision . DS . $moduleName . DS . 'ext' . DS . $ext . DS;
- $paths['custom'] = $this->getExtensionRoot() . 'custom' . DS . $moduleName . DS . 'ext' . DS . $ext . DS;
- if($this->config->framework->extensionLevel == 1)
- {
- $paths['saas'] = $saasExtPath;
- return $paths;
- }
- /* When extensionLevel == 2. */
- $paths['site'] = empty($this->siteCode) ? '' : $this->getExtensionRoot() . $this->config->edition . DS . $moduleName . DS . 'ext' . DS . '_' . $this->siteCode . DS . $ext . DS;
- $paths['saas'] = $saasExtPath;
- return $paths;
- }
- /**
- * 检查模块中某一个变量必须为英文字母和数字组合。Check module a variable must be ascii.
- *
- * @param string $var
- * @param bool $exit
- * @access public
- * @return bool
- */
- public function checkModuleName($var, $exit = true)
- {
- global $filter;
- static $checkedModule = array();
- if(!isset($checkedModule[$var]))
- {
- $rule = $filter->default->moduleName;
- $result = validater::checkByRule($var, $rule);
- $checkedModule[$var] = $result;
- }
- if($checkedModule[$var]) return true;
- if(!$exit) return false;
- if(!$var) return false;
- $this->triggerError("'$var' illegal. ", __FILE__, __LINE__, true);
- }
- /**
- * 检查方法中某一个变量必须为英文字母和数字组合。Check method a variable must be ascii.
- *
- * @param string $var
- * @param bool $exit
- * @access public
- * @return bool
- */
- public function checkMethodName($var, $exit = true)
- {
- global $filter;
- $rule = $filter->default->methodName;
- if($this->config->framework->filterParam == 2 and isset($filter->{$this->moduleName}->methodName)) $rule = $filter->{$this->moduleName}->methodName;
- if(validater::checkByRule($var, $rule)) return true;
- if(!$exit) return false;
- $this->triggerError("'$var' illegal. ", __FILE__, __LINE__, $exit = true);
- }
- /**
- * 设置Action的扩展文件。 Set the action extension file.
- *
- * @access public
- * @return bool
- */
- public function setActionExtFile()
- {
- $moduleExtPaths = $this->getModuleExtPath($this->moduleName, 'control');
- /* 如果扩展目录为空,不包含任何扩展文件。If there's no ext paths return false.*/
- if(empty($moduleExtPaths)) return false;
- if(!empty($moduleExtPaths['saas']))
- {
- $this->extActionFile = $moduleExtPaths['saas'] . $this->methodName . '.php';
- if(file_exists($this->extActionFile)) return true;
- }
- /* 1. 如果extensionLevel == 2,且扩展文件存在,返回该站点扩展文件。 If extensionLevel == 2 and site extensionFile exists, return it. */
- if($this->config->framework->extensionLevel == 2 and !empty($moduleExtPaths['site']))
- {
- $this->extActionFile = $moduleExtPaths['site'] . $this->methodName . '.php';
- if(file_exists($this->extActionFile)) return true;
- }
- /* 2. 尝试在定制开发目录寻找扩展文件。Then try to find the custom extension file. */
- $this->extActionFile = $moduleExtPaths['custom'] . $this->methodName . '.php';
- if(file_exists($this->extActionFile)) return true;
- /* 3. 如果设置过vision,尝试在vision中查找扩展文件。If vision is set, try to find the vision extension file. */
- if($moduleExtPaths['vision']) $this->extActionFile = $moduleExtPaths['vision'] . $this->methodName . '.php';
- if(file_exists($this->extActionFile)) return true;
- /* 4. 在喧喧目录中查找扩展文件。Then try to find the xuan extension file. */
- if($moduleExtPaths['xuan']) $this->extActionFile = $moduleExtPaths['xuan'] . $this->methodName . '.php';
- if(file_exists($this->extActionFile)) return true;
- /* 5. 最后尝试寻找公共扩展文件。Finally, try to find the common extension file. */
- $this->extActionFile = $moduleExtPaths['common'] . $this->methodName . '.php';
- if(empty($moduleExtPaths['common'])) return false;
- return file_exists($this->extActionFile);
- }
- /**
- * Check for API extend.
- *
- * @access public
- * @return bool
- */
- public function checkAPIFile()
- {
- $moduleExtPaths = $this->getModuleExtPath($this->moduleName, 'control');
- /* 如果扩展目录为空,不包含任何扩展文件。If there's no ext paths return false.*/
- if(empty($moduleExtPaths)) return false;
- /* 如果extensionLevel == 2,且扩展文件存在,返回该站点扩展文件。If extensionLevel == 2 and site extensionFile exists, return it. */
- if($this->config->framework->extensionLevel == 2 and !empty($moduleExtPaths['site']))
- {
- $locateFile = $moduleExtPaths['site'] . $this->methodName . '.302';
- if(file_exists($locateFile)) $this->sendAPI($locateFile);
- $requestFile = $moduleExtPaths['site'] . $this->methodName . '.api';
- if(file_exists($requestFile)) $this->sendAPI($requestFile);
- }
- /* 然后再尝试寻找公共扩展文件。Then try to find the common extension file. */
- $locateFile = $moduleExtPaths['common'] . $this->methodName . '.302';
- if(file_exists($locateFile)) $this->sendAPI($locateFile);
- $requestFile = $moduleExtPaths['common'] . $this->methodName . '.api';
- if(file_exists($requestFile)) $this->sendAPI($requestFile);
- return false;
- }
- /**
- * 设置一个模块的model文件,如果存在model扩展,一起合并。
- * Set the model file of one module. If there's an extension file, merge it with the main model file.
- *
- * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name.
- * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name.
- * @access public
- * @return string the model file
- */
- public function setModelFile($moduleName, $appName = '')
- {
- return $this->setTargetFile($moduleName, $appName);
- }
- /**
- * 设置一个模块的target文件,如果存在target扩展,一起合并。
- * Set the target file of one module. If there's an extension file, merge it with the main target file.
- *
- * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name.
- * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name.
- * @param string $class 对象的类型,可选值 target、zen、tao,默认为 target。The type of the object, optional values target, zen, tao, the default is target.
- * @access public
- * @return string the target file
- */
- public function setTargetFile($moduleName, $appName = '', $class = 'model')
- {
- if($appName == '') $appName = $this->getAppName();
- /* 设置主target文件。 Set the main target file. */
- $mainTargetFile = $this->getModulePath($appName, $moduleName) . "{$class}.php";
- if($this->config->framework->extensionLevel == 0) return $mainTargetFile;
- /* 计算扩展的文件和hook文件。Compute the extension files and hook files. */
- $hookFiles = array();
- $extFiles = array();
- $apiFiles = array();
- $siteExtended = false;
- $targetExtPaths = $this->getModuleExtPath($moduleName, $class);
- foreach($targetExtPaths as $extType => $targetExtPath)
- {
- if(empty($targetExtPath)) continue;
- $tmpHookFiles = helper::ls($targetExtPath . 'hook/', '.php');
- $tmpExtFiles = helper::ls($targetExtPath, '.php');
- $tmpAPIFiles = helper::ls($targetExtPath, '.api');
- $hookFiles = array_merge($hookFiles, $tmpHookFiles);
- $extFiles = array_merge($extFiles, $tmpExtFiles);
- $apiFiles = array_merge($apiFiles, $tmpAPIFiles);
- if($extType == 'site' and (!empty($tmpHookFiles) or !empty($tmpExtFiles) or !empty($tmpAPIFiles))) $siteExtended = true;
- }
- /* 如果没有扩展文件,返回主文件。 If no extension or hook files, return the main file directly. */
- if(empty($extFiles) and empty($hookFiles) and empty($apiFiles)) return $mainTargetFile;
- /* 计算合并之后的targetFile路径。Compute the merged target file path. */
- $runMode = PHP_SAPI == 'cli' ? '_cli' : '';
- $extTargetPrefix = $this->config->edition . $runMode . DS . $this->config->vision . DS;
- if($siteExtended and !empty($this->siteCode)) $extTargetPrefix .= $this->siteCode[0] . DS . $this->siteCode;
- $mergedTargetDir = $this->getTmpRoot() . $class . DS . $extTargetPrefix;
- $mergedTargetFile = $mergedTargetDir . $moduleName . '.php';
- if(!is_dir($mergedTargetDir))
- {
- $made = mkdir($mergedTargetDir, 0755, true);
- if(!$made && !empty($this->config->debug)) helper::end("ERROR: Can NOT create required directory '{$mergedTargetDir}', please create it manually with correct permission.");
- }
- /* 判断生成的缓存文件是否需要更新。 Judge whether the merged target file needed update or not. */
- if(!$this->needTargetFileUpdate($mergedTargetFile, $extFiles, $hookFiles, $apiFiles, $targetExtPaths, $mainTargetFile)) return $mergedTargetFile;
- /* 合并扩展和hook文件。Merge the extension and hook files. */
- $targetLines = $this->mergeTargetExtFiles($moduleName, $extFiles, $mergedTargetDir, $class);
- $this->mergeTargetHookFiles($moduleName, $mainTargetFile, $targetLines, $hookFiles, $mergedTargetDir, $mergedTargetFile, $apiFiles, $class);
- return $mergedTargetFile;
- }
- /**
- * 检查合并之后的target文件是否需要更新。Check whether the merged target file need update or not.
- *
- * @param string $mergedTargetFile
- * @param array $extFiles
- * @param array $hookFiles
- * @param array $apiFiles
- * @param array $targetExtPaths
- * @param string $mainTargetFile
- * @access public
- * @return bool
- */
- public function needTargetFileUpdate($mergedTargetFile, $extFiles, $hookFiles, $apiFiles, $targetExtPaths, $mainTargetFile)
- {
- $lastTime = file_exists($mergedTargetFile) ? filemtime($mergedTargetFile) : 0;
- foreach($extFiles as $extFile) if(filemtime($extFile) > $lastTime) return true;
- foreach($hookFiles as $hookFile) if(filemtime($hookFile) > $lastTime) return true;
- foreach($apiFiles as $apiFile) if(filemtime($apiFile) > $lastTime) return true;
- $targetExtPath = $targetExtPaths['common'];
- $targetHookPath = $targetExtPaths['common'] . 'hook/';
- if(is_dir($targetExtPath ) and filemtime($targetExtPath) > $lastTime) return true;
- if(is_dir($targetHookPath) and filemtime($targetHookPath) > $lastTime) return true;
- if(!empty($targetExtPaths['site']))
- {
- $targetExtPath = $targetExtPaths['site'];
- $targetHookPath = $targetExtPaths['site'] . 'hook/';
- if(is_dir($targetExtPath ) and filemtime($targetExtPath) > $lastTime) return true;
- if(is_dir($targetHookPath) and filemtime($targetHookPath) > $lastTime) return true;
- }
- if(filemtime($mainTargetFile) > $lastTime) return true;
- return false;
- }
- /**
- * 将target的扩展文件合并在一起。Merge target ext files.
- *
- * @param string $moduleName
- * @param array $extFiles
- * @param string $mergedTargetDir
- * @param string $class model | zen | tao
- * @access public
- * @return string
- */
- public function mergeTargetExtFiles($moduleName, $extFiles, $mergedTargetDir, $class = 'model')
- {
- /* 设置类名。Set the class names. */
- $targetClass = $moduleName . ucfirst($class);
- $tmpTargetClass = "tmpExt$targetClass";
- /* 开始拼装代码。Prepare the codes. */
- $targetLines = "<?php\n";
- $targetLines .= "global \$app;\n";
- $targetLines .= "helper::import(\$app->getModulePath('', '$moduleName') . " . "'$class.php');\n";
- $targetLines .= "class $tmpTargetClass extends $targetClass \n{\n";
- /* 将扩展文件的代码合并到代码中。Cycle all the extension files and merge them into target lines. */
- $extTargets = array();
- foreach($extFiles as $extFile) $extTargets[basename((string) $extFile)] = $extFile;
- foreach($extTargets as $extTarget) $targetLines .= static::removePHPTAG($extTarget);
- /* 做个标记,方便后面替换代码使用。Make a mark for replacing codes. */
- $replaceMark = '//**//';
- $targetLines .= "\n$replaceMark\n}";
- /* 生成一个临时的target扩展文件,并加载,用于后续的hook文件加载使用。Create a tmp merged target file and import it for merge hook codes using. */
- $tmpTargetFile = $mergedTargetDir . "tmp$moduleName.php";
- if(file_put_contents($tmpTargetFile, $targetLines))
- {
- if(!class_exists($tmpTargetClass)) include $tmpTargetFile;
- return $targetLines;
- }
- $this->triggerError("ERROR: $tmpTargetFile not writable.", __FILE__, __LINE__, true);
- }
- /**
- * 合并target的hook脚本。Merge hook files for a target.
- *
- * @param string $moduleName
- * @param string $mainTargetFile
- * @param string $targetLines
- * @param array $hookFiles
- * @param string $mergedTargetDir
- * @param string $mergedTargetFile
- * @param array $apiFiles
- * @param string $class model | zen | tao
- * @access public
- * @return void
- */
- public function mergeTargetHookFiles($moduleName, $mainTargetFile, $targetLines, $hookFiles, $mergedTargetDir, $mergedTargetFile, $apiFiles, $class = 'model')
- {
- /* 定义相关变量。Init vars. */
- $targetClass = $moduleName . ucfirst($class);
- $extTargetClass = 'ext' . $targetClass;
- $tmpTargetClass = 'tmpExt' . $targetClass;
- $tmpTargetFile = $mergedTargetDir . "tmp$moduleName.php";
- $replaceMark = '//**//';
- /* 读取hook文件。Get hook codes need to merge. */
- $hookCodes = array();
- foreach($apiFiles as $apiFile)
- {
- /* 通过文件名获得其对应的方法名。Get methods according it's filename. */
- $fileName = baseName((string) $apiFile);
- [$method] = explode('.', $fileName);
- $url = static::extractAPIURL($apiFile);
- if($url) $hookCodes[$method][] = "return helper::requestAPI('$url');";
- }
- foreach($hookFiles as $hookFile)
- {
- /* 通过文件名获得其对应的方法名。Get methods according it's filename. */
- $fileName = baseName((string) $hookFile);
- [$method] = explode('.', $fileName);
- $hookCodes[$method][] = static::removePHPTAG($hookFile);
- }
- /* 合并Hook文件。Cycle the hook methods and merge hook codes. */
- $hookedMethods = array_keys($hookCodes);
- $mainTargetCodes = file($mainTargetFile);
- $mergedTargetCodes = file($tmpTargetFile);
- /* 如果已经合并,不需要再合并了。 If merged by other thread, return directly. */
- if(!$mergedTargetCodes) return;
- foreach($hookedMethods as $method)
- {
- /* 通过反射获得hook脚本对应的方法所在的文件和起止行数。Reflection the hooked method to get it's defined position. */
- if(!method_exists($tmpTargetClass, $method)) continue;
- $methodRelfection = new reflectionMethod($tmpTargetClass, $method);
- $definedFile = $methodRelfection->getFileName();
- $startLine = $methodRelfection->getStartLine();
- $endLine = $methodRelfection->getEndLine();
- /* 将Hook脚本和老的代码合并在一起,并替换原来的定义。Merge hook codes with old codes and replace back. */
- $oldCodes = $definedFile == $tmpTargetFile ? $mergedTargetCodes : $mainTargetCodes;
- $oldCodes = implode("", array_slice($oldCodes, $startLine - 1, $endLine - $startLine + 1));
- $openBrace = strpos($oldCodes, '{');
- $newCodes = substr($oldCodes, 0, $openBrace + 1) . "\n" . implode("\n", $hookCodes[$method]) . substr($oldCodes, $openBrace + 1);
- if($definedFile == $tmpTargetFile) $targetLines = str_replace($oldCodes, $newCodes, $targetLines);
- if($definedFile != $tmpTargetFile) $targetLines = str_replace($replaceMark, $newCodes . "\n$replaceMark", $targetLines);
- }
- /* 保存最终的Target文件。Save the last merged target file. */
- $targetLines = str_replace($tmpTargetClass, $extTargetClass, $targetLines);
- file_put_contents($mergedTargetFile, $targetLines);
- unlink($tmpTargetFile);
- }
- /**
- * Remove tags of PHP
- *
- * @param string $fileName
- * @static
- * @access public
- * @return string
- */
- public static function removePHPTAG($fileName)
- {
- $code = trim(file_get_contents($fileName));
- if(strncmp($code, '<?php', strlen('<?php')) === 0) $code = ltrim($code, '<?php');
- $code = ltrim($code);
- if(strncmp($code, 'declare(strict_types=1);', strlen('declare(strict_types=1);')) === 0) $code = ltrim($code, 'declare(strict_types=1);');
- if(strrpos($code, '?' . '>') !== false) $code = rtrim($code, '?' . '>');
- return trim($code);
- }
- /**
- * Extract API url from api file.
- *
- * @param string $fileName
- * @static
- * @access public
- * @return string
- */
- public static function extractAPIURL($fileName)
- {
- global $config;
- $url = '';
- $lines = file($fileName);
- foreach($lines as $line)
- {
- $line = trim((string) $line);
- if(empty($line)) continue;
- if(preg_match('/^https?\:\/\//', $line))
- {
- $url = $line;
- break;
- }
- }
- if(empty($url)) return '';
- return $url;
- }
- /**
- * Send API.
- *
- * @param string $apiFile
- * @access public
- * @return void
- */
- public function sendAPI($apiFile)
- {
- $css = null;
- $js = null;
- $extension = substr($apiFile, strrpos($apiFile, '.') + 1);
- if($extension != '302' and $extension != 'api') return false;
- $lines = file($apiFile);
- $url = '';
- foreach($lines as $line)
- {
- $line = trim((string) $line);
- if(empty($line)) continue;
- if(preg_match('/^https?\:\/\//', $line))
- {
- $url = $line;
- break;
- }
- }
- if(empty($url)) return false;
- $url .= (strpos($url, '?') !== false ? '&' : '?') . $this->config->sessionVar . '=' . session_id() . '&account=' . $_SESSION['user']->account;
- if($extension == '302')
- {
- helper::header('location', $url);
- helper::end();
- }
- if($extension == 'api')
- {
- $response = common::http($url);
- $headFile = $this->moduleRoot . 'common/view/header.html.php';
- $footFile = $this->moduleRoot . 'common/view/footer.html.php';
- $obLevel = ob_get_level();
- for($i = 0; $i < $obLevel; $i++) ob_end_clean();
- $viewFiles = $this->control->setViewFile($this->moduleName, $this->methodName);
- if($css) $this->control->view->pageCSS = $css;
- if($js) $this->control->view->pageJS = $js;
- $output = '';
- $output .= $this->control->printViewFile($headFile);
- $output .= $response;
- if(isset($viewFiles['hookFiles'])) foreach($viewFiles['hookFiles'] as $hookFile) $output .= $this->control->printViewFile($hookFile);
- $output .= $this->control->printViewFile($footFile);
- helper::end($output);
- }
- }
- //-------------------- 路由相关方法(Routing related methods) --------------------//
- /**
- * 设置路由(PATH_INFO 方式):
- * 1.设置模块名;
- * 2.设置方法名;
- * 3.设置控制器文件。
- *
- * Set the route according to PATH_INFO.
- * 1. set the module name.
- * 2. set the method name.
- * 3. set the control file.
- *
- * @access public
- * @return void
- */
- public function setRouteByPathInfo()
- {
- if(!empty($this->uri))
- {
- /*
- * 根据$requestFix分割符,分割网址。
- * There's the request separator, split the URI by it.
- **/
- if(strpos($this->uri, (string) $this->config->requestFix) !== false)
- {
- $items = explode($this->config->requestFix, $this->uri);
- $this->setModuleName($items[0]);
- $this->setMethodName($items[1]);
- }
- /*
- * 如果网址中没有分隔符,使用默认的方法。
- * No request separator, use the default method name.
- **/
- else
- {
- $this->setModuleName($this->uri);
- $this->setMethodName($this->config->default->method);
- }
- }
- else
- {
- $this->setModuleName($this->config->default->module); // 使用默认模块 use the default module.
- $this->setMethodName($this->config->default->method); // 使用默认方法 use the default method.
- }
- $this->setControlFile();
- }
- /**
- * 设置路由(GET 方式):
- * 1.设置模块名;
- * 2.设置方法名;
- * 3.设置控制器文件。
- *
- * Set the route according to GET.
- * 1. set the module name.
- * 2. set the method name.
- * 3. set the control file.
- *
- * @access public
- * @return void
- */
- public function setRouteByGET()
- {
- $moduleName = isset($_GET[$this->config->moduleVar]) ? strtolower((string) $_GET[$this->config->moduleVar]) : $this->config->default->module;
- $methodName = isset($_GET[$this->config->methodVar]) ? strtolower((string) $_GET[$this->config->methodVar]) : $this->config->default->method;
- $this->setModuleName($moduleName);
- $this->setMethodName($methodName);
- $this->setControlFile();
- }
- /**
- * 加载一个模块:
- * 1. 引入控制器文件或扩展的方法文件;
- * 2. 创建control对象;
- * 3. 解析url,得到请求的参数;
- * 4. 使用call_user_function_array调用相应的方法。
- *
- * Load a module.
- * 1. include the control file or the extension action file.
- * 2. create the control object.
- * 3. set the params passed in through url.
- * 4. call the method by call_user_function_array
- *
- * @access public
- * @return bool|object if the module object of die.
- */
- public function loadModule()
- {
- if(is_null($this->params) and !$this->setParams())
- {
- $this->outputXhprof();
- return false;
- }
- /* 调用该方法 Call the method. */
- $module = $this->control;
- $method = $this->methodName ? $this->methodName : $this->config->default->method;
- call_user_func_array(array($module, $method), $this->params);
- $this->checkAPIFile();
- $this->outputXhprof();
- return $module;
- }
- /**
- * 加载指定模块下的某种对象。
- * Load the target object of one module.
- *
- * @param string $moduleName 模块名,如果为空,使用当前模块。The module name, if empty, use current module's name.
- * @param string $appName 应用名,如果为空,使用当前应用。The app name, if empty, use current app's name.
- * @param string $class 对象的类型,可选值 model、zen、tao,默认为 model。The type of the object, optional values model, zen, tao, the default is model.
- * @access public
- * @return object|bool 如果没有model文件,返回false,否则返回model对象。If no model file, return false, else return the model object.
- */
- public function loadTarget($moduleName = '', $appName = '', $class = 'model')
- {
- if(empty($moduleName)) $moduleName = $this->moduleName;
- if(empty($appName)) $appName = $this->appName;
- if(isset(self::$loadedTargets[$class][$appName][$moduleName])) return self::$loadedTargets[$class][$appName][$moduleName];
- $targetFile = $this->setTargetFile($moduleName, $appName, $class);
- /**
- * 如果没有target文件,返回false。
- * If no target file, return false.
- */
- if(!helper::import($targetFile)) return false;
- /**
- * 如果没有扩展文件,target类名是$moduleName + $class,如果有扩展,还需要增加ext前缀。
- * If no extension file, target class name is $moduleName + $class, else with 'ext' as the prefix.
- */
- $targetClass = class_exists('ext' . $appName . $moduleName. $class) ? 'ext' . $appName . $moduleName . $class : $appName . $moduleName . $class;
- if(!class_exists($targetClass))
- {
- $targetClass = class_exists('ext' . $moduleName. $class) ? 'ext' . $moduleName . $class : $moduleName . $class;
- if(!class_exists($targetClass)) $this->triggerError(" The $class $targetClass not found", __FILE__, __LINE__, true);
- }
- /**
- * 因为zen继承自control,tao继承自model,构造函数里会调用loadTarget方法,赋默认值值防止递归调用。
- */
- if($class == 'zen' || $class == 'tao') self::$loadedTargets[$class][$appName][$moduleName] = false;
- /**
- * 初始化target 对象并返回。
- * Init the target object and return it.
- */
- $target = new $targetClass($appName);
- self::$loadedTargets[$class][$appName][$moduleName] = $target;
- return $target;
- }
- /**
- * 设置请求的参数(PATH_INFO 方式)。
- * Set the params by PATH_INFO.
- *
- * @param array $defaultParams the default settings of the params.
- * @param string $type
- * @access public
- * @return void
- */
- public function setParamsByPathInfo($defaultParams = array(), $type = '')
- {
- $params = array();
- if($type != 'fetch')
- {
- /* 分割URI。 Spit the URI. */
- $items = explode($this->config->requestFix, (string)$this->uri);
- $itemCount = count($items);
- /**
- * 前两项为模块名和方法名,参数从下标2开始。
- * The first two item is moduleName and methodName. So the params should begin at 2.
- **/
- for($i = 2; $i < $itemCount; $i ++)
- {
- $key = key($defaultParams); // Get key from the $defaultParams.
- if(empty($key)) continue;
- $params[$key] = $items[$i];
- next($defaultParams);
- }
- }
- $this->params = $this->mergeParams($defaultParams, $params);
- }
- /**
- * 设置请求的参数(GET 方式)。
- * Set the params by GET.
- *
- * @param array $defaultParams the default settings of the params.
- * @param string $type
- * @access public
- * @return void
- */
- public function setParamsByGET($defaultParams, $type = '')
- {
- $params = array();
- if($type != 'fetch')
- {
- /* Unset moduleVar, methodVar, viewVar and session 变量, 剩下的作为参数。 */
- /* Unset the moduleVar, methodVar, viewVar and session var, all the left are the params. */
- unset($_GET[$this->config->moduleVar]);
- unset($_GET[$this->config->methodVar]);
- unset($_GET[$this->config->viewVar]);
- unset($_GET[$this->config->sessionVar]);
- $params = $_GET;
- }
- /* Fix bug #3267. Param 'words' is not validated when searching. */
- if($this->rawModule == 'search' and $this->rawMethod == 'index') unset($params['words']);
- $this->params = $this->mergeParams($defaultParams, $params);
- }
- /**
- * 合并请求的参数和默认参数,这样就可以省略已经有默认值的参数了。
- * Merge the params passed in and the default params. Thus, the params which have default values needn't pass value, just like a function.
- *
- * @param array $defaultParams the default params defined by the method.
- * @param array $passedParams the params passed in through url.
- * @access public
- * @return array the merged params.
- */
- public function mergeParams($defaultParams, $passedParams)
- {
- global $filter;
- /* Remove these three params. */
- unset($passedParams['onlybody']);
- unset($passedParams['tid']);
- unset($passedParams['zin']);
- unset($passedParams['HTTP_X_REQUESTED_WITH']);
- /* Check params from URL. */
- $nameRule = $filter->{$this->moduleName}->{$this->methodName}->paramName ?? $filter->default->paramName;
- foreach($passedParams as $param => $value)
- {
- if(!validater::checkByRule($param, $nameRule)) helper::end('Bad Request!');
- $valueRule = $filter->default->paramValue;
- if(isset($filter->{$this->moduleName}->{$this->methodName}->paramValue[$param]))
- {
- $valueRule = $filter->{$this->moduleName}->{$this->methodName}->paramValue[$param];
- }
- if($value and !validater::checkByRule($value, $valueRule)) helper::end('Bad Request!');
- }
- $passedParams = array_values($passedParams);
- $i = 0;
- foreach($defaultParams as $key => $defaultItem)
- {
- if(isset($passedParams[$i]))
- {
- $defaultParams[$key] = helper::convertType(strip_tags((string) $passedParams[$i]), $defaultItem['type']);
- }
- else
- {
- if($defaultItem['default'] === '_NOT_SET') $this->triggerError("The param '$key' should pass value. ", __FILE__, __LINE__, true);
- $defaultParams[$key] = helper::convertType(strip_tags((string) $defaultItem['default']), $defaultItem['type']);
- }
- $i ++;
- }
- return $defaultParams;
- }
- /**
- * 获取$moduleName变量。
- * Get the $moduleName var.
- *
- * @access public
- * @return string
- */
- public function getModuleName()
- {
- return $this->moduleName;
- }
- /**
- * 获取$controlFile变量。
- * Get the $controlFile var.
- *
- * @access public
- * @return string
- */
- public function getControlFile()
- {
- return $this->controlFile;
- }
- /**
- * 获取$methodName变量。
- * Get the $methodName var.
- *
- * @access public
- * @return string
- */
- public function getMethodName()
- {
- return $this->methodName;
- }
- /**
- * 获取$param变量。
- * Get the $param var.
- *
- * @access public
- * @return array
- */
- public function getParams()
- {
- return $this->params;
- }
- //-------------------- 常用的工具方法(Tool methods) ------------------//
- /**
- * 从类库中加载一个类文件。
- *
- * Load a class file.
- *
- * @param string $className the class name
- * @param bool $static statis class or not
- * @access public
- * @return object|bool the instance of the class or just true.
- */
- public function loadClass($className, $static = false)
- {
- $className = strtolower($className);
- /* 搜索$coreLibRoot(Search in $coreLibRoot) */
- $classFile = $this->coreLibRoot . $className . DS . $className . '.class.php';
- if(!helper::import($classFile)) $this->triggerError("class file $classFile not found", __FILE__, __LINE__, true);
- /* 如果是静态调用,则返回(If static, return) */
- if($static) return true;
- /* 实例化该类(Instance it) */
- global ${$className};
- if(!class_exists($className)) $this->triggerError("the class $className not found in $classFile", __FILE__, __LINE__, true);
- if(!is_object(${$className})) ${$className} = new $className();
- return ${$className};
- }
- /**
- * 加载整个应用公共的配置文件。
- * Load the common config files for the app.
- *
- * @access public
- * @return void
- */
- public function loadMainConfig()
- {
- /* 初始化$config对象。Init the $config object. */
- global $config, $filter;
- if(!is_object($config)) $config = new config();
- /* 加载主配置文件。 Load the main config file. */
- $mainConfigFile = $this->configRoot . 'config.php';
- if(!file_exists($mainConfigFile)) $this->triggerError("The main config file $mainConfigFile not found", __FILE__, __LINE__, true);
- include $mainConfigFile;
- $this->config = $config;
- }
- /**
- * 当multiSite功能打开的时候,加载额外的配置文件。
- * When multiSite feature enabled, load extra config file.
- *
- * @access public
- * @return void
- */
- public function loadExtraConfig()
- {
- global $config;
- $multiConfigFile = $this->configRoot . 'multi.php';
- if(file_exists($multiConfigFile)) include $multiConfigFile;
- $siteConfigFile = $this->configRoot . "sites/{$this->siteCode}.php";
- if(file_exists($siteConfigFile)) include $siteConfigFile;
- }
- /**
- * 加载模块的config文件,返回全局$config对象。
- * 如果该模块是common,加载$configRoot的配置文件,其他模块则加载其模块的配置文件。
- *
- * Load config and return it as the global config object.
- * If the module is common, search in $configRoot, else in $modulePath.
- *
- * @param string $moduleName module name
- * @param string $appName app name
- * @access public
- * @return void
- */
- public function loadModuleConfig($moduleName, $appName = '')
- {
- if(isset(self::$loadedConfigs[$moduleName])) return false;
- self::$loadedConfigs[$moduleName] = $moduleName;
- global $config;
- if($config and (!isset($config->$moduleName) or !is_object($config->$moduleName))) $config->$moduleName = new stdclass();
- /* 将主配置文件和扩展配置文件合并在一起。Put the main config file and extension config files together. */
- $configFiles = $this->getMainAndExtFiles($moduleName, $appName, 'config');
- if(empty($configFiles)) return false;
- /* 加载每一个配置文件。Load every config file. */
- foreach($configFiles as $configFile)
- {
- if(isset(self::$loadedConfigs[$configFile])) continue;
- if(is_string($configFile) && file_exists($configFile)) include $configFile;
- self::$loadedConfigs[$configFile] = $configFile;
- }
- /* 加载数据库中与本模块相关的配置项。Merge from the db configs. */
- if($moduleName != 'common')
- {
- if(isset($config->systemDB->$moduleName)) $this->mergeConfig($config->systemDB->$moduleName, $moduleName);
- if(isset($config->personalDB->$moduleName)) $this->mergeConfig($config->personalDB->$moduleName, $moduleName);
- }
- }
- /**
- * Merge db config.
- *
- * @param array $dbConfig
- * @param string $moduleName
- * @access public
- * @return void
- */
- public function mergeConfig($dbConfig, $moduleName = 'common')
- {
- global $config;
- /* 如果没有设置本模块配置,则首先进行初始化。Init the $config->$moduleName if not set.*/
- if($moduleName != 'common' and !isset($config->$moduleName)) $config->$moduleName = new stdclass();
- $config2Merge = $config;
- if($moduleName != 'common') $config2Merge = $config->$moduleName;
- foreach($dbConfig as $item)
- {
- if($item->section)
- {
- if(!isset($config2Merge->{$item->section})) $config2Merge->{$item->section} = new stdclass();
- if(is_object($config2Merge->{$item->section}))
- {
- $config2Merge->{$item->section}->{$item->key} = $item->value;
- }
- }
- else
- {
- $config2Merge->{$item->key} = $item->value;
- }
- }
- }
- /**
- * 向客户端输出配置参数,客户端可以根据这些参数实现和调整请求的逻辑。
- * Export the config params to the client, thus the client can adjust it's logic according the config.
- *
- * @access public
- * @return string
- */
- public function exportConfig()
- {
- $view = new stdclass();
- $view->version = $this->config->version;
- $view->requestType = $this->config->requestType;
- $view->requestFix = $this->config->requestFix;
- $view->moduleVar = $this->config->moduleVar;
- $view->methodVar = $this->config->methodVar;
- $view->viewVar = $this->config->viewVar;
- $view->sessionVar = $this->config->sessionVar;
- $view->systemMode = $this->config->systemMode;
- $view->sprintConcept = zget($this->config->custom, 'sprintConcept', '0');
- $view->URAndSR = zget($this->config->custom, 'URAndSR', '0');
- $view->maxUploadSize = strtoupper(ini_get('upload_max_filesize'));
- $this->session->set('random', mt_rand(0, 10000));
- $view->sessionName = session_name();
- $view->sessionID = session_id();
- $view->random = $this->session->random;
- $view->expiredTime = ini_get('session.gc_maxlifetime');
- $view->serverTime = time();
- return json_encode($view);
- }
- /**
- * 获取主语言文件。
- * Get main lang file.
- *
- * @param string $moduleName the module name
- * @param string $appName the app name
- * @access public
- * @return string.
- */
- private function getMainLangFile($moduleName, $appName = '')
- {
- $path = $moduleName . DS . 'lang' . DS . $this->clientLang . '.php';
- $modulePath = $this->getExtensionRoot() . 'saas' . DS;
- if(file_exists($modulePath . $path)) return $modulePath . $path;
- /* 1. 最后尝试在定制开发中寻找。 Finally, try to find the module in the custom dir. */
- $modulePath = $this->getExtensionRoot() . 'custom' . DS;
- if(file_exists($modulePath . $path)) return $modulePath . $path;
- /* 2. 如果设置过vision,尝试在vision中查找。 If vision is set, try to find the module in the vision. */
- if($this->config->vision != 'rnd')
- {
- $modulePath = $this->getExtensionRoot() . $this->config->vision . DS;
- if(file_exists($modulePath . $path)) return $modulePath . $path;
- }
- /* 3. 尝试查找商业版本是否有此模块。 Try to find the module in other editon. */
- if($this->config->edition != 'open')
- {
- $modulePath = $this->getExtensionRoot() . $this->config->edition . DS;
- if(file_exists($modulePath . $path)) return $modulePath . $path;
- }
- /* 4. 尝试查找喧喧是否有此模块。 Try to find the module in other editon. */
- $modulePath = $this->getExtensionRoot() . 'xuan' . DS;
- if(file_exists($modulePath . $path)) return $modulePath . $path;
- /* 5. 如果通用版本里有此模块,优先使用。 If module is in the open edition, use it. */
- $modulePath = $this->getModuleRoot($appName);
- if(file_exists($modulePath . $path)) return $modulePath . $path;
- return '';
- }
- /**
- * 加载语言文件,返回全局$lang对象。
- * Load lang and return it as the global lang object.
- *
- * @param string $moduleName the module name
- * @param string $appName the app name
- * @access public
- * @return object the lang object
- */
- public function loadLang($moduleName, $appName = '')
- {
- /* 加载语言文件。Load lang files. */
- global $lang;
- if(!is_object($lang)) $lang = new language();
- if(!isset($lang->$moduleName)) $lang->$moduleName = new stdclass();
- if(isset(self::$loadedLangs[$moduleName])) return $lang;
- self::$loadedLangs[$moduleName] = $moduleName;
- /* 计算最终要加载的语言文件。 Get the lang files to be loaded. */
- $langFilesToLoad = $this->getMainAndExtFiles($moduleName, $appName, 'lang');
- if(empty($langFilesToLoad)) return $lang;
- foreach($langFilesToLoad as $langFile)
- {
- if(isset(self::$loadedLangs[$langFile])) continue;
- include $langFile;
- self::$loadedLangs[$langFile] = $langFile;
- }
- $this->lang = $lang;
- return $lang;
- }
- /**
- * 连接数据库。
- * Connect to database.
- *
- * @access public
- * @return void
- */
- public function connectDB()
- {
- global $dbh, $slaveDBH;
- if(!isset($this->config->installed) or !$this->config->installed) return;
- /* Set master db. */
- if(isset($this->config->db->host)) $this->dbh = $dbh = $this->connectByPDO($this->config->db, 'MASTER');
- /* Set slave db. */
- if(!empty($this->config->slaveDBList))
- {
- $biIndex = 0;
- $slaveList = array();
- foreach($this->config->slaveDBList as $index => $db)
- {
- if(isset($db->type) && $db->type == 'bi')
- {
- $biIndex = $index;
- }
- else
- {
- $slaveList[] = $index;
- }
- }
- $slaveIndex = empty($slaveList) ? $biIndex : $slaveList[array_rand($slaveList)];
- $this->config->biDB = $this->initSlaveDB($biIndex);
- $this->slaveDBH = $slaveDBH = $this->connectByPDO($this->initSlaveDB($slaveIndex), 'SLAVE');
- }
- $this->loadDAO();
- }
- /**
- * 加载DAO。
- * Load DAO.
- *
- * @access public
- * @return void
- */
- public function loadDAO()
- {
- global $dao;
- $driver = $this->config->db->driver;
- $classFile = $this->coreLibRoot . 'dao' . DS . $driver . '.class.php';
- include_once($classFile);
- $dao = new $driver($this);
- $this->dao = $dao;
- $this->loadClass('mao', true);
- $this->mao = new mao($this);
- }
- /**
- * 加载缓存类,初始化全局缓存对象。
- * Load the cache class and init the global cache object.
- *
- * @access public
- * @return void
- */
- private function loadCache()
- {
- if(!$this->checkInstalled()) return false;
- if(!empty($this->installing) || !empty($this->upgrading)) return false;
- $cacheConfig = $this->dao->select('`key`, value')->from(TABLE_CONFIG)->where('owner')->eq('system')->andWhere('module')->eq('common')->andWhere('section')->eq('cache')->fetchPairs();
- foreach($cacheConfig as $key => $value) $this->config->cache->$key = $value;
- if(!$this->config->cache->enable) return;
- if($this->config->cache->driver == 'redis')
- {
- $redisConfig = $this->dao->select('`key`, value')->from(TABLE_CONFIG)->where('owner')->eq('system')->andWhere('module')->eq('common')->andWhere('section')->eq('redis')->fetchPairs();
- foreach($redisConfig as $key => $value) $this->config->redis->$key = $value;
- }
- $tables = $this->dao->showTables();
- foreach($tables as $table)
- {
- $table = current($table);
- if($table == '`' . TABLE_AUTOCACHE . '`')
- {
- $autoCache = $this->dao->select('code, fields')->from(TABLE_AUTOCACHE)->fetchPairs();
- foreach($autoCache as $code => $fields)
- {
- $table = "`{$this->config->db->prefix}{$code}`";
- $name = 'CACHE_' . strtoupper($code) . '_AUTO';
- $this->config->cache->res[$table][] =['name' => $name, 'fields' => explode(',', $fields)];
- }
- }
- }
- $this->loadClass('cache', true);
- $this->cache = new Zentao\Cache\cache($this);
- /* 为 dao 和 mao 设置访问缓存的对象。 Set the cache object for dao and mao. */
- $this->dao->cache = $this->cache;
- $this->mao->cache = $this->cache;
- }
- /**
- * Init config of slave db.
- *
- * @param int $slaveIndex
- * @access private
- * @return object
- */
- private function initSlaveDB($slaveIndex = 0)
- {
- global $config;
- $slaveDB = $config->slaveDBList[$slaveIndex];
- $slaveDB->persistant = $config->db->persistent;
- $slaveDB->driver = $config->db->driver;
- $slaveDB->encoding = $config->db->encoding;
- $slaveDB->strictMode = $config->db->strictMode;
- $slaveDB->prefix = $config->db->prefix;
- return $slaveDB;
- }
- /**
- * 使用PDO连接数据库。
- * Connect database by PDO.
- *
- * @param object $params the database params.
- * @param string $flag the database flag.
- * @access public
- * @return object|bool
- */
- public function connectByPDO($params, $flag = 'MASTER')
- {
- if(!isset($params->driver)) static::triggerError('no pdo driver defined, it should be mysql or sqlite', __FILE__, __LINE__, true);
- if(!isset($params->user)) return false;
- try
- {
- $dbh = new dbh($params, true, $flag);
- /*
- * 如果系统是Linux,开启仿真预处理和缓冲查询。
- * If run on linux, set emulatePrepare and bufferQuery to true.
- **/
- if(!isset($params->emulatePrepare) and PHP_OS == 'Linux') $params->emulatePrepare = true;
- if(!isset($params->bufferQuery) and PHP_OS == 'Linux') $params->bufferQuery = true;
- if(!$this->apiVersion) $params->emulatePrepare = false;
- $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
- $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
- $dbh->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_TO_STRING);
- if(isset($params->emulatePrepare)) $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, $params->emulatePrepare);
- if(isset($params->bufferQuery)) $dbh->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, $params->bufferQuery);
- return $dbh;
- }
- catch(PDOException $exception)
- {
- $message = $exception->getMessage();
- if(empty($message))
- {
- /* Try to repair table. */
- helper::header('location', "{$this->config->webRoot}checktable.php");
- helper::end();
- }
- static::triggerError($message, __FILE__, __LINE__, true);
- }
- }
- /**
- * 连接SQLite数据库。
- * Connect SQLite database.
- *
- * @param object $params
- * @access public
- * @return object
- */
- public function connectSqlite($params = null)
- {
- if(empty($params))
- {
- $params = new stdclass();
- $params->file = $this->getTmpRoot() . 'sqlite.db';
- }
- return new sqlite($params);
- }
- /**
- * Query from database, use master or slave db.
- *
- * @param string $query
- * @access public
- * @return mixed
- */
- public function dbQuery($query)
- {
- if(!$this->dbh) return false;
- if($this->slaveDBH && strtolower(substr($query, 0, 6)) == 'select') return $this->slaveDBH->query($query);
- return $this->dbh->query($query);
- }
- //-------------------- 错误处理方法(Error methods) ------------------//
- /**
- * 程序停止时执行的函数。
- * The shutdown handler.
- *
- * @access public
- * @return void
- */
- public function shutdown()
- {
- /* 如果开启了缓存则关闭缓存连接,主要用于 Redis 等缓存服务。Close the cache connection if it's open. */
- if(!empty($this->cache)) $this->cache->close();
- /* 如果debug模式开启,保存sql语句(If debug on, save sql queries) */
- if(!empty($this->config->debug)) $this->saveSQL();
- /*
- * 发现错误,保存到日志中。
- * If any error occurs, save it.
- * */
- if(!function_exists('error_get_last')) return;
- $error = error_get_last();
- if($error)
- {
- $this->saveError($error['type'], $error['message'], $error['file'], $error['line']);
- if(!empty($this->config->debug) && (!is_dir($this->logRoot) || !is_writable($this->logRoot))) helper::end('ERROR: ' . $error['message']);
- }
- }
- /**
- * 触发一个错误。
- * Trigger an error.
- *
- * @param string $message 错误信息 error message
- * @param string $file 所在文件 the file error occurs
- * @param int $line 错误行 the line error occurs
- * @param bool $exit 是否停止程序 exit the program or not
- * @access public
- * @return void
- */
- public function triggerError($message, $file, $line, $exit = false)
- {
- $function = null;
- /* 设置错误信息(Set the error info) */
- $message = htmlSpecialString($message);
- if(preg_match('/[^\x00-\x80]/', $message)) $message = helper::convertEncoding($message, 'gbk');
- /* Only show error when debug is open. */
- if(!$this->config->debug) die;
- $log = (new Exception())->getTraceAsString(); /* Print a backtrace like debug_print_backtrace(). */
- $log = str_replace($this->basePath, '', $log); /* Remove the base path from the backtrace. */
- $log .= "ERROR: $message in $file on line $line";
- if(isset($_SERVER['SCRIPT_URI'])) $log .= ", request: $_SERVER[SCRIPT_URI]";
- $trace = debug_backtrace();
- extract($trace[0]);
- extract($trace[1]);
- $log .= ", last called by $file on line $line through function $function.\n";
- /* Change absolute path to relative path. */
- $log = str_replace($this->basePath, '', $log);
- /* 触发错误(Trigger the error) */
- $exit ? helper::end($log) : trigger_error($log, E_USER_WARNING);
- }
- /**
- * 保存错误信息。
- * Save error info.
- *
- * @param int $level
- * @param string $message
- * @param string $file
- * @param int $line
- * @access public
- * @return void
- */
- public function saveError($level, $message, $file, $line)
- {
- if(empty($this->config->debug)) return true;
- if(!is_dir($this->logRoot)) return true;
- if(!is_writable($this->logRoot)) return true;
- /*
- * 删除设定时间之前的日志。
- * Delete the log before the set time.
- **/
- if(mt_rand(0, 10) == 1)
- {
- $logDays = $this->config->framework->logDays ?? 14;
- $dayTime = time() - $logDays * 24 * 3600;
- foreach(glob($this->getLogRoot() . '*') as $logFile)
- {
- if(filemtime($logFile) <= $dayTime) unlink($logFile);
- }
- }
- /*
- * 忽略该错误:Redefining already defined constructor。
- * Skip the error: Redefining already defined constructor.
- **/
- if(strpos($message, 'Redefining') !== false) return true;
- /*
- * 设置错误信息。
- * Set the error info.
- **/
- if(preg_match('/[^\x00-\x80]/', $message)) $message = helper::convertEncoding($message, 'gbk');
- $errorLog = "\n" . date('H:i:s') . " $message in <strong>$file</strong> on line <strong>$line</strong> ";
- $uri = $this->getURI();
- $errorLog .= "when visiting <strong>" . (empty($uri) ? '' : htmlspecialchars($uri)) . "</strong>\n";
- /*
- * 为了安全起见,对公网环境隐藏脚本路径。
- * If the ip is pulic, hidden the full path of scripts.
- */
- $remoteIP = helper::getRemoteIp(true);
- if(!defined('IN_SHELL') and !($remoteIP == '127.0.0.1' or filter_var($remoteIP, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === false))
- {
- $errorLog = str_replace($this->getBasePath(), '', $errorLog);
- }
- /* 保存到日志文件(Save to log file) */
- $runMode = PHP_SAPI == 'cli' ? '_cli' : '';
- $errorFile = $this->logRoot . "php$runMode." . date('Ymd') . '.log.php';
- if(!is_file($errorFile)) file_put_contents($errorFile, "<?php\n die();\n?" . ">\n");
- $fh = fopen($errorFile, 'a');
- if($fh) fwrite($fh, strip_tags(htmlspecialchars_decode($errorLog))) and fclose($fh);
- /*
- * 如果debug > 1,直接在页面显示非严重错误。
- * If the debug > 1, show non-serious errors on page directly.
- **/
- if(!empty($this->config->debug) && $this->config->debug > 1)
- {
- /* Send non-serious errors to page in zin mode. */
- $isZinRequest = isset($_SERVER['HTTP_X_ZIN_OPTIONS']);
- $isNonSeriousError = $level !== E_ERROR && $level !== E_PARSE && $level !== E_CORE_ERROR && $level !== E_COMPILE_ERROR;
- if($isZinRequest && $isNonSeriousError)
- {
- /* Generate error stack trace info. */
- $e = new Exception();
- $trace = $e->getTraceAsString();
- $this->zinErrors[] = array('file' => $file, 'line' => $line, 'message' => $message, 'level' => $level, 'trace' => $trace);
- return;
- }
- /* Show non-serious errors to classic page. */
- if($level == E_NOTICE or $level == E_WARNING or $level == 8192)
- {
- $cmd = "vim +$line $file";
- $size = strlen($cmd);
- echo "<pre class='alert alert-danger'>$message: ";
- echo "<input type='text' value='$cmd' size='$size' style='border:none; background:none;' onclick='this.select();' /></pre>";
- }
- }
- /*
- * 如果是严重错误,由shutdown触发,会停止程序。
- * If error level is serious, die by shutdown function.
- * */
- if(in_array($level, array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR)))
- {
- if(empty($this->config->debug)) return true;
- if(PHP_SAPI == 'cli')
- {
- echo $errorLog;
- }
- else
- {
- $htmlError = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8' /></head>";
- $htmlError .= "<body>" . nl2br($errorLog) . "</body></html>";
- echo $htmlError;
- }
- }
- return true;
- }
- /**
- * 保存sql语句。
- * Save the sql.
- *
- * @access public
- * @return void
- */
- public function saveSQL()
- {
- if(!$this->config->debug) return true;
- if(!class_exists('dao')) return;
- $runMode = PHP_SAPI == 'cli' ? '_cli' : '';
- $sqlLog = $this->getLogRoot() . "sql$runMode." . date('Ymd') . '.log.php';
- if(!is_file($sqlLog)) file_put_contents($sqlLog, "<?php\n die();\n?" . ">\n");
- if(!is_writable($sqlLog)) return false;
- $fh = fopen($sqlLog, 'a');
- fwrite($fh, date('Ymd H:i:s') . ": " . $this->getURI() . "\n");
- foreach(dbh::$queries as $key => $query)
- {
- if(!empty(dbh::$flags)) fwrite($fh, ' #Flag: ' . (dbh::$flags[$key] ?? '') . "\n");
- if(!empty(dbh::$durations)) fwrite($fh, ' #Query_time: ' . (dbh::$durations[$key] ?? '') . "\n");
- if(!empty(dbh::$traces)) fwrite($fh, ' #Trigger_code: ' . (dbh::$traces[$key] ?? '') . "\n");
- fwrite($fh, " $query\n");
- }
- fwrite($fh, "\n");
- fclose($fh);
- }
- /**
- * Check app if it is run in a container.
- *
- * @access public
- * @return bool
- */
- public function isContainer()
- {
- return strtolower((string)getenv('IS_CONTAINER')) == 'true';
- }
- /**
- * Check app if it can be upgraded automatically.
- *
- * @access public
- * @return bool
- */
- public function canAutoUpgrade()
- {
- return strtolower((string)getenv('ZT_AUTO_UPGRADE')) == 'true';
- }
- /**
- * Check app if it need check safe file.
- *
- * @access public
- * @return bool
- */
- public function hasValidSafeFile()
- {
- return strtolower((string)getenv('ZT_CHECK_SAFE_FILE')) == 'true';
- }
- /**
- * Get main file and ext files.
- *
- * @param string $moduleName
- * @param string $appName
- * @param string $type lang|config|control|model
- * @access public
- * @return array
- */
- public function getMainAndExtFiles($moduleName, $appName = '', $type = 'lang')
- {
- $clientLang = null;
- /* 初始化变量。Init vars. */
- $modulePath = $this->getModulePath($appName, $moduleName);
- $extFiles = array();
- $filesToLoad = array();
- /* 判断主文件是否存在。Whether the main file exists or not. */
- if($type == 'lang')
- {
- $mainFile = $this->getMainLangFile($moduleName, $appName);
- }
- else
- {
- $mainFile = $modulePath . $type . '.php';
- }
- if($mainFile) $filesToLoad[] = $mainFile;
- if($type == 'config')
- {
- $filesToLoad[] = helper::ls($modulePath . DS . 'config', '.php');
- }
- /* 获取扩展文件。If extensionLevel > 0, get extension files. */
- if($this->config->framework->extensionLevel > 0)
- {
- $commonExtFiles = array();
- $siteExtFiles = array();
- $extPath = $this->getModuleExtPath($moduleName, $type);
- if($this->config->framework->extensionLevel >= 1)
- {
- $clientLang = $type == 'lang' ? $this->clientLang : '';
- if(!empty($extPath['common'])) $commonExtFiles = helper::ls($extPath['common'] . $clientLang, '.php');
- if(!empty($extPath['xuan'])) $commonExtFiles = array_merge($commonExtFiles, helper::ls($extPath['xuan'] . $clientLang, '.php'));
- if(!empty($extPath['vision'])) $commonExtFiles = array_merge($commonExtFiles, helper::ls($extPath['vision'] . $clientLang, '.php'));
- if(!empty($extPath['custom'])) $commonExtFiles = array_merge($commonExtFiles, helper::ls($extPath['custom'] . $clientLang, '.php'));
- if(!empty($extPath['saas'])) $commonExtFiles = array_merge($commonExtFiles, helper::ls($extPath['saas'] . $clientLang, '.php'));
- }
- if($this->config->framework->extensionLevel == 2 and !empty($extPath['site'])) $siteExtFiles = helper::ls($extPath['site'] . $clientLang, '.php');
- $extFiles = array_merge($commonExtFiles, $siteExtFiles);
- }
- /* 计算最终要加载的文件。 Get the files to be loaded. */
- $filesToLoad = array_merge($filesToLoad, $extFiles);
- if(empty($filesToLoad)) return false;
- return $filesToLoad;
- }
- /**
- * 检查是否已安装禅道,主要用于DevOps平台版。
- * Check zentao is installed.
- *
- * @access public
- * @return bool
- */
- public function checkInstalled()
- {
- $installed = true;
- if(!isset($this->config->installed) || !$this->config->installed) $installed = false;
- if(($this->config->inContainer || $this->config->inQuickon) && $installed && !$this->getInstalledVersion()) $installed = false;
- if(!isset($_SESSION['installing']) && !$installed && !empty($this->installing)) $_SESSION['installing'] = true;
- return $installed;
- }
- /**
- * 检查是否需要升级。如果需要升级并且开启了缓存,清空缓存以避免直接执行 SQL 语句导致数据不一致。
- * Check if need upgrade. If need upgrade and cache is open, clear the cache to avoid data inconsistency caused by direct execution of SQL statements.
- *
- * @access public
- * @return bool
- */
- public function checkNeedUpgrade()
- {
- $installedVersion = $this->getInstalledVersion();
- if($installedVersion == $this->config->version) return false;
- if(!empty($this->cache)) $this->cache->clear();
- return true;
- }
- }
- class config
- {
- /**
- * 设置成员变量,成员可以是'db.user'类似的格式。
- * Set the value of a member. the member can be the format like db.user.
- *
- * <code>
- * <?php
- * $config->set('db.user', 'wwccss');
- * ?>
- * </code>
- * @param string $key the key of the member
- * @param mixed $value the value
- * @access public
- * @return void
- */
- public function set($key, $value)
- {
- helper::setMember('config', $key, $value);
- }
- }
- /**
- * lang类。
- * The lang class.
- *
- * @package framework
- */
- class language
- {
- /**
- * 设置成员变量,成员可以是'db.user'类似的格式。
- * Set the value of a member. the member can be the foramt like db.user.
- *
- * <code>
- * <?php
- * $lang->set('version', '1.0);
- * ?>
- * </code>
- * @param string $key 成员的键名,可以是father.child的形式。
- * the key of the member, can be father.child
- * @param mixed $value the value
- * @access public
- * @return void
- */
- public function set($key, $value)
- {
- helper::setMember('lang', $key, $value);
- }
- /**
- * 显示一个成员的值。
- * Show a member.
- *
- * @param object $obj the object
- * @param string $key the key
- * @access public
- * @return void
- */
- public function show($obj, $key)
- {
- $obj = (array)$obj;
- echo $obj[$key] ?? '';
- }
- }
- /**
- * 超级对象类,转化超级全局变量。
- * The super object class.
- *
- * @package framework
- */
- class super
- {
- /**
- * 构造函数,设置超级变量名。
- * Construct, set the var scope.
- *
- * @param string $scope the scope, can be server, post, get, cookie, session, global
- * @access public
- * @return void
- * @param string $tab
- */
- public function __construct($scope, $tab = '')
- {
- $this->scope = $scope;
- $this->tab = $tab;
- }
- /**
- * 设置超级变量的成员值。
- * Set one member value.
- *
- * @param string $key the key
- * @param mixed $value the value
- * @param string $tab
- * @access public
- * @return void
- */
- public function set($key, $value, $tab = '')
- {
- if($this->scope == 'post')
- {
- $_POST[$key] = $value;
- }
- elseif($this->scope == 'get')
- {
- $_GET[$key] = $value;
- }
- elseif($this->scope == 'server')
- {
- $_SERVER[$key] = $value;
- }
- elseif($this->scope == 'cookie')
- {
- $_COOKIE[$key] = $value;
- }
- elseif($this->scope == 'session')
- {
- if($tab) $_SESSION["app-$tab"][$key] = $value;
- $_SESSION[$key] = $value;
- }
- elseif($this->scope == 'env')
- {
- $_ENV[$key] = $value;
- }
- elseif($this->scope == 'global')
- {
- $GLOBALS[$key] = $value;
- }
- }
- /**
- * 超级变量的魔术方法,比如用$post->key访问$_POST['key']。
- * The magic get method.
- *
- * @param string $key the key
- * @access public
- * @return mixed|bool return the value of the key or false.
- */
- public function __get($key)
- {
- if($this->scope == 'post')
- {
- if(isset($_POST[$key])) return $_POST[$key];
- return false;
- }
- elseif($this->scope == 'get')
- {
- if(isset($_GET[$key])) return $_GET[$key];
- return false;
- }
- elseif($this->scope == 'server')
- {
- if($key == 'ajax') return isset($_SERVER['HTTP_X_REQUESTED_WITH']) ? true : false;
- if(isset($_SERVER[$key])) return $_SERVER[$key];
- $key = strtoupper($key);
- if(isset($_SERVER[$key])) return $_SERVER[$key];
- return false;
- }
- elseif($this->scope == 'cookie')
- {
- if(isset($_COOKIE[$key])) return $_COOKIE[$key];
- return false;
- }
- elseif($this->scope == 'session')
- {
- $tab = $this->tab;
- if($tab and isset($_SESSION["app-$tab"][$key])) return $_SESSION["app-$tab"][$key];
- if(isset($_SESSION[$key])) return $_SESSION[$key];
- return false;
- }
- elseif($this->scope == 'env')
- {
- if(isset($_ENV[$key])) return $_ENV[$key];
- return false;
- }
- elseif($this->scope == 'global')
- {
- if(isset($GLOBALS[$key])) return $GLOBALS[$key];
- return false;
- }
- else
- {
- return false;
- }
- }
- /**
- * 打印变量的详细结构。
- * Print the structure.
- *
- * @access public
- * @return void
- */
- public function a()
- {
- if($this->scope == 'post') a($_POST);
- if($this->scope == 'get') a($_GET);
- if($this->scope == 'server') a($_SERVER);
- if($this->scope == 'cookie') a($_COOKIE);
- if($this->scope == 'session') a($_SESSION);
- if($this->scope == 'env') a($_ENV);
- if($this->scope == 'global') a($GLOBALS);
- }
- }
- class EndResponseException extends \Exception
- {
- /**
- * 响应内容
- *
- * @var string
- */
- private $content;
- /**
- * @param string $content
- *
- * @return self
- */
- public static function create($content = '')
- {
- $exception = new self($content);
- $exception->content = $content;
- return $exception;
- }
- /**
- * Get 响应内容
- *
- * @return string
- */
- public function getContent()
- {
- return $this->content;
- }
- }
- /**
- * ZenTao session handler.
- *
- * @package framework
- */
- class ztSessionHandler implements SessionHandlerInterface
- {
- public $sessSavePath;
- public $sessionFile;
- public $sessionID;
- public $sessionName;
- /**
- * Construct.
- *
- * @access public
- * @return void
- */
- public function __construct()
- {
- register_shutdown_function('session_write_close');
- }
- /**
- * Get sessionID.
- *
- * @access public
- * @return string
- */
- public function getSessionID()
- {
- return $this->sessionID;
- }
- /**
- * Get session file.
- *
- * @param string $id
- * @access public
- * @return string
- */
- public function getSessionFile($id)
- {
- if(!empty($this->sessionFile)) return $this->sessionFile;
- if(!preg_match('/^\w+$/', $id)) return false;
- $fileName = "sess_{$id}";
- $this->sessionFile = $this->sessSavePath . DS . $fileName;
- $this->sessionID = $id;
- return $this->sessionFile;
- }
- /**
- * Creates a new session, or reinitialize existing session.
- *
- * @param string $savePath
- * @param string $sessionName
- * @access public
- * @return bool
- */
- #[\ReturnTypeWillChange]
- public function open($savePath, $sessionName)
- {
- $this->sessSavePath = $savePath;
- $this->sessionName = $sessionName;
- return true;
- }
- /**
- * Closes the current session.
- *
- * @access public
- * @return bool
- */
- #[\ReturnTypeWillChange]
- public function close()
- {
- return true;
- }
- /**
- * Reads the session data from the session file, and returns the results.
- *
- * @param string $id
- * @access public
- * @return string|false
- */
- #[\ReturnTypeWillChange]
- public function read($id)
- {
- $sessFile = $this->getSessionFile($id);
- if(!$sessFile) return false;
- if(file_exists($sessFile)) return file_get_contents($sessFile);
- return '';
- }
- /**
- * Writes the session data to the session file.
- *
- * @param string $id
- * @param string $sessData
- * @access public
- * @return bool
- */
- #[\ReturnTypeWillChange]
- public function write($id, $sessData)
- {
- $sessFile = $this->getSessionFile($id);
- if(!$sessFile) return true;
- if(!is_file($sessFile) && !touch($sessFile)) return true;
- if(!is_writable($sessFile)) return true;
- if(md5_file($sessFile) == md5($sessData)) return true;
- if(file_put_contents($sessFile, $sessData, LOCK_EX)) return true;
- return true;
- }
- /**
- * Destroys a session.
- *
- * @param string $id
- * @access public
- * @return bool
- */
- #[\ReturnTypeWillChange]
- public function destroy($id)
- {
- $sessFile = $this->getSessionFile($id);
- if(file_exists($sessFile)) unlink($sessFile);
- return true;
- }
- /**
- * Cleans up expired sessions.
- *
- * @param int $maxlifeTime
- * @access public
- * @return int|false
- */
- #[\ReturnTypeWillChange]
- public function gc($maxlifeTime)
- {
- /* API session never expires. */
- global $config;
- if((defined('RUN_MODE') && RUN_MODE == 'api') || isset($_GET[$config->sessionVar])) return 0;
- $time = time();
- $count = 0;
- foreach(glob("{$this->sessSavePath}/sess_*") as $fileName)
- {
- if(filemtime($fileName) + $maxlifeTime < $time && unlink($fileName)) $count++;
- }
- return $count;
- }
- }
|