From 94ee001dfd039dd7071b25e5d63c2f158c2dc267 Mon Sep 17 00:00:00 2001 From: Mahmood Ahmad Date: Thu, 18 Apr 2024 21:12:40 +0200 Subject: [PATCH] adding support for plugins --- docs/commands.md | 6 +-- docs/config.md | 2 +- docs/introduction.md | 6 ++- docs/plugins.md | 20 +++++++++ docs/structure.PNG | Bin 19239 -> 50305 bytes src/Commands/MakeModule.php | 6 +-- src/Commands/MakeUnit.php | 7 ++-- src/Core/Base/File.stub | 6 +-- src/Core/Base/Module.stub | 38 +++++++++++++----- src/Core/Module/ModuleServiceProvider.stub | 4 +- src/Core/Module/Unit.stub | 2 +- src/Core/Module/UnitApiController.stub | 9 +++-- src/Core/Module/UnitFactory.stub | 4 +- src/Core/Module/UnitRequest.stub | 2 +- src/Core/Module/UnitResource.stub | 2 +- src/Core/Module/UnitTest.stub | 4 +- src/Core/Module/UnitWebController.stub | 2 +- src/Core/Module/api.stub | 2 +- src/Core/Module/web.stub | 2 +- src/Generators/Payloads/Commands/Base.php | 8 ++++ src/Generators/Payloads/Commands/Install.php | 4 +- .../Payloads/Commands/MakeModule.php | 30 +++++++++----- src/Generators/Payloads/Commands/MakeUnit.php | 37 +++++++++++------ src/Logic/FileManipulator.php | 11 +++++ src/Logic/StringManipulator.php | 1 + src/Processors/Factory.php | 4 +- src/config.php | 11 +++++ src/lang/en/install.php | 2 +- src/lang/en/module.php | 4 +- tests/Unit/InstallTest.php | 8 ++-- 30 files changed, 173 insertions(+), 71 deletions(-) create mode 100644 docs/plugins.md diff --git a/docs/commands.md b/docs/commands.md index be67a6f..3433258 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -8,12 +8,12 @@ Summary of all the commands: ### Create new module -`php artisan laragine:module ModuleName` +`php artisan laragine:module ModuleName` | optional: add `--plugins` to be in the Plugins directory ### Initialize the unit -`php artisan laragine:unit UnitName --module=ModuleName --init` +`php artisan laragine:unit UnitName --module=ModuleName --init` | optional: add `--plugins` to be in the Plugins directory ### Create all the related stuff for the unit -`php artisan laragine:unit UnitName --module=ModuleName` \ No newline at end of file +`php artisan laragine:unit UnitName --module=ModuleName` | optional: add `--plugins` to be in the Plugins directory \ No newline at end of file diff --git a/docs/config.md b/docs/config.md index 3d68d33..f38a4d1 100644 --- a/docs/config.md +++ b/docs/config.md @@ -1,3 +1,3 @@ ## Config -You will notice in any module you generate, a `config` directory, so basically you can add configuration for the module, and you can access it in this form: `config('core_modulename.some_key')` for example: `config('core_base.api_key')` \ No newline at end of file +You will notice in any module you generate, a `config` directory, so basically you can add configuration for the module, and you can access it in this form: `config('coreOrplugins_moduleName.some_key')` for example: `config('core_base.api_key')` another example `config('plugins_sale.tax')` \ No newline at end of file diff --git a/docs/introduction.md b/docs/introduction.md index 522360b..70760ce 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -22,7 +22,9 @@ It's very important to know why to use Laragine, here is why: ![Structure](structure.png) -The `Base` module is the main module in which every new module will be created (keep reading the other sections to know how), will be derived from. +The `Base` module in the `core` directory is the main module in which every new module will be created (keep reading the other sections to know how), will be derived from. + +Also it's worth mentioning that there is another directory called `plugins` for overriding current modules, adding extra functionalities or adding new modules to the system. It's also very important to understand the following terms: @@ -34,7 +36,7 @@ It's also very important to understand the following terms: * Laragine currently is working on **Laravel 8.x, 9.x, 10.x and 11.x** -* Laragine directory will be in the root directory under `Core` directory +* Laragine directory will be in the root directory under `core` directory and as mentioned above there is also `plugins` directory * The system response (including errors response if you applied what's in `Error Handling` section) to any request will be as in below examples (`status_code` is the http status code): diff --git a/docs/plugins.md b/docs/plugins.md new file mode 100644 index 0000000..76230e5 --- /dev/null +++ b/docs/plugins.md @@ -0,0 +1,20 @@ +## Plugins + +**Note:** it's important to read the module and unit sections first + +To create a new module or a new unit to the plugins directory you can do so by adding `--plugins` option to the commands + +Here is a complete example: + +Creating New module: +```bash +php artisan laragine:module Todo --plugins +``` +Initializing a unit: +```bash +php artisan laragine:unit Task --module=Todo --init --plugins +``` +Publishing the unit: +```bash +php artisan laragine:unit Task --module=Todo --plugins +``` \ No newline at end of file diff --git a/docs/structure.PNG b/docs/structure.PNG index c77b0db058f6ccd5ef189a8881078c700943bf59..aba8fd675a21f94b0c2014cf39322dff7443e067 100644 GIT binary patch literal 50305 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

