3030use iTXTech \SimpleFramework \Scheduler \OnCompletionListener ;
3131use iTXTech \SimpleFramework \Scheduler \Scheduler ;
3232use iTXTech \SimpleFramework \Util \Config ;
33+ use iTXTech \SimpleFramework \Util \FrameworkProperties ;
34+ use iTXTech \SimpleFramework \Util \StringUtil ;
3335use iTXTech \SimpleFramework \Util \Util ;
3436
3537class Framework implements OnCompletionListener{
36- const PROG_NAME = "SimpleFramework " ;
37- const PROG_VERSION = "2.1.0 " ;
38- const API_LEVEL = 6 ;
39- const CODENAME = "Navi " ;
38+ public const PROG_NAME = "SimpleFramework " ;
39+ public const PROG_VERSION = "2.1.0 " ;
40+ public const API_LEVEL = 6 ;
41+ public const CODENAME = "Navi " ;
4042
4143 /** @var Framework */
4244 private static $ instance = null ;
4345
46+ private static $ tickInterval = 50000 ;
47+
48+ //Objects
4449 /** @var ConsoleReader */
4550 private $ console ;
46-
4751 /** @var CommandProcessor */
4852 private $ commandProcessor ;
49-
5053 /** @var Config */
5154 private $ config ;
52-
5355 /** @var \ClassLoader */
5456 private $ classLoader ;
55-
5657 /** @var Scheduler */
5758 private $ scheduler ;
58-
5959 /** @var ModuleManager */
6060 private $ moduleManager ;
61+ /** @var Options */
62+ private $ options ;
63+ /** @var FrameworkProperties */
64+ private $ properties ;
6165
66+ //Properties
6267 private $ shutdown = false ;
68+ private $ displayTitle = true ;
6369
70+ //
6471 private $ currentTick = 0 ;
65-
6672 private $ titleQueue = [];
6773
68- private $ dataPath ;
69- private $ modulePath ;
70- private $ moduleDataPath ;
71- public $ displayTitle = true ;
72-
73- /** @var Options */
74- private $ options ;
75-
76- public static $ usleep = 50000 ;
77-
7874 public function __construct (\ClassLoader $ classLoader ){
7975 if (self ::$ instance === null ){
8076 self ::$ instance = $ this ;
8177 }
82- $ this ->dataPath = \getcwd () . DIRECTORY_SEPARATOR ;
83- $ this ->modulePath = $ this ->dataPath . "modules " . DIRECTORY_SEPARATOR ;
84- $ this ->moduleDataPath = $ this ->dataPath . "data " . DIRECTORY_SEPARATOR ;
8578 $ this ->classLoader = $ classLoader ;
86-
8779 $ this ->options = new Options ();
8880 $ this ->registerDefaultOptions ();
81+
82+ $ this ->properties = new FrameworkProperties ();
83+ $ this ->properties ->dataPath = \getcwd () . DIRECTORY_SEPARATOR ;
84+ $ this ->properties ->generatePath ();
85+ }
86+
87+ public static function getTickInterval () : int {
88+ return self ::$ tickInterval ;
89+ }
90+
91+ public static function setTickInterval (int $ tickInterval ) : void {
92+ self ::$ tickInterval = max ($ tickInterval , 0 );
93+ }
94+
95+ public function isDisplayTitle () : bool {
96+ return $ this ->displayTitle ;
97+ }
98+
99+ public function setDisplayTitle (bool $ displayTitle ) : void {
100+ $ this ->displayTitle = $ displayTitle ;
89101 }
90102
91103 public function getLoader (){
@@ -104,7 +116,7 @@ public function getCodename() : string{
104116 return self ::CODENAME ;
105117 }
106118
107- public function getAPILevel () : int {
119+ public function getApi () : int {
108120 return self ::API_LEVEL ;
109121 }
110122
@@ -129,7 +141,8 @@ private function registerDefaultOptions(){
129141 ->desc ("Display this help message " )->build ());
130142 $ this ->options ->addOption ((new OptionBuilder ("v " ))->longOpt ("version " )
131143 ->desc ("Display version of SimpleFramework " )->build ());
132- $ this ->options ->addOption ((new OptionBuilder ("l " ))->longOpt ("disable-logger " )
144+
145+ $ this ->options ->addOption ((new OptionBuilder ("d " ))->longOpt ("disable-logger " )
133146 ->desc ("Disable Logger output " )->build ());
134147 $ this ->options ->addOption ((new OptionBuilder ("c " ))->longOpt ("disable-logger-class " )
135148 ->desc ("Disable Logger Class detection " )->build ());
@@ -139,23 +152,32 @@ private function registerDefaultOptions(){
139152 ->desc ("Enable or Disable ANSI " )->hasArg ()->argName ("yes|no " )->build ());
140153 $ this ->options ->addOption ((new OptionBuilder ("t " ))->longOpt ("title " )
141154 ->desc ("Enable or Disable title display " )->hasArg ()->argName ("yes|no " )->build ());
155+ $ this ->options ->addOption ((new OptionBuilder ("e " ))->longOpt ("config " )
156+ ->desc ("Overwrite specified config property " )->hasArg ()->argName ("prop " )->build ());
157+
158+ $ this ->options ->addOption ((new OptionBuilder ("l " ))->longOpt ("data-path " )
159+ ->desc ("Specify SimpleFramework data path " )->hasArg ()->argName ("path " )->build ());
160+ $ this ->options ->addOption ((new OptionBuilder ("m " ))->longOpt ("module-path " )
161+ ->desc ("Specify SimpleFramework module path " )->hasArg ()->argName ("path " )->build ());
162+ $ this ->options ->addOption ((new OptionBuilder ("n " ))->longOpt ("module-data-path " )
163+ ->desc ("Specify SimpleFramework module data path " )->hasArg ()->argName ("path " )->build ());
164+ $ this ->options ->addOption ((new OptionBuilder ("o " ))->longOpt ("config-path " )
165+ ->desc ("Specify SimpleFramework config file " )->hasArg ()->argName ("path " )->build ());
142166
143- //TODO
144167 $ this ->options ->addOption ((new OptionBuilder ("l " ))->longOpt ("load-module " )->hasArg ()
145168 ->desc ("Load the specified module " )->argName ("path " )->build ());
146- $ this ->options ->addOption ((new OptionBuilder ("r " ))->longOpt ("cmd " )->hasArg ()
169+ $ this ->options ->addOption ((new OptionBuilder ("r " ))->longOpt ("run-command " )->hasArg ()
147170 ->desc ("Execute the specified command " )->argName ("command " )->build ());
148171 }
149172
150- private function processCommandLineOptions (array $ argv ) : bool {
173+ private function processCommandLineOptions (array $ argv ){
151174 try {
152175 $ cmd = (new Parser ())->parse ($ this ->options , $ argv );
153176 if ($ cmd ->hasOption ("help " )){
154177 $ t = (new HelpFormatter ())->generateHelp ("sf " , $ this ->options );
155178 echo $ t ;
156179 exit (0 );
157180 }
158-
159181 if ($ cmd ->hasOption ("version " )){
160182 Util::println (Framework::PROG_NAME . " " . Framework::PROG_VERSION .
161183 " \"" . Framework::CODENAME . "\" [PHP " . PHP_VERSION . "] " );
@@ -166,105 +188,128 @@ private function processCommandLineOptions(array $argv) : bool{
166188 }
167189 exit (0 );
168190 }
169-
170191 if ($ cmd ->hasOption ("disable-logger " )){
171192 Logger::$ disableOutput = true ;
172193 }
173-
174194 if ($ cmd ->hasOption ("disable-logger-class " )){
175195 Logger::$ disableClass = true ;
176196 }
177-
178197 if ($ cmd ->hasOption ("without-prefix " )){
179198 Logger::$ hasPrefix = false ;
180199 }
181-
182200 if ($ cmd ->hasOption ("ansi " )){
183201 Terminal::$ formattingCodes = Util::getCliOptBool ($ cmd ->getOptionValue ("ansi " ));
184202 Terminal::init ();
185203 }
186-
187204 if ($ cmd ->hasOption ("title " )){
188- $ this ->displayTitle = false ;
205+ $ this ->properties ->config ["display-title " ] = false ;
206+ }
207+ if ($ cmd ->hasOption ("load-module " )){
208+ foreach ($ cmd ->getOptionValues ("load-module " ) as $ value ){
209+ $ this ->properties ->additionalModules [] = $ value ;
210+ }
211+ }
212+ if ($ cmd ->hasOption ("run-command " )){
213+ foreach ($ cmd ->getOptionValues ("run-command " ) as $ value ){
214+ $ this ->properties ->commands [] = $ value ;
215+ }
216+ }
217+ if ($ cmd ->hasOption ("data-path " )){
218+ $ this ->properties ->dataPath = $ cmd ->getOptionValue ("data-path " );
219+ $ this ->properties ->generatePath ();
220+ }
221+ if ($ cmd ->hasOption ("module-path " )){
222+ $ this ->properties ->modulePath = $ cmd ->getOptionValue ("module-path " );
223+ }
224+ if ($ cmd ->hasOption ("module-data-path " )){
225+ $ this ->properties ->moduleDataPath = $ cmd ->getOptionValue ("module-data-path " );
226+ }
227+ if ($ cmd ->hasOption ("config " )){
228+ foreach ($ cmd ->getOptionValues ("config " ) as $ value ){
229+ list ($ k , $ v ) = explode ("= " , $ value , 2 );
230+ if (StringUtil::contains ($ k , ". " )){
231+ list ($ k1 , $ k2 ) = explode (". " , $ k );
232+ $ this ->properties ->config [$ k1 ][$ k2 ] = $ v ;
233+ }else {
234+ $ this ->properties ->config [$ k ] = $ v ;
235+ }
236+ }
189237 }
190-
191238 }catch (\Throwable $ e ){
192239 Util::println ($ e ->getMessage ());
193240 $ t = (new HelpFormatter ())->generateHelp ("sf " , $ this ->options , true );
194241 echo $ t ;
195242 exit (1 );
196243 }
197- return false ;
198244 }
199245
200246 public function start (bool $ useMainThreadTick = true , array $ argv = []){
201247 try {
202- if (!$ this ->processCommandLineOptions ($ argv )){
203- //$this->displayTitle("SimpleFramework is starting...");
204- @mkdir ("modules " );
205- @mkdir ("data " );
206-
207- set_exception_handler ("\\iTXTech \\SimpleFramework \\Console \\Logger::logException " );
208-
209- $ this ->config = new Config ($ this ->dataPath . "config.json " , Config::JSON , [
210- "auto-load-modules " => true ,
211- "async-workers " => 2 ,
212- "log-file " => "" ,
213- "display-title " => true ,
214- "module-dependency-resolver " => [
215- "enabled " => true ,
216- "remote-database " => "https://raw.githubusercontent.com/iTXTech/WraithSpireDatabase/master/ " ,
217- "modules " => []
218- ]
219- ]);
220- $ this ->config ->save ();
221-
222- Logger::setLogFile ($ this ->config ->get ("log-file " , "" ));
223-
224- Logger::info (TextFormat::AQUA . self ::PROG_NAME . " " . TextFormat::LIGHT_PURPLE . self ::PROG_VERSION . TextFormat::GREEN . " [ " . self ::CODENAME . "] " );
225- Logger::info (TextFormat::GOLD . "Licensed under GNU General Public License v3.0 " );
226-
227- if ($ this ->moduleManager === null ){
228- $ this ->moduleManager = new ModuleManager ($ this ->classLoader , $ this ->modulePath , $ this ->moduleDataPath );
229- }
248+ $ this ->processCommandLineOptions ($ argv );
249+ $ this ->properties ->mkdirDirs ();
250+
251+ set_exception_handler ("\\iTXTech \\SimpleFramework \\Console \\Logger::logException " );
252+
253+ $ this ->config = new Config ($ this ->properties ->configPath , Config::JSON , [
254+ "auto-load-modules " => true ,
255+ "async-workers " => 2 ,
256+ "log-file " => "" ,
257+ "display-title " => true ,
258+ "wsmdr " => [//WraithSpireModuleDependencyResolver
259+ "enabled " => true ,
260+ "remote-database " => "https://raw.githubusercontent.com/iTXTech/WraithSpireDatabase/master/ " ,
261+ "modules " => []
262+ ]
263+ ]);
264+ $ this ->config ->save ();
265+ $ this ->properties ->mergeConfig ($ this ->config );
266+
267+ Logger::setLogFile ($ this ->config ->get ("log-file " , "" ));
268+
269+ Logger::info (TextFormat::AQUA . self ::PROG_NAME . " " . TextFormat::LIGHT_PURPLE .
270+ self ::PROG_VERSION . TextFormat::GREEN . " [ " . self ::CODENAME . "] " );
271+ Logger::info (TextFormat::GOLD . "Licensed under GNU General Public License v3.0 " );
272+
273+ $ this ->moduleManager = new ModuleManager ($ this ->classLoader ,
274+ $ this ->properties ->modulePath , $ this ->properties ->moduleDataPath );
275+
276+ if (!\iTXTech \SimpleFramework \SINGLE_THREAD ){
277+ Logger::info ("Starting ConsoleReader... " );
278+ $ this ->console = new ConsoleReader ();
279+ }
230280
231- if (!\iTXTech \SimpleFramework \SINGLE_THREAD ){
232- Logger::info ("Starting ConsoleReader... " );
233- $ this ->console = new ConsoleReader ();
234- }
281+ Logger::info ("Starting Command Processor... " );
282+ $ this ->commandProcessor = new CommandProcessor ();
283+ $ this ->commandProcessor ->registerDefaultCommands ();
235284
236- Logger::info ("Starting Command Processor... " );
237- if (!$ this ->commandProcessor instanceof CommandProcessor){
238- $ this ->commandProcessor = new CommandProcessor ();
239- $ this ->commandProcessor ->registerDefaultCommands ();
240- }
285+ Logger::info ("Starting multi-threading scheduler... " );
286+ $ this ->scheduler = new Scheduler ($ this ->classLoader , $ this , $ this ->config ->get ("async-workers " , 2 ));
241287
242- Logger::info ("Starting multi-threading scheduler... " );
243- $ this ->scheduler = new Scheduler ($ this ->classLoader , $ this , $ this ->config ->get ("async-workers " , 2 ));
288+ $ mdr = $ this ->config ->get ("wsmdr " );
289+ if ($ mdr ["enabled " ]){
290+ Logger::info ("Starting WraithSpire module dependency resolver... " );
291+ $ this ->moduleManager ->registerModuleDependencyResolver (
292+ new WraithSpireMDR ($ this ->moduleManager , $ mdr ["remote-database " ], $ mdr ["modules " ]));
293+ }
244294
245- $ mdr = $ this ->config ->get ("module-dependency-resolver " );
246- if ($ mdr ["enabled " ]){
247- Logger::info ("Starting WraithSpire module dependency resolver... " );
248- $ this ->moduleManager ->registerModuleDependencyResolver (
249- new WraithSpireMDR ($ this ->moduleManager , $ mdr ["remote-database " ], $ mdr ["modules " ]));
250- }
295+ if ($ this ->config ->get ("auto-load-modules " , true )){
296+ $ this ->moduleManager ->loadModules ();
297+ }
298+ $ this ->properties ->loadModules ($ this ->moduleManager );
251299
252- if ($ this ->config ->get ("auto-load-modules " , true )){
253- $ this ->moduleManager ->loadModules ();
254- }
300+ $ this ->displayTitle = $ this ->config ->get ("display-title " , true );
255301
256- $ this ->displayTitle = $ this ->config ->get ("display-title " , true );
302+ if (($ mdr = $ this ->moduleManager ->getModuleDependencyResolver ()) instanceof WraithSpireMDR){
303+ /** @var WraithSpireMDR $mdr */
304+ $ mdr ->init ();
305+ }
257306
258- if (($ mdr = $ this ->moduleManager ->getModuleDependencyResolver ()) instanceof WraithSpireMDR){
259- /** @var WraithSpireMDR $mdr */
260- $ mdr ->init ();
261- }
307+ Logger::notice ("Done! Type 'help' for help. " );
262308
263- Logger:: notice ( " Done! Type 'help' for help. " );
309+ $ this -> properties -> runCommands ( $ this -> commandProcessor );
264310
265- if ($ useMainThreadTick ){
266- $ this ->tick ();
267- }
311+ if ($ useMainThreadTick ){
312+ $ this ->tick ();
268313 }
269314 }catch (\Throwable $ e ){
270315 Logger::logException ($ e );
@@ -279,11 +324,10 @@ public function getCommandProcessor() : CommandProcessor{
279324 return $ this ->commandProcessor ;
280325 }
281326
282- //main thread tick, not recommend for modules
283327 private function tick (){
284328 while (!$ this ->shutdown ){
285329 $ this ->update ();
286- usleep (self ::$ usleep );
330+ usleep (self ::$ tickInterval );
287331 }
288332
289333 //shutdown!
0 commit comments