├── .gitignore ├── README.md ├── app ├── Http │ ├── Controllers │ │ ├── Actions │ │ │ └── ActionController.php │ │ ├── Api │ │ │ └── ApiController.php │ │ ├── Shortcodes │ │ │ └── ShortcodeController.php │ │ └── SideMenu │ │ │ └── SideMenuController.php │ └── Middleware │ │ └── TestMiddleware.php └── Providers │ └── TestServiceProvider.php ├── artisan ├── assets ├── css │ ├── app.css │ └── index.css └── js │ ├── app.js │ ├── index.js │ ├── react │ └── app.js │ └── vue │ └── app.js ├── bootstrap ├── Activation.php ├── Bootstrap.php ├── DeActivation.php └── System │ ├── Action.php │ ├── Api.php │ ├── Application.php │ ├── Cache.php │ ├── Config.php │ ├── Controller.php │ ├── Enqueue.php │ ├── Helpers │ ├── App.php │ ├── Response.php │ ├── View.php │ └── helpers.php │ ├── Providers │ ├── ActionServiceProvider.php │ ├── ApiServiceProvider.php │ ├── EnqueueServiceProvider.php │ ├── InitialDataProvider.php │ ├── ShortcodeServiceProvider.php │ └── SideMenuServiceProvider.php │ ├── Session.php │ ├── Shortcode.php │ └── SideMenu.php ├── composer.json ├── config └── app.php ├── database └── Migration.php ├── enqueues └── enqueue.php ├── hooks ├── action.php └── shortcode.php ├── package-lock.json ├── package.json ├── plugin-master.php ├── resources ├── js │ ├── react │ │ ├── Home.jsx │ │ └── app.js │ └── vue │ │ ├── App.vue │ │ └── app.js ├── scss │ └── app.scss └── views │ ├── action.php │ ├── index.php │ ├── react-app.php │ └── vue-app.php ├── routes ├── api.php └── sidemenu.php └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /vendor 3 | /node_modules 4 | composer.lock 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PluginMaster (an Application Development Framework for WordPress) 2 | # What is PluginMaster? 3 |
4 | « PluginMaster is an Application development framework for WordPress. It changes the flavor of plugin development.» 5 |6 | 7 | # Code Features 8 |
wp-content/plugins/
directory in your WordPresscomposer create-project plugin-master/plugin-master
OR composer
29 | create-project plugin-master/plugin-master project_name
index.php
page in root folder.config.php
, located in app/config/
37 | directory (You can add any configuration related data in config.php
)
38 | Migrations are typically paired with the PluginMaster schema builder to build your application's database schema. When plugin activates, all migration migrate to the database and when deactivate plugin, all table will be deleted. You just need to define the migration file.
46 | Migration file directory :database/migrations/
47 |
48 | Structure
49 |
50 | The migration file name has 2 parts : 51 |
Also class name will be the same as the table name.58 | 59 |
File name like :1_demo_users.php
. 55 | This means,1
is for sequence maintain anddemo_users
is the table name and also class 56 | name. the table prefix will be set from the schema builder. 57 |
A migration class contains one method: up. The up method is used to add new tables to your database.
60 | Sample Migration File 61 |File Name: 1_demo_users.php
64 | use App\system\schema\Schema;
65 |
66 | class demo_users
67 | {
68 | public function up()
69 | {
70 | return Schema::create('demo_users', function (Schema $column) {
71 | $column->intIncrements('id');
72 | $column->string('name')->nullable() ;
73 | $column->string('mobile') ;
74 | $column->string('email')->nullable();
75 | $column->text('description')->nullable();
76 | $column->enum('status', ['ok', 'not']);
77 | $column->integer('user_id')->unsigned()->nullable();
78 | $column->foreign('user_id')->on('demo_users.id');
79 | $column->timestamp('student_created_at')->default('current_timestamp')->onUpdateTimeStamp();
80 | });
81 | }
82 |
83 | }
84 |
85 |
86 |
87 | Schema Functions
88 | intIncrements($column)
: integer (10), auto_increment, primary key bigIntIncrements($column)
: bigint (20), auto_increment, primary key integer($column, $length = 10)
: integer (10) bigInt($column, $length = 20)
: bigint (20) decimal($column, $length = 20, $places = 2)
: decimal (20, 2) text($column)
: text enum($column, $values)
: enum( value, value) ($values must be array). date($column)
: date timestamp($column)
: timestamp nullable()
: null unsigned()
: unsigned default($value)
: default 'value' (if $value == 'CURRENT_TIMESTAMP' OR 'current_timestamp' then set CURRENT_TIMESTAMP
onUpdateTimeStamp()
: ON UPDATE CURRENT_TIMESTAMP foreign($column)
: make CONSTRAINT for foreign key on($reference)
: $reference means table.column. check following example.
104 |
105 |
106 | $column->integer('user_id')->unsigned();
107 | $column->foreign('user_id')->on('demo_users.id');
108 |
109 |
110 | Create a WP side menu in easy way. just declare your side nav with controller, method &, etc.
118 | Side Menu declaration file : routes/sidenav.phpSample Structure
121 |
122 |
123 | $sidenav->main('DemoPlugin', ["icon" => "dashicons-admin-site", "as" => 'DemoController@main', "position" => 500, "removeFirstSubmenu" => true], function ($sidenav) {
124 | $sidenav->sub('Dashboard', ["title" => "Dashboard", "as" => 'DemoController@sub']);
125 | });
126 |
127 |
128 | The main method
has three parameters..
@
sign) The sub method
has two parameters.
@
sign) In146 | Optional index: position (default is 500), removeFirstSubmenu ( for delete first submenu, default false)DemoController@main
:DemoController
is controller name 143 | located atapp/controller/sidenav/
andmain
is method name of 144 | DemoController 145 |
The sub method
has two parameters.
@
sign) In160 | 161 |DemoController@main
:DemoController
is controller name 157 | located atapp/controller/sidenav/
andsub
is method name of 158 | DemoController 159 |
Create WP rest route in easy way.
170 | Rest Route declaration file : routes/route.php
171 |
Rest Route Controller must declare inside : app/controller/api/
API Namespace: Namespace maintain by api_namespace
of config.php. It's located in app/config/config.php
173 |
Sample Structure
175 |
176 | $route->get('dashboard/{id?}', 'DemoController@dashboard');
177 | $route->post('add-note', 'DemoController@addNote');
178 | $route->post('update-note', 'DemoController@addNote', true);
179 |
180 |
181 | DemoController
is controller name and dashboard
is method name , located in app/controller/api/
directory
182 | PluginMaster has two methods: GET, POST
183 |Both Route has 3 parts/parameters
184 |{parameter_name}
{parameter_name?}
function dashboard($variable)
then $variable['param_name']
X-WP-Nonce: token
PluginMaster's database query builder provides a convenient, fluent interface to run 202 | database queries. It can be used to perform most database operations in your application.
203 | Namespace:PluginMaster\DB\DB;
DB::table('users')->first();
DB::table('users')->get();
where($column, $value )
:
214 |
215 |
216 | DB::table('users')
217 | ->where('id', 1)
218 | ->get()
219 |
220 | DB::table('users')
221 | ->where(function($query){
222 | $query->where('id', 1);
223 | $query->orWhere('name', "name");
224 | })
225 | ->get()
226 |
227 | orWhere($column, $value)
:
229 | DB::table('users')
230 | ->where('id', 1)
231 | ->orWhere('name', "name")
232 | ->get()
233 |
234 | DB::table('users')
235 | ->where('id', 1)
236 | ->orWhere(function($query){
237 | $query->where('field', 'value);
238 | $query->where('field', 'value);
239 | })
240 | ->first()
241 |
242 | whereRaw($query)
:
244 | DB::table('users')
245 | ->whereRaw('id = 1')
246 | ->first()
247 | orWhereRaw($query)
:
250 | DB::table('users')
251 | ->whereRaw('id = 1')
252 | ->orWhereRaw('id = 1')
253 | ->first()
254 | orderBy($columns, $direction)
:
258 | DB::table('users')
259 | ->orderBy('id', 'desc')
260 | DB::table('users')
261 | ->orderBy('id,name', 'desc')
262 | groupBy($columns)
:
265 | DB::table('users')
266 | ->groupBy('id')
267 | DB::table('users')
268 | ->groupBy('id,name')
269 | limit($number)
:
273 | DB::table('users')
274 | ->where('id', 1)
275 | ->limit(number)->get()
276 | offset($number)
:
279 | DB::table('users')
280 | ->where('id', 1)
281 | ->limit(number)->offset(number)->get()
282 | select($fields)
:
285 | DB::table('users')
286 | ->select('id,name')
287 | ->get()
288 | insert($data)
:
290 | DB::table('users')
291 | ->insert(['name' => "demo"])
292 | update($data,$where)
:
294 | DB::table('users')
295 | ->where('id', 1)
296 | ->update(['name' => "demo"])
297 | delete($where)
:
299 | DB::table('users')
300 | ->where('id', 1)
301 | ->delete()
302 | join($table, $first, $operator = null, $second = null) (INNER JOIN)
:
305 | DB::table('demo_notes as n')
306 | ->join('demo_users as u', 'u.id', '=', 'n.user_id')
307 | ->first()
308 |
309 | DB::table('demo_notes as n')
310 | ->join('demo_users as u', function($query){
311 | $query->on( 'u.id', '=', 'n.user_id')
312 | $query->orOn( 'u.id', '=', 'n.user_id')
313 | })
314 | ->first()
315 |
316 |
317 | DB::table('demo_notes as n')
318 | ->join('demo_users as u', function($query) use($request){
319 | $query->on( 'u.id', '=', 'n.user_id')
320 | $query->onWhere( 'u.id', '=', $request->id)
321 | })
322 | ->first()
323 |
324 |
325 |
326 | Note: Must use table alias for using join or leftJoin.327 |
leftJoin($table, $first, $operator = null, $second = null) (LEFT JOIN)
: Same as
330 | join()
331 | transaction()
:
334 | DB::startTransaction(function(){
335 | DB::table('demo_notes')
336 | ->insert([
337 | "note" => "Hello",
338 | ]);
339 | })
340 |
341 | DB::startTransaction(function(DB $query){
342 | $query->table('demo_notes')
343 | ->insert([
344 | "note" => "Hello",
345 | ]);
346 | })
347 |
348 | Easy way to add css and js file to application
357 | Enqueue Declaration file : enqueue/enqueue.phpFunctions
360 | headerScript($path) :
: $enqueue->headerScript('assets/js/index.js');
headerScriptCdn($path) :
: $enqueue->headerScriptCdn('http://alemran.me/js/index.js');
footerScript($path) :
: $enqueue->footerScript('assets/js/index.js');
footerScriptCdn($path) :
:$enqueue->footerScriptCdn('http://alemran.me/js/index.js');
style($path) :
:$enqueue->style('assets/css/style.css');
styleCdn($path) :
:$enqueue->style('assets/js/index.css');
csrfToken($handler, $objectName):
:
371 |
372 | $enqueue->footerScript('assets/js/index.js','DemoScriptIndex');
373 | $enqueue->csrfToken('DemoScriptIndex','corsData');
374 |
375 |
376 | DemoScriptIndex
is Handler and corsData
is object name. You can access api ROOT url and token corsData object.
Note: CSRF token must define under a js file's Handler.378 |
$enqueue->hotScript('file_name.js')
for Webpack (DevServer) hot mode with Vue js (main url will be http://localhost:8080/file_name.js
)
381 | Create and manage shortcode in easy way
388 | Shortcode Declaration file : shortcode/shortcode.php $shortCode->add('pluginmaster', 'ShortCodeController@index' ) ;
392 | pluginmaster
is the name of shortcode. ShortCodeController
is controller and index
is method name.
Method Sample
394 |
395 | public function index(){
396 | $data = DB::table('table_name')->get();
397 | return view('shortcode', compact('data')) ;
398 | }
399 |
400 |
401 |
402 |
403 | # 7. Request Handling System
404 |
405 |
406 | Easy way to access request data from native or AJAX request
407 | No need isset function to check. just call$request->name
, it will return null if not
408 | set Example
410 |
411 | use App\system\request\Request;
412 | $request = new Request();
413 | echo $request->name;
414 |
415 |
416 | Access Header: $request->header(name)
Get All Data as Array: $request->all()
Check Request Method : if($request->isMethod('post')){}
Validate data is easy in PluginMaster
425 |Manually Validate ( not compatible for REST API) :
426 |
427 |
428 | use App\system\Validator;
429 | $validator = Validator::make($request, [
430 | 'ID' => 'required|number|limit:10,11',
431 | 'name' => 'required|wordLimit:10,20',
432 | 'slug' => 'required|noSpecialChar',
433 | ]);
434 |
435 | if ($validator->fails()) {
436 | $errors = $validator->errors();
437 | }
438 |
439 |
440 |
441 | For checking validation fail: $validator->fail();
.
For Validation errors: $validator->errors()
.
You can use $validator->flashErrors();
for flashing errors as flash session and you can access all flashed errors through formErrors()
global function. Also you can access single field error through formError(field name).
In controller
447 |
448 | use App\system\Validator;
449 | $validator = Validator::make($request, [
450 | 'ID' => 'required|number|limit:10,11',
451 | 'name' => 'required|wordLimit:10,20',
452 | 'slug' => 'required|noSpecialChar',
453 | ]);
454 |
455 |
456 | if ($validator->fails()) {
457 | $errors = $validator->formErrors();
458 | }
459 |
460 |
461 | In view file
462 |
463 | if ( count(formErrors()) ) :
464 | <div class="alert alert-danger">
465 | <ul>
466 | <php foreach (formErrors() as $key=>$value): ?>
467 | <li> <php echo $value; ?> </li>
468 | <php endforeach; ?>
469 | </ul>
470 | </div>
471 | <php endif; ?>
472 |
473 | <input type="text" name="email">
474 | <p> <php formError('email'); ?> </p>
475 |
476 | OR
477 | You can pass errors to view file with compact
478 |479 | view('path to view', compact('errors')); 480 |481 | 482 |
Stopping On Validation Failure (Compatible for REST API) : If validation fail then stop other execution, just return validation errors.
483 |Example:
484 |
485 | use App\system\request\Request;
486 | $request = new Request();
487 | $request->validate([
488 | 'name' => 'required',
489 | ]);
490 |
491 |
492 | Error will return as like following:
493 |
494 | [
495 | "message" => "Validation failed",
496 | "errors" => [
497 | "name" => "name Field is required"
498 | ]
499 | ]
500 |
501 |
502 | Available Validation:
503 | Build Vue JS application with your plugin
521 |Configuration
522 | Configuration file located in root directory as webpack.config.js
.
Vue js files Default directory is : resources/js
.
Run : npm run dev
. (for development mode)
Run : npm run watch
. (for on-change build)
Run : npm run hot
. (for on-change build and reload) (default hot mode(webpack dev server) listen from port 8080. if you run this command , you must declare $enqueue->hotScript('file_name.js')
in enqueue .
Configuration for Build
528 |
529 |
530 | const buildConfig = [
531 | {
532 | source: 'resources/js/app.js',
533 | outputDir: 'assets/js', // targeted output directory name
534 | outputFileName: 'app' // can be with .js extension
535 | }
536 | ];
537 |
538 |
539 | # OR may be
540 |
541 |
542 | const buildConfig = [
543 | {
544 | source: 'resources/js/app.js',
545 | outputDir: 'assets/js', // targeted output directory name
546 | outputFileName: 'app' // can be with .js extension
547 | } ,
548 | {
549 | source: 'resources/js/nextApp.js',
550 | outputDir: 'assets/js', // targeted output directory name
551 | outputFileName: 'nextApp' // can be with .js extension
552 | }
553 | ];
554 |
555 |
556 |
557 |
558 |
559 | # 10. Global Functions
560 |
561 |
562 |
563 | view()
: root of view file : resources/view/
. you have to pass only file name withour extention . Example: view('home/index')
.
565 | compact
566 |
567 | $title = "......";
568 | $data = [] ;
569 | return view('home/index', compact('title', 'data'))
570 |
571 | json($data, $code)
: for returning as json with status code config($key)
: for returning configuration data. you can set/ change configuration data from : add/config/config.php
current_url()
: for current url
576 | formErrors()
: for form validation errors as array formError($field_name)
: for single field validation error session_flush($key, $value = null)
: for getting and setting flush session session($key, $value = null)
: for getting and setting session Session::flush(key)
for getting onetime Session and Session::flush(key, value)
589 | for setting onetime session.
590 | Flush session unset after page loading completed591 |
Session::flush(key, value)
594 | Session::get(key)
597 | Session::forget(key)
600 | The MIT License (MIT)
605 | 606 |Developed by : AL EMRAN
607 | 608 | # Support for this project 609 | Assalamu Alikum ! You can donate for the project. 610 | 611 | [](https://beerpay.io/emrancu/PluginMaster) [](https://beerpay.io/emrancu/PluginMaster?focus=wish) 612 | -------------------------------------------------------------------------------- /app/Http/Controllers/Actions/ActionController.php: -------------------------------------------------------------------------------- 1 | "This message from PluginMaster Action."]); 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /app/Http/Controllers/Api/ApiController.php: -------------------------------------------------------------------------------- 1 | $this->request->url(), 16 | "name" => $request->get_param('name'), 17 | ]); 18 | } 19 | 20 | public function getProductsName(WP_REST_Request $request): string 21 | { 22 | return Response::json([ 23 | "url" => $this->request->url(), 24 | "name" => $request->get_param('name'), 25 | "dynamic" => "This is dynamic api", 26 | ]); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app/Http/Controllers/Shortcodes/ShortcodeController.php: -------------------------------------------------------------------------------- 1 | This message from PluginMaster ShortCode. read more..'; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/Http/Controllers/SideMenu/SideMenuController.php: -------------------------------------------------------------------------------- 1 | boot(); 48 | }, 100); 49 | 50 | /** 51 | * destroy onetime flush session 52 | */ 53 | Session::destroyFlush(); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /bootstrap/DeActivation.php: -------------------------------------------------------------------------------- 1 | add($name, $callback, $priority); 24 | } 25 | 26 | private static function handler(): ActionHandler 27 | { 28 | if (!static::$actionHandler) { 29 | static::$actionHandler = App::get(ActionHandler::class); 30 | } 31 | 32 | return static::$actionHandler; 33 | } 34 | 35 | /** 36 | * add only wp_ajax_ action and resolve callback 37 | * @note no need to pass 'wp_ajax_' 38 | * @param string $name 39 | * @param $callback 40 | * @param int $priority 41 | */ 42 | public static function ajax(string $name, $callback, int $priority = 10): void 43 | { 44 | static::handler()->add('wp_ajax_' . $name, $callback, $priority); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /bootstrap/System/Api.php: -------------------------------------------------------------------------------- 1 | register($api, $dynamic); 104 | } 105 | 106 | /** 107 | * @param string $route 108 | * @param string|callable $callback 109 | * @param bool $public 110 | */ 111 | public static function post(string $route, $callback, bool $public = false): void 112 | { 113 | static::registerAPI([$route, 'POST', $callback, $public]); 114 | } 115 | 116 | /** 117 | * @param string $route 118 | * @param string|callable $callback 119 | * @param bool $public 120 | */ 121 | public static function put(string $route, $callback, bool $public = false): void 122 | { 123 | static::registerAPI([$route, 'PUT', $callback, $public]); 124 | } 125 | 126 | /** 127 | * @param string $route 128 | * @param string|callable $callback 129 | * @param bool $public 130 | */ 131 | public static function patch(string $route, $callback, bool $public = false): void 132 | { 133 | static::registerAPI([$route, 'PATCH', $callback, $public]); 134 | } 135 | 136 | /** 137 | * @param string $route 138 | * @param string|callable $callback 139 | * @param bool $public 140 | */ 141 | public static function delete(string $route, $callback, bool $public = false): void 142 | { 143 | static::registerAPI([$route, 'DELETE', $callback, $public]); 144 | } 145 | 146 | /** 147 | * @param string $route 148 | * @param string|callable $callback 149 | * @param bool $public 150 | */ 151 | public static function all(string $route, $callback, bool $public = false): void 152 | { 153 | static::registerAPI([$route, 'GET, POST, PUT, PATCH, DELETE', $callback, $public]); 154 | } 155 | 156 | /** 157 | * @param string $route 158 | * @param string $class 159 | * @param bool $public 160 | */ 161 | public static function dynamic(string $route, string $class, bool $public = false): void 162 | { 163 | static::registerAPI([$route, 'GET, POST, PUT, PATCH, DELETE', $class, $public], true); 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /bootstrap/System/Application.php: -------------------------------------------------------------------------------- 1 | setBasePath($path); 57 | $this->setAppConfig(); 58 | $this->setVersion($this->config('version')); 59 | } 60 | 61 | /** 62 | * @set application base path ( Plugin directory path ) 63 | * @set pluginFile 64 | * @set pluginBasename 65 | * @param string $path 66 | * @return mixed 67 | */ 68 | public function setBasePath(string $path): void 69 | { 70 | $this->pluginFile = $path; 71 | $this->basePath = untrailingslashit(plugin_dir_path($path)); 72 | $this->pluginBasename = plugin_basename($path); 73 | } 74 | 75 | /** 76 | * set ConfigHandler instance inside container 77 | * and set config path for ConfigHandler to resolve config data 78 | * @return mixed 79 | * @throws \ReflectionException 80 | */ 81 | private function setAppConfig(): void 82 | { 83 | // create instance 84 | $configHandler = $this->get(ConfigHandler::class); 85 | $configHandler->setPath($this->configPath()); 86 | 87 | // set app config data from config/app.php 88 | $this->config = $configHandler->resolveData('app'); 89 | } 90 | 91 | /** 92 | * @param string|null $path 93 | * @return mixed 94 | */ 95 | public function configPath(string $path = null): string 96 | { 97 | return $this->basePath . DIRECTORY_SEPARATOR . 'config' . ($path ? DIRECTORY_SEPARATOR . $path : $path); 98 | } 99 | 100 | /** 101 | * @param string $version 102 | * @return mixed 103 | */ 104 | public function setVersion(string $version): void 105 | { 106 | $this->version = $version; 107 | } 108 | 109 | /** 110 | * get app config data 111 | * just pass config/app.php 's array key to access (Like config('provider') - do not need to pass 'app.providers') ) 112 | * @param $key 113 | * @return mixed 114 | */ 115 | public function config($key) 116 | { 117 | $keys = explode('.', $key); 118 | 119 | $finalData = $this->config; 120 | 121 | foreach ($keys as $key) { 122 | $finalData = $finalData[$key] ?? ''; 123 | } 124 | 125 | return $finalData; 126 | } 127 | 128 | /** 129 | * @param null $path 130 | * @return Application 131 | * @throws \ReflectionException 132 | */ 133 | public static function getInstance($path = null): ?Application 134 | { 135 | if (null === self::$instance) { 136 | self::$instance = new self($path); 137 | } 138 | 139 | return self::$instance; 140 | } 141 | 142 | /** 143 | * Get the version number of the application. 144 | * 145 | * @return string 146 | */ 147 | public function version(): string 148 | { 149 | return $this->version; 150 | } 151 | 152 | /** 153 | * Get the plugin base name. 154 | * 155 | * @return string 156 | */ 157 | public function baseName(): string 158 | { 159 | return $this->pluginBasename; 160 | } 161 | 162 | /** 163 | * @param string|null $path 164 | * @return mixed 165 | */ 166 | public function basePath(string $path = null): string 167 | { 168 | return $this->basePath . ($path ? DIRECTORY_SEPARATOR . $path : $path); 169 | } 170 | 171 | /** 172 | * @param string $path 173 | * @return mixed 174 | */ 175 | public function asset(string $path): string 176 | { 177 | return $this->baseUrl() . 'assets/' . $path; 178 | } 179 | 180 | /** 181 | * @param null $path 182 | * @return mixed 183 | */ 184 | public function baseUrl($path = null): string 185 | { 186 | return trailingslashit(plugins_url('/', $this->pluginFile)) . ($path ? '/' . $path : $path); 187 | } 188 | 189 | /** 190 | * @param string|null $path 191 | * @return mixed 192 | */ 193 | public function bootstrapPath(string $path = null): string 194 | { 195 | return $this->basePath . DIRECTORY_SEPARATOR . 'bootstrap' . ($path ? DIRECTORY_SEPARATOR . $path : $path); 196 | } 197 | 198 | /** 199 | * @param string|null $path 200 | * @return mixed 201 | */ 202 | public function appPath(string $path = null): string 203 | { 204 | return $this->basePath . DIRECTORY_SEPARATOR . 'app' . ($path ? DIRECTORY_SEPARATOR . $path : $path); 205 | } 206 | 207 | /** 208 | * @param string $path 209 | * @return mixed 210 | */ 211 | public function databasePath(string $path = ''): string 212 | { 213 | return $this->basePath . DIRECTORY_SEPARATOR . 'database' . ($path ? DIRECTORY_SEPARATOR . $path : $path); 214 | } 215 | 216 | /** 217 | * @param string|null $path 218 | * @return mixed 219 | */ 220 | public function viewPath(string $path = null): string 221 | { 222 | return $this->basePath . DIRECTORY_SEPARATOR . 'resources/views' . ($path ? DIRECTORY_SEPARATOR . $path : $path); 223 | } 224 | 225 | /** 226 | * @param string|null $path 227 | * @return mixed 228 | */ 229 | public function assetPath(string $path = null): string 230 | { 231 | return $this->basePath . DIRECTORY_SEPARATOR . 'assets' . ($path ? DIRECTORY_SEPARATOR . $path : $path); 232 | } 233 | 234 | /** 235 | * @param string|null $path 236 | * @return mixed 237 | */ 238 | public function enqueuePath(string $path = null): string 239 | { 240 | return $this->basePath . DIRECTORY_SEPARATOR . 'enqueues' . ($path ? DIRECTORY_SEPARATOR . $path : $path); 241 | } 242 | 243 | /** 244 | * @param string|null $path 245 | * @return mixed 246 | */ 247 | public function hookPath(string $path = null): string 248 | { 249 | return $this->basePath . DIRECTORY_SEPARATOR . 'hooks' . ($path ? DIRECTORY_SEPARATOR . $path : $path); 250 | } 251 | 252 | /** 253 | * @param string|null $path 254 | * @return mixed 255 | */ 256 | public function routePath(string $path = null): string 257 | { 258 | return $this->basePath . DIRECTORY_SEPARATOR . 'routes' . ($path ? DIRECTORY_SEPARATOR . $path : $path); 259 | } 260 | 261 | /** 262 | * @param string|null $path 263 | * @return mixed 264 | */ 265 | public function hooksPath(string $path = null): string 266 | { 267 | return $this->basePath . DIRECTORY_SEPARATOR . 'hooks' . ($path ? DIRECTORY_SEPARATOR . $path : $path); 268 | } 269 | 270 | public function cachePath($path = null): string 271 | { 272 | return wp_upload_dir()['basedir'] . DIRECTORY_SEPARATOR . $this->config( 273 | 'slug' 274 | ) . ($path ? DIRECTORY_SEPARATOR . $path : ''); 275 | } 276 | 277 | /** 278 | * Boot the application's service providers. 279 | * 280 | * @return void 281 | * @throws \ReflectionException 282 | */ 283 | public function boot(): void 284 | { 285 | if ($this->isBooted()) { 286 | return; 287 | } 288 | 289 | $this->bootProvider(); 290 | $this->booted = true; 291 | } 292 | 293 | /** 294 | * Determine if the application has booted. 295 | * 296 | * @return bool 297 | */ 298 | public function isBooted(): bool 299 | { 300 | return $this->booted; 301 | } 302 | 303 | /** 304 | * boot service providers 305 | * @return void 306 | * @throws \ReflectionException 307 | */ 308 | protected function bootProvider(): void 309 | { 310 | /** 311 | * run system service providers 312 | */ 313 | foreach ($this->config('system_providers') as $serviceProvider) { 314 | if (method_exists($serviceProvider, 'boot')) { 315 | $this->call([$serviceProvider, 'boot']); 316 | } 317 | } 318 | 319 | /** 320 | * run your service providers for your modules / functionalities 321 | */ 322 | foreach ($this->config('providers') as $serviceProvider) { 323 | if (method_exists($serviceProvider, 'boot')) { 324 | $this->call([$serviceProvider, 'boot']); 325 | } 326 | } 327 | } 328 | 329 | } 330 | -------------------------------------------------------------------------------- /bootstrap/System/Cache.php: -------------------------------------------------------------------------------- 1 | get($fileName, $directory); 22 | } 23 | 24 | /** 25 | * @return CacheHandler 26 | */ 27 | private static function getHandler(): CacheHandler 28 | { 29 | if (!static::$cacheHandlerInstance) { 30 | $app = App::get(); 31 | static::$cacheHandlerInstance = $app->get(CacheHandler::class)->setAppVersion( 32 | $app->version() 33 | )->setCachePath($app->cachePath()); 34 | } 35 | 36 | return static::$cacheHandlerInstance; 37 | } 38 | 39 | /** 40 | * @param string $fileName 41 | * @param $content 42 | * @param null $directory 43 | * @return bool|int 44 | */ 45 | public static function set(string $fileName, $content, $directory = null): bool 46 | { 47 | return static::getHandler()->createFile($fileName, $content, $directory); 48 | } 49 | 50 | /** 51 | * @return bool|int 52 | */ 53 | public static function reset(): bool 54 | { 55 | return static::getHandler()->reset(); 56 | } 57 | 58 | /** 59 | * @param string $fileName 60 | * @param string|null $directory 61 | * @return bool 62 | */ 63 | public static function check(string $fileName, string $directory = null): bool 64 | { 65 | return static::getHandler()->check($fileName, $directory); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /bootstrap/System/Config.php: -------------------------------------------------------------------------------- 1 | resolveData($key); 22 | } 23 | 24 | /** 25 | * @return ConfigHandler 26 | */ 27 | private static function getInstance() 28 | { 29 | if (!self::$instance) { 30 | self::$instance = App::get(ConfigHandler::class); 31 | } 32 | 33 | return self::$instance; 34 | } 35 | 36 | /** 37 | * @param $key 38 | */ 39 | public static function set($key) 40 | { 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /bootstrap/System/Controller.php: -------------------------------------------------------------------------------- 1 | request = App::get()->get(Request::class); 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /bootstrap/System/Enqueue.php: -------------------------------------------------------------------------------- 1 | data[] = [ 70 | 'id' => $id, 71 | 'path' => $path, 72 | 'script' => true, 73 | 'hook' => static::$hook, 74 | ]; 75 | 76 | return $this; 77 | } 78 | 79 | /** 80 | * @param array $deps 81 | * @return Enqueue 82 | */ 83 | public function dependency(array $deps): self 84 | { 85 | $this->data[$this->getCurrentIndex()]['dependency'] = $deps; 86 | 87 | return $this; 88 | } 89 | 90 | private function getCurrentIndex(): int 91 | { 92 | return count($this->data) - 1; 93 | } 94 | 95 | /** 96 | * @return Enqueue 97 | */ 98 | public function inHeader(): self 99 | { 100 | $this->data[$this->getCurrentIndex()]['in_footer'] = false; 101 | 102 | return $this; 103 | } 104 | 105 | /** 106 | * @return Enqueue 107 | */ 108 | public function inFooter(): self 109 | { 110 | $this->data[$this->getCurrentIndex()]['in_footer'] = true; 111 | 112 | return $this; 113 | } 114 | 115 | /** 116 | * @param string $ver 117 | * @return Enqueue 118 | */ 119 | public function version(string $ver): self 120 | { 121 | $this->data[$this->getCurrentIndex()]['version'] = $ver; 122 | 123 | return $this; 124 | } 125 | 126 | /** 127 | * @param array $attributes 128 | * @return Enqueue 129 | */ 130 | public function attributes(array $attributes): self 131 | { 132 | $this->data[$this->getCurrentIndex()]['attributes'] = $attributes; 133 | 134 | return $this; 135 | } 136 | 137 | /** 138 | * @param string $cdnPath 139 | * @param string|null $id 140 | * @return Enqueue 141 | */ 142 | public function scriptCdn(string $cdnPath, ?string $id = null): self 143 | { 144 | $this->data[] = [ 145 | 'id' => $id, 146 | 'path' => $cdnPath, 147 | 'cdn' => true, 148 | 'script' => true, 149 | 'hook' => static::$hook, 150 | ]; 151 | 152 | return $this; 153 | } 154 | 155 | /** 156 | * @param string $path 157 | * @param string|null $id 158 | * @param string $media 159 | * @return Enqueue 160 | */ 161 | public function style(string $path, ?string $id = null, string $media = 'all'): self 162 | { 163 | $this->data[] = [ 164 | 'id' => $id, 165 | 'path' => $path, 166 | 'media' => $media, 167 | 'hook' => static::$hook, 168 | ]; 169 | 170 | return $this; 171 | } 172 | 173 | /** 174 | * @param string $cdnPath 175 | * @param string|null $id 176 | * @param string $media 177 | * @return Enqueue 178 | */ 179 | public function styleCdn(string $cdnPath, ?string $id = null, string $media = 'all'): self 180 | { 181 | $this->data[] = [ 182 | 'id' => $id, 183 | 'path' => $cdnPath, 184 | 'media' => $media, 185 | 'cdn' => true, 186 | 'hook' => static::$hook, 187 | ]; 188 | 189 | return $this; 190 | } 191 | 192 | /** 193 | * @param string $handle 194 | * @param string $objectName 195 | * @param $data 196 | */ 197 | public function localizeScript(string $handle, string $objectName, $data): void 198 | { 199 | $this->data[] = [ 200 | 'param' => [$handle, $objectName, $data], 201 | 'type' => 'localizeScript', 202 | 'hook' => static::$hook, 203 | ]; 204 | } 205 | 206 | /** 207 | * @param string $data 208 | * @param array $option 209 | */ 210 | public function inlineScript(string $data, array $option = []): void 211 | { 212 | $this->data[] = [ 213 | 'param' => [$data, $option], 214 | 'type' => 'inlineScript', 215 | 'hook' => static::$hook, 216 | ]; 217 | } 218 | 219 | /** 220 | * @param string $data 221 | * @param string $handle 222 | */ 223 | public function inlineStyle(string $data, string $handle = ''): void 224 | { 225 | $this->data[] = [ 226 | 'param' => [$data, $handle], 227 | 'type' => 'inlineStyle', 228 | 'hook' => static::$hook, 229 | ]; 230 | } 231 | 232 | private function getData(): array 233 | { 234 | return $this->data; 235 | } 236 | 237 | public function __call($method, $args): array 238 | { 239 | if($method == 'getData'){ 240 | return $this->getData(); 241 | } 242 | 243 | return []; 244 | } 245 | } 246 | 247 | 248 | -------------------------------------------------------------------------------- /bootstrap/System/Helpers/App.php: -------------------------------------------------------------------------------- 1 | basePath(); 24 | } 25 | 26 | /** 27 | * @param null $class 28 | * @return Application|null 29 | */ 30 | public static function get($class = null) 31 | { 32 | if (is_null($class)) { 33 | return Application::getInstance(); 34 | } 35 | 36 | return Application::getInstance()->get($class); 37 | } 38 | 39 | /** 40 | * access only config/app.php 's config data 41 | * no need to pass app just like: config('slug') for app slug name 42 | * @param $key 43 | * @return Application|null 44 | */ 45 | public static function config($key) 46 | { 47 | return static::get()->config($key); 48 | } 49 | 50 | /** 51 | * @return mixed|string 52 | */ 53 | public static function baseUrl() 54 | { 55 | return static::get()->baseUrl(); 56 | } 57 | 58 | /** 59 | * @return mixed|string 60 | */ 61 | public static function textDomain() 62 | { 63 | return static::get()->config('slug'); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /bootstrap/System/Helpers/Response.php: -------------------------------------------------------------------------------- 1 | resolvePHP($viewInstance->resolvePath($path), $data); 21 | } 22 | 23 | 24 | /** 25 | * @param $path 26 | * @return string 27 | */ 28 | protected function resolvePath($path): string 29 | { 30 | $viewPath = ''; 31 | 32 | foreach (explode('.', $path) as $path) { 33 | $viewPath .= '/' . $path; 34 | } 35 | 36 | return $viewPath; 37 | } 38 | 39 | /** 40 | * @param string $path 41 | * @param array $data 42 | * @return string 43 | */ 44 | protected function resolvePHP(string $path, array $data = []): string 45 | { 46 | if (count($data)) { 47 | extract($data); 48 | } 49 | 50 | return include App::get()->viewPath() . $path . '.php'; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /bootstrap/System/Helpers/helpers.php: -------------------------------------------------------------------------------- 1 | get($class); 23 | } 24 | } 25 | 26 | 27 | if (!function_exists('plugin_master_asset')) { 28 | /** 29 | * @param $path 30 | * @return string 31 | */ 32 | 33 | function plugin_master_asset($path): string 34 | { 35 | return Application::getInstance()->asset($path); 36 | } 37 | } 38 | 39 | 40 | if (!function_exists('plugin_master_config')) { 41 | /** 42 | * Get config. 43 | * @param $key 44 | * @return mixed 45 | */ 46 | 47 | function plugin_master_config($key) 48 | { 49 | return Config::get($key); 50 | } 51 | } 52 | 53 | 54 | if (!function_exists('plugin_master_url')) { 55 | /** 56 | * Get config. 57 | * @return mixed 58 | */ 59 | 60 | function plugin_master_url() 61 | { 62 | return App::get()->baseUrl(); 63 | } 64 | } 65 | 66 | 67 | if (!function_exists('plugin_master_view')) { 68 | /** 69 | * Get view file. 70 | * @param $path 71 | * @param array $data 72 | * @param bool $noTemplate 73 | * @return mixed 74 | */ 75 | 76 | function plugin_master_view($path, $data = [], $noTemplate = false) 77 | { 78 | return View::render($path, $data, $noTemplate); 79 | } 80 | } 81 | 82 | 83 | if (!function_exists('plugin_master_domain')) { 84 | /** 85 | * Get text domain / slug. 86 | */ 87 | 88 | function plugin_master_domain() 89 | { 90 | return App::get()->config('slug'); 91 | } 92 | } 93 | 94 | if (!function_exists('plugin_master_slug')) { 95 | /** 96 | * generate slug from string. 97 | */ 98 | 99 | function plugin_master_slug(string $string) 100 | { 101 | return str_replace(' ', '-', strtolower($string)); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /bootstrap/System/Providers/ActionServiceProvider.php: -------------------------------------------------------------------------------- 1 | get(ActionHandler::class); 22 | 23 | $actionHandler->setAppInstance($app) 24 | ->setControllerNamespace($this->controllerNamespace) 25 | ->loadFile($app->hooksPath('action.php')); 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /bootstrap/System/Providers/ApiServiceProvider.php: -------------------------------------------------------------------------------- 1 | get(ApiHandler::class); 23 | 24 | $apiHandler->setAppInstance($app) 25 | ->setNamespace($app->config('api_namespace')) 26 | ->setControllerNamespace($this->controllerNamespace) 27 | ->setMiddleware($app->config('middleware')) 28 | ->loadRoutes($app->routePath('api.php')); 29 | }); 30 | 31 | add_action('rest_api_init', function () use ($app) { 32 | 33 | /** @var \PluginMaster\Foundation\Api\ApiHandler $apiHandler */ 34 | $apiHandler = $app->get(ApiHandler::class); 35 | $apiHandler->apiGenerate(); 36 | 37 | }, 100); 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /bootstrap/System/Providers/EnqueueServiceProvider.php: -------------------------------------------------------------------------------- 1 | get(EnqueueHandler::class); 22 | 23 | /** @var \PluginMaster\Bootstrap\System\Enqueue $enqueue */ 24 | $enqueue = $app->get(Enqueue::class); 25 | 26 | $enqueueHandler->setAppInstance($app)->loadEnqueueFile($app->enqueuePath('enqueue.php')); 27 | 28 | add_action('init', function () use ($enqueueHandler, $enqueue) { 29 | $enqueueHandler->initEnqueue($enqueue); 30 | }, 12); 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /bootstrap/System/Providers/InitialDataProvider.php: -------------------------------------------------------------------------------- 1 | config('slug'); 28 | 29 | /** 30 | * basic data need for ajax request 31 | * you can add your custom data here 32 | */ 33 | $data = [ 34 | "name" => $app->config('name'), 35 | "slug" => $slug, 36 | "version" => $app->version(), 37 | "api_namespace" => $app->config('api_namespace'), 38 | 'api_endpoint' => home_url().'?rest_route=/'.$app->config('api_namespace'), 39 | "ajax_url" => admin_url('admin-ajax.php'), 40 | "nonce" => wp_create_nonce("wp_rest") 41 | ]; 42 | 43 | /** 44 | * generate object name from application slug ( in config/app.php as 'slug') 45 | */ 46 | $objectName = str_replace("-", "_", $slug); 47 | 48 | /** 49 | * add localize script data 50 | * @for admin area 51 | */ 52 | Enqueue::admin()->localizeScript('jquery-core', $objectName, $data); 53 | 54 | /** 55 | * add localize script data 56 | * @for front-end area 57 | */ 58 | Enqueue::front()->localizeScript('jquery-core', $objectName, $data); 59 | 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /bootstrap/System/Providers/ShortcodeServiceProvider.php: -------------------------------------------------------------------------------- 1 | get(ShortcodeHandler::class); 22 | 23 | $shortcodeHandler->setAppInstance($app) 24 | ->setControllerNamespace($this->controllerNamespace) 25 | ->loadFile($app->hooksPath('shortcode.php')); 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /bootstrap/System/Providers/SideMenuServiceProvider.php: -------------------------------------------------------------------------------- 1 | get(SideMenu::class); 22 | 23 | add_action('admin_menu', function () use ($app, $SideMenu) { 24 | 25 | /** @var SideMenuHandler $sideMenuHandler */ 26 | $sideMenuHandler = $app->get(SideMenuHandler::class); 27 | 28 | $sideMenuHandler->setAppInstance($app) 29 | ->setNamespace($this->controllerNamespace) 30 | ->loadMenuFile($app->routePath('sidemenu.php')) 31 | ->setSideMenu($SideMenu); 32 | 33 | }); 34 | 35 | add_action('admin_menu', function () use ($app) { 36 | $app->get(SideMenuHandler::class)->removeFirstSubMenu(); 37 | }, 12); 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /bootstrap/System/Session.php: -------------------------------------------------------------------------------- 1 | add($name, $callback); 25 | } 26 | 27 | private static function handler(): ShortcodeHandler 28 | { 29 | if (!static::$shortcodeHandler) { 30 | static::$shortcodeHandler = App::get(ShortcodeHandler::class); 31 | } 32 | 33 | return static::$shortcodeHandler; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /bootstrap/System/SideMenu.php: -------------------------------------------------------------------------------- 1 | prentSlug = $slug; 49 | 50 | static::getInstance()->data[] = [ 51 | 'title' => $title, 52 | 'menu_title' => $title, 53 | 'slug' => $slug, 54 | ]; 55 | 56 | return static::getInstance(); 57 | } 58 | 59 | private function getCurrentIndex(): int 60 | { 61 | return count($this->data) - 1; 62 | } 63 | 64 | public function capability(string $capability = 'manage_options'): self 65 | { 66 | $this->data[$this->getCurrentIndex()]['capability'] = $capability; 67 | 68 | return $this; 69 | } 70 | 71 | public function menuTitle(string $title): self 72 | { 73 | $this->data[$this->getCurrentIndex()]['menu_title'] = $title; 74 | 75 | return $this; 76 | } 77 | 78 | public function callback($callback): self 79 | { 80 | $this->data[$this->getCurrentIndex()]['callback'] = $callback; 81 | 82 | return $this; 83 | } 84 | 85 | public function icon(string $icon): self 86 | { 87 | $this->data[$this->getCurrentIndex()]['icon'] = $icon; 88 | 89 | return $this; 90 | } 91 | 92 | public function position(int $position): self 93 | { 94 | $this->data[$this->getCurrentIndex()]['position'] = $position; 95 | 96 | return $this; 97 | } 98 | 99 | /** 100 | * $option['as'] required 101 | * @param string $title 102 | * @param string|null $slug 103 | * @return SideMenu 104 | */ 105 | public function child(string $title, string $slug = null): self 106 | { 107 | if(!$this->prentSlug){ 108 | return $this; 109 | } 110 | 111 | $this->data[] = [ 112 | 'title' => $title, 113 | 'menu_title' => $title, 114 | 'submenu' => true, 115 | 'parent_slug' => $this->prentSlug, 116 | 'slug' => $slug ?? plugin_master_slug($title), 117 | ]; 118 | 119 | return $this; 120 | } 121 | 122 | /** 123 | * @param string $parentSlug 124 | * @param string $title 125 | * @param string|null $slug 126 | * @return SideMenu 127 | */ 128 | public static function submenu(string $parentSlug, string $title, string $slug = null): self 129 | { 130 | static::getInstance()->data[] = [ 131 | 'title' => $title, 132 | 'menu_title' => $title, 133 | 'submenu' => true, 134 | 'parent_slug' => $parentSlug, 135 | 'slug' => $slug ?? plugin_master_slug($title), 136 | ]; 137 | 138 | return static::getInstance(); 139 | } 140 | 141 | public function getData(): array 142 | { 143 | return $this->data; 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plugin-master/plugin-master", 3 | "description": "An Application Development Framework for Wordpress.", 4 | "license": "MIT", 5 | "homepage": "https://github.com/emrancu/PluginMaster", 6 | "support": { 7 | "issues": "https://github.com/emrancu/PluginMaster/issues", 8 | "source": "https://github.com/emrancu/PluginMaster" 9 | }, 10 | "authors": [ 11 | { 12 | "name": "AL EMRAN", 13 | "email": "emrancu1@gmail.com" 14 | } 15 | ], 16 | "keywords": [ 17 | "framework", 18 | "PluginMaster", 19 | "WordPress Plugin Development framework" 20 | ], 21 | "type": "project", 22 | "autoload": { 23 | "classmap": [], 24 | "files": [ 25 | "bootstrap/System/Helpers/helpers.php" 26 | ], 27 | "psr-4": { 28 | "PluginMaster\\App\\": "app/", 29 | "PluginMaster\\Bootstrap\\": "bootstrap/", 30 | "PluginMaster\\Database\\": "database/" 31 | } 32 | }, 33 | "require": { 34 | "php": "^7.0|^8.0", 35 | "plugin-master/contracts": "^1.0", 36 | "plugin-master/db": "^1.0", 37 | "plugin-master/request": "^1.0", 38 | "plugin-master/validator": "^1.0", 39 | "plugin-master/foundation": "^1.0", 40 | "plugin-master/schema": "^1.0" 41 | }, 42 | "require-dev": { 43 | "automattic/jetpack-autoloader": "2.10.1" 44 | }, 45 | "minimum-stability": "dev", 46 | "prefer-stable": true, 47 | "config": { 48 | "allow-plugins": { 49 | "automattic/jetpack-autoloader": true 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /config/app.php: -------------------------------------------------------------------------------- 1 | "Plugin Master", 19 | 20 | /** 21 | * application/plugin slug/text domain 22 | * @type string 23 | */ 24 | 'slug' => "plugin-master", 25 | 26 | /** 27 | * application/plugin version 28 | * @type string 29 | */ 30 | 'version' => "1.0.1", 31 | 32 | /** 33 | * rest api namespace 34 | * @type string 35 | */ 36 | 37 | 'api_namespace' => "PluginMaster/v1", 38 | 39 | /** 40 | * add your custom Service Providers here 41 | * service provider path App/Providers 42 | * @type array 43 | */ 44 | 'providers' => [ 45 | TestServiceProvider::class, 46 | ], 47 | 48 | /** 49 | * add your rest api middleware here 50 | * middleware path App/Middleware 51 | * @type array 52 | */ 53 | 'middleware' => [ 54 | 'test' => TestMiddleware::class 55 | ], 56 | 57 | /** 58 | * system service provide 59 | * do not add your service provider here 60 | * if you want to disable any system service provider just comment out or remove from here 61 | * @type array 62 | */ 63 | 'system_providers' => [ 64 | SystemSideMenuServiceProvider::class, 65 | SystemApiServiceProvider::class, 66 | SystemActionServiceProvider::class, 67 | SystemShortcodeServiceProvider::class, 68 | SystemEnqueueServiceProvider::class, 69 | InitialDataProvider::class, 70 | ], 71 | ]; 72 | -------------------------------------------------------------------------------- /database/Migration.php: -------------------------------------------------------------------------------- 1 | intIncrements( 'id' ); 19 | $column->integer( 'user_id' ) ; 20 | $column->text( 'note' )->nullable(); 21 | $column->enum( 'status', [ 'active', 'completed' ] ); 22 | $column->timestamp( 'created_at' )->default( 'current_timestamp' ); 23 | $column->timestamp( 'updated_at' )->nullable()->onUpdateTimeStamp(); 24 | } )->execute(); 25 | 26 | */ 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /enqueues/enqueue.php: -------------------------------------------------------------------------------- 1 | script('js/react/app.js')->inFooter(); 6 | Enqueue::admin()->script('js/js/vue/app.js')->inFooter(); 7 | 8 | Enqueue::admin()->style('css/app.css')->version(time()); 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /hooks/action.php: -------------------------------------------------------------------------------- 1 | { 4 | returnHello world, React JS ❤️
5 | } 6 | 7 | export default Home 8 | -------------------------------------------------------------------------------- /resources/js/react/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Home from './Home.jsx'; 4 | 5 | if( document.getElementById('reactApp') ){ 6 | 7 | ReactDOM.render( 8 |Hello world, Vue JS ❤️
4 |