^k6Z8Ijo3K zFNkh=MAT-u6AsqIwE{x*l4XN}7uD$vU`*k6E7|dY?Ialcx)5CAV7r5Xgj3w--%~1q zNjf#Gxl@Hic0pDk=*K)=+ZdpW$c4A{YF^@ma9- zPuI1oW!R9Cy5d$);MOgm4vP4>aO8COGi{Q zW1}2elSYyjO4gMy#JSvgg3-X0lrQzUHhTJ3c9UO{y(fRKCc~vApnpfvY&e%wK>~~P zv2+jG`s6^-WuSfwQwLVYx}+zWm&&_?f=U8H~i^3z;_97J@o{C0xVBUDGTq#=TmO4=K!QG&n84&y@IGBSeA|?6}RnSEO2Tretn7 zepfi6^zXa^6*{?pE*ZsSu9L?=gQIX6O{yQ+6(#77Gi8ZVbx^E!gr0U=GJ}r9?E3Fp z|6gh6{ZIA(|9|6Th7$={$1ahToy>+&UN0-h$V{)Y_bhv5L}Y7Q8I^JzD~BSRWRI-u zO;%Fh`}631`TPOjAG>tvqH;VQ_s4Bq?`T&4mL#DE8@Sb!{XAbYF;r?I6sUr!i%>fZ%P)o z3su=kWD8VfAEC|)jZ|)o633E|27?6=CDg|gOJ&P=Dn`6tTzm9(`Iy77*q0m%dOYQb z(8}kilXeYO9CXVn*>fMx^&esIXuX;x_iv%P%pMSM<|=Q$kfKj>j9j^_lTQewLJB_p z4g4|Tv@Amz5sQOkkp~Jis>y7~jNo#HYQ(G1#iPPXWvn-pmZ1?wCxsdoTS~dd20>XT zaKq83$C@6yjQ&978mOmb#YI}Gg~H@jSy_syM(b0tmonO#c91O-K9Snq&?Hx0xwwz{ zt@)9eGKyYUNu3A^C z8~W$S>y58#S-UC9^RU+kqPlXtr9uJ~hZ`$l=&6n*IId=FawS*m6DP0WOdiWjX>Tc^ zO^(A!j1g*7H2?ZhZxD3}Ot1%VigReWbq^z*|6jieC2rBo*IP0B?7fr}KaF#py%e1| zCJ&bqf;M&z$#;>Syuhm`s9VurI{#tfau3cC|I2x!ru+HD$C)1nisg=N4>ek@8ug_1 zDU92oV!};e`^%O=${`8gMGcdV?tR5+jkTgQarXUYRr8ubj^S@U_yF~==Epg4j0EivH|Oj>{sF(FqrY(rO|P~) z)x`EpBwTkS+$a5}aabS;HdTi&XI`C_cEn0&u3O-8XZq4$fXJV0cI?AKK|+Az#`k6< z!z%3o9m8H0|9XqhtW|YVlwM_qPN^z^-<11Y4*DY?=r*pmWK4~kr0$U z#ljKRiC$qk21_FGf)15dW9`JD+?jX0tM>S@M8kz1>bC&_CC2rMBm08F3(rxM`&yeb zr@iBz4bzb616Nbpk6qELNFn-UZ6+cWP$8X)xJ}D~F39Uo$5Z}<*{JLn@IH&kK)@u5 zFduh9B7eDeDha{niNcg%F@`YI^YBH>!B>W7w)TQ$6D6WU|K;M^b~)crhK7t!U!|oU zC6j^(R7y%Z^66R1WLzwE35%3BG|{|NjA6_t=0UFMbt2;II3YjsWj}bW%wbSZIiG1V zY+aB_N(aT$_@6TI`;4S@|7Ua9(KT}awK-Y^ems1n^c`0kH&sv?G9~mo^+8Zx2Z9)3 z@Q$Lq;PX^nWi8>-B{GXF2nxNzvYY9yTV7uJR%4oQGd&*ws|vC8?H(|%Rk9n=Ao{uj z(xli2al^a-NQEZ(!}e3oZteFhE>tF$k?H(h60Yz&{7&D^rKnaS90YAT9?r z-Bzm5lNPbs4&}#1_9cU%Rz@er#dQCSSvb9wNa;TX#6mkIAy88^-yDTQ+z_&g0+_04*Atj7|9zrOYiag}Km|axvirOX$`mf|1Hd z=G8oHTPX;L#N0pCaj~C6gJRMcg4E1HU+E2k)&<^ohSd}<0L<5;ykzC6N$k}g%)CLM_pK5!YoI1CmCVNr?Wurn(O|9S++DuDji)Q^( zr#|)xLg!`Lv`I|RvObGG8vAUZ)8J#;(Z*QuMA9iu)7O*1aFjgH?#N@3x2qjxL<56TejA;yxU$>UkN`CU-9g4-nGZ)%T`nqN4CGY-@d&qDtlwUls=_X1qegSz1~ zb$w}CQN0ab-{yA{&6#nA9@#a(`OcV7@t|PfDjIb{WDTqf(*1IJVM;T|RQXoiDMSZl zqmd>Tq>_3PYEms$IuxV+tdwds>Jdj1;h)@!P>vgP$}ugI1_uV?kSamVa#Z@UxyZno?o{X&;t`DNA(mg&3mq>F(&(fas8gJvFi z^7O_2zrio=oFynnb#`$)_xR5@r$LD=LUio$xOg7=g_eiiOQH)dnLhPwW z-}UH@wKBy`3n9CHAb@t?W9di4g&@>#o&*uT`rp%iFOLK)kxR`u39hYq399AOV%4>R zi-d|NmN;x}c9Fz-IAuDWAm6yGvgQ<|%rw2{Wmd>*FRGoOusX*Z7AiLb7EBf|iiUXa zxLhOLzVy91f8RgR^_=rJv%sze&CpE*Vaev*l#)i;e_rx-0qAzG&^+316G% zsCGEsQRKtil}%s$w8xC)#wDcevZheUxx6R4y5lv%ut>CqOf@ls+Pb1&QNBeQUNwzp znAL2j6Xn?6{Ct^(PnP&ryglOHIk?}!&zKXcu^i`^S}>JOEh zt}o2cCVbYWXbto8&1rqe=O%dJ3nOotQQe9k-0VNyx}dp76T5~Gb^55^^vkSI#)!Rg z<&r#})>79-e}dlShA2F`hSUiJ`UpSpshK?rc@i4ho+v}#gl4KTlFRQ3f=h=OL~pr+ z^S~Qb1iLhgEO&(yD`)l^G`JmG*C+LC9`{4-Bv^>?e9V#!EDL`qW^n-t_Ti3vUY|6; z*FIl%iEpT>ixLC;z;I+~)3zmF@b>f3!y$#VAN6o6F5GrKv7(*trNtw&(u1~}^VPdi zsGm3WBxtsEjYe*_qfdAQBL+wNL}NVX8B$Wx4Hz-xlRsw`DgRni53VzV<*Vx z)R2|j2hq?t?1ZsrOTi@+(dRQ}>MFJ%>0v^tL9_B&eEFl&N0bXR0{ot!bD;y=S0Y2K zagtEW@g?YBtzVlZ$@`04`9{Lc7GUAz`{tj7>JJ-X$!!y2>V>mjMv<*|LFh1;)fY)j zRN=Q2xka`;{H7yZLV%i});oq_;>D&ySHnIL1&d5-Ib`Ky>t?9xygM{)g~8gC+& zp}G5Nk^E_f4n=-#o5`0o(l=25X4LFg_Z(%o@)bp4(;p}3@U0qa8q)R|1rK*jtBRlv zuZ&Dz-6rMpAk{$ck7+9~z+8=6axyw@$wJS9wKYRu+Yd@hSGmp+)}&!#cC%fcc!5Fz z6n;QHq)Rm~si|mb=y1ny{TrP!aa|EoNr1+whvN1 z(wVNaOYkwc0yR)Wk_1vKJpz&{%8O^0y@mi?nT0tNfhicycgd)KT6!ebH7z{yVB2%>^^}xplv~q>85Tp%;eXBHwKgIS%tG6kX6g3&wfw#3&U)qnl_N|SlmXR zb+&G){3UPFfud|(=59C|3+z;Xq=j7)>GJl9~aG-u^t&z6H1CrJ%p&1 ziuZjC!F3{4(Bt~Q2NAxNY9ytkqAHd&^KV>LjPZ($ z{fdPHt=M1KS2%K<@8)c#5RdaDfyoDUghif@AjKTW;HICti7ER2Wo~JgfLe^?x!X>LLLJ*ou{Vc_AIWv>y^}_eE1^5nI4KHR;)ofL; z5W-F$VraS7N;K~Vb;X0uO8d<>_1s#C!oYa~O!w|C zil!@IF!PQ%$iF1mh_wvXrW6j?ZmgF{z7S4fbxgvOSAFk!WsyUe5?i#d&^@b*jRi>D z%PfqVPvWU>1X!ub=KFhZw)YOZ7Y%4oZa$&X*C6&58Hz>%uYlzch0m7Juq!#Y^Gt+N znD1iQ`f&wdm{N@I#DBpyrV)MK-?euO4)@`}_qP*PQLI%va?e+qm=9t#Wg0j=MeVzVSlMT8W6+l+1iR*r3yNdsfJ2|zz znw+FP+q~y!@3@b-G>a?g)tUd1aS?ZLx)^ijC-meEJYx0jwWizOLLMzY3KkL>A~d`? zE%&WP$Fvbx=JiLv%GK7iNha1@?h}>gAnh^9mp@P?fQ1sfRcui3(9UvA`;~bWE*Uxs z?tI7`m7mCWe&-Ad=!H>4IQtE64GQ=cUQ4N5*)NY|sk|obWJ=;0gzGq99 z++`yANmec|o^Eh#z2WXKzo{+rzIj2($J?L;7nQ<(aZ{|v;6$*~pSR@)jlThYjj&d{ z3UiW`(zOubvye4Z;w?njm`Re%t&}Urq1_WT)(3*9ZbB($DUhT6hmzA2xf0 zSjGCLK@ik%jojAyHp9u!#G&=)ZN-Os(sid}2+tGUrh6pvJ}-Gcw?8U1-DMa~83;xY zXJwz>$p;eVw^%oQ!5k8Rg>F*!!M`v3XVBvFJtau|3Ja#?+~Q_^jlgv7lL^W{bwtO$ zOw`MKn9?AlLFEb!ICE-7`II{4&-HFy=)F!fY0 z3)!3(oOg}}-Vi2jD0W4ptpwS5y{u4ISEmQ;Ql-u%4cswS)>H7>O9C0Jpb5?nF@y`M zuaP=;BJ8Qvh#;8qdG?COcW-?(%o2KEK;(8*Z@qu`;2QzNRTct^N*%jrbV9LlOL2>p^%ON1CY=XV)~YuJh1#E6(k=O3qs zFu7u~F)?+1WgK@5Kc$8`gE9^Tr*joI+Ebj5hj8;kCngRfVtdPjkNl(xYAXB zc7q>LcAMr9sPSuO!P`S3IxQ)!xjW7^l!o`28It>oH?>A9pQZS}vZ%z5Pd^hx$SZ8% zwhsPC6BseDBEJCMR&Y3K$YE^d{kh{OCVali{T+SfNhy_i-3L0w-ksmnQQccEXDZ!V zrS0C_tJkZ&cUInOsnoV}h3`oKha>hhzd~Y$`-nO0$TYAVbR>&^wZ^pZ9^w5F%vM{) zYI}0)8Yk>tfL$l+FWh<96V(MU*x;DwwxtEEm@_ack`v`q93}JWW`pymuYd0O6qz1&; zR)1v7Z6G(s$@zxH#umuv7U4>|N)eO%OY38$DrkK-ha91`g{Ph$Qo2BvYfJZpqPf7( z?nG#g2>Nw$aj|g56Um1@&4%8e(bpQ7Hg9wynGyp48!Wd@h@zyF@y#%R$Y2!#=ZS%r zk=_esR?_W-UhU$q6BQuYNrI8?QR4yV$fMih*q(TfEl;s&7o_Jh8sI`;R)&?ga}Po8;Vv%esC0vb zoPuH;v9U`yL-kTvLtK{goJ(r&RnJQqO00Ht1F4Vnau~UrN~n0G@UW3UI=9Cp<~^{F zKVwtQnlHF$K}Cg7^8-%)42e&lKNs!`SFS>I?Tn(=655vO4W0Lloe7}2+LJH*-nGGk z1%6>9u^oj%U4iut20934G`?ugMDgA)Jmko``XbkiTu(O|-Ib$ryI@NVD06hT;0ft0MI43TgBb^Yjw15Hpl8cC}1U7lRo-L-F-_!Qkb zB)T(IZ6o=8w7VOx>D0QQAan5&vWlZb^!O_vo_U$(_|z*?CSoyN4R+knPBpM99g8fY zwZ2IyRrw_vhO>9!2k8j+`y-e)jOr62nt}LE`I(C@{D;a5Ia3?1*sEVh(qzoA&Ya~a-Xw=_LM>}tSRM6jEbW2 z1yjV3knk3-_S+5nOlI1bp{$iZiGOS8M;R-x}%! zf*{b~j_aIvVIB+Ej7vUq{aV#4aVt{u>$_hT5daTwM63y~EK>rMqmlU3ry>qr>x zFb$*%>2h(#yk()by{dT;b#r}6KkC6df`krvtzq!|2uu~-M~{YtVV&XAz!)_SPt?5B zx;7Q02^KXMubyH{Ms`2;OH}G$=i%_lPWk}-yg8!&A_)nJzov$&K^2`ssiX(F+Hr}m z4DWu5Z-L{l#N~3<&-HCJfc2Gc zcj}^xbU^kw$@&UBChoCdgS9@VYyxZlt^@KRqklJZ{zI7qh8TEOiQrrNlcT8iD(%HI RBm6Z;G%sG$C{eQv`F}}4O3?rS literal 19239 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'name')); + $command = GeneratorFactory::create($this, 'MakeModule', $this->argument('name'), $this->option('plugins')); $command->run(); } } diff --git a/src/Commands/MakeUnit.php b/src/Commands/MakeUnit.php index f900b4d..a5d9a4d 100644 --- a/src/Commands/MakeUnit.php +++ b/src/Commands/MakeUnit.php @@ -12,14 +12,14 @@ class MakeUnit extends Command * * @var string */ - protected $signature = 'laragine:unit {name} {--module=} {--I|init}'; + protected $signature = 'laragine:unit {name} {--module=} {--I|init} {--P|plugins}'; /** * The console command description. * * @var string */ - protected $description = 'Create new unit'; + protected $description = 'Create a new unit'; /** * Create a new command instance. @@ -48,7 +48,8 @@ public function handle() 'MakeUnit', $this->argument('name'), $this->option('module'), - $this->option('init') + $this->option('init'), + $this->option('plugins') ); $command->run(); diff --git a/src/Core/Base/File.stub b/src/Core/Base/File.stub index 4715e3c..9e7597e 100644 --- a/src/Core/Base/File.stub +++ b/src/Core/Base/File.stub @@ -9,11 +9,11 @@ trait File * * @param string $dir * @param string $module - * @param boolean $is_core + * @param boolean $is_plugins */ - protected function loadFiles($dir, $module = 'base', $is_core = true) + protected function loadFiles($dir, $module = 'base', $is_plugins = false) { - $module_root_dir = $is_core ? 'core' : 'plugins'; + $module_root_dir = $is_plugins ? 'plugins' : 'core'; $this->loadRoutesFrom($dir . '/routes/web.php'); $this->loadRoutesFrom($dir . '/routes/api.php'); diff --git a/src/Core/Base/Module.stub b/src/Core/Base/Module.stub index d6063ed..6fc06fa 100644 --- a/src/Core/Base/Module.stub +++ b/src/Core/Base/Module.stub @@ -2,23 +2,43 @@ namespace Core\Base\Traits\ServiceProvider; +use Illuminate\Support\Str; + trait Module { /** * register the service provider for the module - * - * @param string $excluded_directory - * @param string $root_namespace */ - private function registerModules($excluded_directory = 'Base', $root_namespace = 'Core') + private function registerModules() { - $base_path = base_path() . '/core'; - foreach (glob($base_path.'/*/ModuleServiceProvider.php') as $file) { + // Register the core modules + $root_namespace = 'Core'; + $excluded_directory = 'Base'; + $root_path = config('laragine.root_dir'); + + foreach (glob($root_path.'/*/ModuleServiceProvider.php') as $file) { if (!preg_match("/core\/{$excluded_directory}/i", $file)) { - $namespace = str_replace('/', '\\', str_replace('.php', '', $file)); - $namespace = explode('core\\', $namespace)[1]; - $this->app->register($root_namespace . '\\' . $namespace); + $this->registerModuleServiceProvider($file, $root_namespace); } } + + // Register the plugins modules + $plugins_namespace = 'Plugins'; + $plugins_path = config('laragine.plugins_dir'); + + foreach (glob($plugins_path.'/*/ModuleServiceProvider.php') as $file) { + $this->registerModuleServiceProvider($file, $plugins_namespace); + } + } + + /** + * handle registering the module service provider + */ + private function registerModuleServiceProvider($file, $root_namespace) + { + $root_namespace_lower_case = Str::lower($root_namespace); + $namespace = str_replace('/', '\\', str_replace('.php', '', $file)); + $namespace = explode("{$root_namespace_lower_case}\\", $namespace)[1]; + $this->app->register($root_namespace . '\\' . $namespace); } } diff --git a/src/Core/Module/ModuleServiceProvider.stub b/src/Core/Module/ModuleServiceProvider.stub index 614f7f4..717b0fa 100644 --- a/src/Core/Module/ModuleServiceProvider.stub +++ b/src/Core/Module/ModuleServiceProvider.stub @@ -1,6 +1,6 @@ loadFiles(__DIR__, '#UNIT_NAME_LOWER_CASE#'); + $this->loadFiles(__DIR__, '#UNIT_NAME_LOWER_CASE#'#IS_PLUGINS#); } /** diff --git a/src/Core/Module/Unit.stub b/src/Core/Module/Unit.stub index cce6c69..2e652b6 100644 --- a/src/Core/Module/Unit.stub +++ b/src/Core/Module/Unit.stub @@ -1,6 +1,6 @@ 'api', 'middleware' => []], function () { # V1 - Route::namespace('Core\#MODULE_NAME#\Controllers\API\V1')->prefix('v1')->name('api.v1.')->group(function () { + Route::namespace('#SELECTED_DIRECTORY#\#MODULE_NAME#\Controllers\API\V1')->prefix('v1')->name('api.v1.')->group(function () { #*** Ex: START: #UNIT_NAME# ***# // Route::apiResource('#UNIT_NAME_PLURAL_LOWER_CASE#', '#UNIT_NAME#Controller'); #*** END: #UNIT_NAME# ***# diff --git a/src/Core/Module/web.stub b/src/Core/Module/web.stub index 23adc35..4a14d24 100644 --- a/src/Core/Module/web.stub +++ b/src/Core/Module/web.stub @@ -1,6 +1,6 @@ prefix('admin')->name('admin.')->group(function () { +Route::namespace('#SELECTED_DIRECTORY#\#MODULE_NAME#\Controllers\Web')->prefix('admin')->name('admin.')->group(function () { #*** Ex: START: #UNIT_NAME# ***# // Route::resource('#UNIT_NAME_PLURAL_LOWER_CASE#', '#UNIT_NAME#Controller')->except([ // 'store', 'update', 'destroy' diff --git a/src/Generators/Payloads/Commands/Base.php b/src/Generators/Payloads/Commands/Base.php index 11738fc..1f24af1 100644 --- a/src/Generators/Payloads/Commands/Base.php +++ b/src/Generators/Payloads/Commands/Base.php @@ -28,6 +28,13 @@ class Base implements GeneratorInterface */ protected $root_dir; + /** + * the plugins dir + * + * @var string + */ + protected $plugins_dir; + /** * init * @@ -40,6 +47,7 @@ public function __construct(Command $command, $args) $this->command = $command; $this->args = $args; $this->root_dir = config('laragine.root_dir'); + $this->plugins_dir = config('laragine.plugins_dir'); } /** diff --git a/src/Generators/Payloads/Commands/Install.php b/src/Generators/Payloads/Commands/Install.php index b551727..a0923c2 100644 --- a/src/Generators/Payloads/Commands/Install.php +++ b/src/Generators/Payloads/Commands/Install.php @@ -15,7 +15,7 @@ public function run() { $allow_publish = true; if (FileManipulator::exists($this->root_dir)) { - if ($this->command->confirm(__('laragine::install.root_dir_exists'), true)) { + if ($this->command->confirm(__('laragine::install.already_installed'), true)) { $allow_publish = true; } else { $allow_publish = false; @@ -25,6 +25,8 @@ public function run() if ($allow_publish) { $this->publishRootDirectory(); + + FileManipulator::generateDir($this->plugins_dir); } } diff --git a/src/Generators/Payloads/Commands/MakeModule.php b/src/Generators/Payloads/Commands/MakeModule.php index 2d7a105..1effc53 100644 --- a/src/Generators/Payloads/Commands/MakeModule.php +++ b/src/Generators/Payloads/Commands/MakeModule.php @@ -7,6 +7,13 @@ class MakeModule extends Base { + /** + * selected directory (root or plugins) + * + * @var string + */ + protected $selected_dir; + /** * run the logic * @@ -14,11 +21,12 @@ class MakeModule extends Base */ public function run() { - $allow_publish = true; - $module_collection = StringManipulator::generate($this->args[0]); - $module_dir = $this->root_dir . '/' . $module_collection['studly']; + $allow_publish = true; + $module_collection = StringManipulator::generate($this->args[0]); + $this->selected_dir = $this->args[1] ? $this->plugins_dir : $this->root_dir; + $module_dir = $this->selected_dir . '/' . $module_collection['studly']; - if (!FileManipulator::exists($this->root_dir)) { + if (!FileManipulator::exists($this->selected_dir)) { $allow_publish = false; $this->command->error(__('laragine::module.run_install')); } @@ -45,9 +53,9 @@ public function run() */ protected function publishModuleDirectory($module_collection) { - $source_dir = __DIR__ . '/../../../Core/Module'; - $destination_dir = $this->root_dir . '/'. $module_collection['studly']; - $files = config('laragine.module.main_files'); + $source_dir = __DIR__ . '/../../../Core/Module'; + $destination_dir = $this->selected_dir . '/'. $module_collection['studly']; + $files = config('laragine.module.main_files'); $search = [ 'file' => ['stub'], @@ -55,7 +63,9 @@ protected function publishModuleDirectory($module_collection) '#UNIT_NAME#', '#UNIT_NAME_PLURAL_LOWER_CASE#', '#UNIT_NAME_LOWER_CASE#', - '#MODULE_NAME#' + '#MODULE_NAME#', + '#SELECTED_DIRECTORY#', + '#IS_PLUGINS#' ] ]; @@ -65,7 +75,9 @@ protected function publishModuleDirectory($module_collection) $module_collection['studly'], $module_collection['plural_lower_case'], $module_collection['singular_lower_case'], - $module_collection['studly'] + $module_collection['studly'], + $this->args[1] ? 'Plugins' : 'Core', + $this->args[1] ? ', true' : '', ] ]; diff --git a/src/Generators/Payloads/Commands/MakeUnit.php b/src/Generators/Payloads/Commands/MakeUnit.php index a8420a8..808985d 100644 --- a/src/Generators/Payloads/Commands/MakeUnit.php +++ b/src/Generators/Payloads/Commands/MakeUnit.php @@ -12,31 +12,38 @@ class MakeUnit extends Base /** * module names (collection) * - * @var + * @var string[] */ public $module_collection; /** * module dir * - * @var + * @var string */ public $module_dir; /** * unit names (collection) * - * @var + * @var string[] */ public $unit_collection; /** * init flag * - * @var + * @var bool */ public $init; + /** + * selected directory (root or plugins) + * + * @var string + */ + protected $selected_dir; + /** * run the logic * @@ -47,11 +54,12 @@ public function run() $this->unit_collection = StringManipulator::generate($this->args[0]); $this->module_collection = StringManipulator::generate($this->args[1]); $this->init = $this->args[2]; - $this->module_dir = $this->root_dir . '/' . $this->module_collection['studly']; + $this->selected_dir = $this->args[3] ? $this->plugins_dir : $this->root_dir; + $this->module_dir = $this->selected_dir . '/' . $this->module_collection['studly']; $validation = new UnitValidation($this->command); $validation->checkModule($this->module_dir) ->checkUnit($this->module_dir, $this->unit_collection, $this->init) - ->checkAttributes($this->root_dir, $this->module_collection, $this->unit_collection); + ->checkAttributes($this->selected_dir, $this->module_collection, $this->unit_collection); if ($validation->allow_proceed) { $this->publishUnit(); @@ -69,12 +77,13 @@ protected function publishUnit() $this->publishUnitInitCase(); } else { $file_name = $this->unit_collection['studly'] . '.json'; - $data = $this->root_dir . '/' . $this->module_collection['studly'] . '/data/' . $file_name; + $data = $this->selected_dir . '/' . $this->module_collection['studly'] . '/data/' . $file_name; $unit_data = [ - 'module_dir' => $this->module_dir, - 'module_collection' => $this->module_collection, - 'unit_collection' => $this->unit_collection + 'module_dir' => $this->module_dir, + 'module_collection' => $this->module_collection, + 'unit_collection' => $this->unit_collection, + 'selected_directory' => $this->args[3] ? 'Plugins' : 'Core', ]; $processors = ['Resource', 'Request', 'Factory', 'Migration']; Factory::create($unit_data, $processors); @@ -89,14 +98,15 @@ protected function publishUnit() */ private function publishUnitInitCase() { $source_dir = __DIR__ . '/../../../Core/Module'; - $destination_dir = $this->root_dir . '/'. $this->module_collection['studly']; + $destination_dir = $this->selected_dir . '/'. $this->module_collection['studly']; $files = config('laragine.module.unit_main_folders'); $search = [ 'file' => ['stub', 'Api', 'Web', 'Unit'], 'content' => [ '#UNIT_NAME#', - '#MODULE_NAME#' + '#MODULE_NAME#', + '#SELECTED_DIRECTORY#', ] ]; @@ -104,7 +114,8 @@ private function publishUnitInitCase() { 'file' => ['php', '', '', $this->unit_collection['studly']], 'content' => [ $this->unit_collection['studly'], - $this->module_collection['studly'] + $this->module_collection['studly'], + $this->args[3] ? 'Plugins' : 'Core', ] ]; diff --git a/src/Logic/FileManipulator.php b/src/Logic/FileManipulator.php index 9040b04..06e4741 100644 --- a/src/Logic/FileManipulator.php +++ b/src/Logic/FileManipulator.php @@ -66,6 +66,17 @@ public static function generate($source_dir, $destination_dir, $files, $search = } } + /** + * generate directory or directories + * + * @param string $destination_dir + * @param integer $mode + */ + public static function generateDir($destination_dir, $mode = 0775) : void + { + File::makeDirectory("$destination_dir", $mode, true, true); + } + protected static function deleteFilesWithMatchSpecificPrefix($destination, $prefix) { foreach (glob("$destination".'/*') as $migration_file) { if(strpos($migration_file, $prefix) !== false) { diff --git a/src/Logic/StringManipulator.php b/src/Logic/StringManipulator.php index 111db4f..60b3ebf 100644 --- a/src/Logic/StringManipulator.php +++ b/src/Logic/StringManipulator.php @@ -10,6 +10,7 @@ class StringManipulator * get all possible shapes of a string * * @param string $string + * @return string[] */ static public function generate(string $string): array { diff --git a/src/Processors/Factory.php b/src/Processors/Factory.php index 8350aad..33b3735 100644 --- a/src/Processors/Factory.php +++ b/src/Processors/Factory.php @@ -46,6 +46,7 @@ public static function create($units_data, array $processors = []) "#REQUEST_STR#", "#FACTORY_STR#", "#MIGRATION_STR#", + '#SELECTED_DIRECTORY#', ] ]; $unit_plural_lower = $units_data['unit_collection']['plural_lower_case']; @@ -60,7 +61,8 @@ public static function create($units_data, array $processors = []) $data['resource_str'], $data['request_str'], $data['factory_str'], - $data['migration_str'] + $data['migration_str'], + $units_data['selected_directory'] ] ]; diff --git a/src/config.php b/src/config.php index a92f476..5648fd9 100644 --- a/src/config.php +++ b/src/config.php @@ -13,6 +13,17 @@ 'root_dir' => base_path() . '/core', + /* + |-------------------------------------------------------------------------- + | The Plugins Directory + |-------------------------------------------------------------------------- + | + | The plugins directory that will be used to push the modules to + | + */ + + 'plugins_dir' => base_path() . '/plugins', + /* |-------------------------------------------------------------------------- | The Base diff --git a/src/lang/en/install.php b/src/lang/en/install.php index 6245404..cb5b749 100644 --- a/src/lang/en/install.php +++ b/src/lang/en/install.php @@ -11,7 +11,7 @@ | */ - 'root_dir_exists' => 'The root directory already exists, do you want to override it?', + 'already_installed' => 'The root directory and the plugins direcotory already exist, do you want to override both directories?', 'root_dir_not_overwritten' => 'Existing root directory was not overwritten', 'success' => 'The installation done successfully!' diff --git a/src/lang/en/module.php b/src/lang/en/module.php index 6bf08dc..cfc8ea1 100644 --- a/src/lang/en/module.php +++ b/src/lang/en/module.php @@ -11,8 +11,8 @@ | */ - 'run_install' => 'Please run install command first', - 'exists' => 'the module directory already exists, do you want to override it?', + 'run_install' => 'Please run the install command first', + 'exists' => 'The module directory already exists, do you want to override it?', 'not_overwritten' => 'Existing module directory was not overwritten', 'success' => 'Module created successfully!', diff --git a/tests/Unit/InstallTest.php b/tests/Unit/InstallTest.php index 57ac555..c7cdebe 100644 --- a/tests/Unit/InstallTest.php +++ b/tests/Unit/InstallTest.php @@ -22,23 +22,23 @@ public function test_the_install_command_create_root_directory() $this->assertTrue(FileManipulator::exists($this->root_dir)); } - public function test_when_root_directory_exists_users_can_choose_to_override_it() + public function test_when_the_package_already_installed_users_can_choose_to_override_the_files() { $command = $this->artisan('laragine:install'); $command->expectsConfirmation( - __('laragine::install.root_dir_exists'), 'yes' + __('laragine::install.already_installed'), 'yes' ); $command->expectsOutput(__('laragine::install.success')); } - public function test_when_root_directory_exists_users_can_choose_to_not_override_it() + public function test_when_the_package_already_installed_users_can_choose_to_not_override_the_files() { $command = $this->artisan('laragine:install'); $command->expectsConfirmation( - __('laragine::install.root_dir_exists'), 'no' + __('laragine::install.already_installed'), 'no' ); $command->expectsOutput(__('laragine::install.root_dir_not_overwritten'));