From 374fba546ad234099e956197005528cdcecb968f Mon Sep 17 00:00:00 2001 From: andyv4 Date: Wed, 30 Sep 2020 11:48:19 +0700 Subject: [PATCH] v1.1.1 --- src/Classes/MySQLDB.php | 24 ++ src/Console/Commands/ScheduledTaskRun.php | 4 - src/Http/Controllers/ActionableController.php | 12 +- src/Http/Controllers/ListPageController2.php | 22 +- src/Interfaces/VerboseOutputInterface.php | 9 + src/Models/ChatDiscussion.php | 16 +- src/Models/ScheduledTask.php | 208 +++++++-------- src/Models/ScheduledTaskInstance.php | 112 --------- src/Models/ScheduledTaskResult.php | 10 +- src/Models/Traits/FilterableTrait.php | 26 +- src/Models/UserNotification.php | 40 +-- src/Services/AuthService.php | 2 + src/Services/WebCacheService.php | 2 +- src/WebHistoryServiceProvider.php | 3 +- ...32_create_scheduled_task_result_table.php} | 20 +- src/helpers.php | 238 +++++++++++++----- .../chat-admin-message-head.blade.php | 13 +- src/views/components/syslog-edit.blade.php | 37 ++- .../sections/cms-import-completed2.blade.php | 34 +++ 19 files changed, 465 insertions(+), 367 deletions(-) create mode 100644 src/Classes/MySQLDB.php create mode 100644 src/Interfaces/VerboseOutputInterface.php delete mode 100644 src/Models/ScheduledTaskInstance.php rename src/database/default/migrations/{2020_06_06_153609_create_scheduled_task_instance_table.php => 2020_07_22_231332_create_scheduled_task_result_table.php} (57%) create mode 100644 src/views/sections/cms-import-completed2.blade.php diff --git a/src/Classes/MySQLDB.php b/src/Classes/MySQLDB.php new file mode 100644 index 0000000..b55a7e2 --- /dev/null +++ b/src/Classes/MySQLDB.php @@ -0,0 +1,24 @@ +fetch_all(MYSQLI_ASSOC); + + if($indexes != null) + $arr = array_index($arr, $indexes); + + return $arr; + } + +} \ No newline at end of file diff --git a/src/Console/Commands/ScheduledTaskRun.php b/src/Console/Commands/ScheduledTaskRun.php index 01e2c9e..cb080d0 100644 --- a/src/Console/Commands/ScheduledTaskRun.php +++ b/src/Console/Commands/ScheduledTaskRun.php @@ -3,12 +3,8 @@ namespace Andiwijaya\AppCore\Console\Commands; use Andiwijaya\AppCore\Models\ScheduledTask; -use Andiwijaya\AppCore\Models\ScheduledTaskInstance; -use Carbon\Carbon; use Illuminate\Console\Command; -use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Log; -use Symfony\Component\Process\Process; class ScheduledTaskRun extends Command { diff --git a/src/Http/Controllers/ActionableController.php b/src/Http/Controllers/ActionableController.php index 2f565ec..b88289a 100644 --- a/src/Http/Controllers/ActionableController.php +++ b/src/Http/Controllers/ActionableController.php @@ -30,7 +30,7 @@ public function store(Request $request){ return call_user_func_array([ $this, $method ], func_get_args()); } - public function show(Request $request){ + public function show(Request $request, $id){ $this->request = $request; @@ -40,6 +40,16 @@ public function show(Request $request){ return call_user_func_array([ $this, $method ], func_get_args()); } + public function patch(Request $request){ + + $this->request = $request; + + $action = isset(($actions = explode('|', $request->input('action', 'patch')))[0]) ? $actions[0] : ''; + $method = action2method($action); + if(method_exists($this, $method)) + return call_user_func_array([ $this, $method ], func_get_args()); + } + public function onlyMethods($methods){ $arr = is_scalar($methods) ? [ $methods ] : (!is_array($methods) ? [] : $methods); diff --git a/src/Http/Controllers/ListPageController2.php b/src/Http/Controllers/ListPageController2.php index 2c8d0f9..2a67cfb 100644 --- a/src/Http/Controllers/ListPageController2.php +++ b/src/Http/Controllers/ListPageController2.php @@ -7,13 +7,13 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Http\Request; use Illuminate\Support\Collection; -use Illuminate\Routing\Controller as BaseController; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Redis; +use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\View; use Illuminate\Support\Str; -class ListPageController2 extends BaseController{ +class ListPageController2 extends ActionableController{ public $model = null; @@ -49,24 +49,6 @@ public function __construct() View::share('meta', $this->meta); } - public function index(Request $request){ - - $action = isset(($actions = explode('|', $request->get('action', 'fetch')))[0]) ? $actions[0] : ''; - - $method = action2method($action); - if(method_exists($this, $method)) - return call_user_func_array([ $this, $method ], func_get_args()); - } - - public function store(Request $request){ - - $action = isset(($actions = explode('|', $request->get('action', 'save')))[0]) ? $actions[0] : ''; - - $method = action2method($action); - if(method_exists($this, $method)) - return call_user_func_array([ $this, $method ], func_get_args()); - } - public function applySorts($builder, array $sorts) { foreach($sorts as $sort){ diff --git a/src/Interfaces/VerboseOutputInterface.php b/src/Interfaces/VerboseOutputInterface.php new file mode 100644 index 0000000..eb9bbdc --- /dev/null +++ b/src/Interfaces/VerboseOutputInterface.php @@ -0,0 +1,9 @@ +extra['offline_message_at'] ?? null))); $offline = self::isOffline(); + if($offline && config('chat.offline-message') && $offline_message_at->diffInHours() > 2){ + $message = config('chat.offline-message'); + $faqs = config('chat.offline-message-faqs', []); + if(count($faqs) > 0){ + $message .= "
    "; + foreach($faqs as $faq_topic){ + + $faq = FAQ::where('topic', $faq_topic)->first(); + $message .= "
  1. seo_url}' target='_blank'>{$faq->topic}
  2. "; + } + $message .= "
"; + } + $message = new ChatMessage([ 'discussion_id'=>$discussion_id, 'direction'=>ChatMessage::DIRECTION_OUT, - 'text'=>config('chat.offline-message'), + 'text'=>$message, 'is_system'=>1, 'extra'=>[ 'name'=>'Tara', 'avatar_url'=>'chat-figure.png' ], ]); diff --git a/src/Models/ScheduledTask.php b/src/Models/ScheduledTask.php index 1286aed..16f5578 100644 --- a/src/Models/ScheduledTask.php +++ b/src/Models/ScheduledTask.php @@ -4,11 +4,14 @@ use Andiwijaya\AppCore\Models\Traits\FilterableTrait; use Andiwijaya\AppCore\Models\Traits\LoggedTraitV3; +use Andiwijaya\AppCore\Providers\ScheduledTaskSecurityProvider; use Carbon\Carbon; use Illuminate\Console\Command; use Illuminate\Database\Eloquent\Model; +use Illuminate\Queue\SerializableClosure; use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Str; use Symfony\Component\Process\Process; class ScheduledTask extends Model @@ -60,28 +63,31 @@ public function results(){ public function preSave() { - if(in_array(($name = explode(':', explode(' ', $this->command)[0])[0]), [ - 'app', - 'migrate', - 'make', - 'event', - 'config', - 'data', - 'cache', - 'list', - 'optimize', - 'down', - 'up', - 'clear-compiled', - 'dump-server', - 'db', - 'queue', - 'redis', - 'route', - 'schedule', - 'vendor' - ])) - exc('Unable to use this command'); + if(is_string($this->command)){ + + if(in_array(($name = explode(':', explode(' ', $this->command)[0])[0]), [ + 'app', + 'migrate', + 'make', + 'event', + 'config', + 'data', + 'cache', + 'list', + 'optimize', + 'down', + 'up', + 'clear-compiled', + 'dump-server', + 'db', + 'queue', + 'redis', + 'route', + 'schedule', + 'vendor' + ])) + exc('Unable to use this command'); + } } @@ -112,33 +118,60 @@ public function run(){ $this->status = self::STATUS_RUNNING; $this->save(); - $report = $this->results()->create([ + $result = $this->results()->create([ 'status'=>self::STATUS_RUNNING, 'started_at'=>Carbon::now()->format('Y-m-d H:i:s'), 'pid'=>getmypid() ]); - $exitCode = Artisan::call($this->command); - $output = Artisan::output(); + if(strpos($this->command, 'SerializableClosure') !== false){ - $report->status = $exitCode > 0 ? self::STATUS_ERROR : self::STATUS_COMPLETED; - $report->verbose = $output; - $report->ellapsed = microtime(1) - $t1; - $report->completed_at = Carbon::now()->format('Y-m-d H:i:s'); - $report->save(); + if (null !== $securityProvider = SerializableClosure::getSecurityProvider()) { + SerializableClosure::removeSecurityProvider(); + } - $this->status = $report->status; - $this->save(); + $command = unserialize($this->command)->getClosure(); + + if ($securityProvider !== null) { + SerializableClosure::addSecurityProvider($securityProvider); + } + + try{ + $output = call_user_func_array($command, [ $result ]); + $exitCode = 0; + } + catch(\Exception $ex){ + $exitCode = 1; + $output = $ex->getMessage() . "@" . $ex->getFile() . ":" . $ex->getLine(); + } + } + else{ + $exitCode = Artisan::call($this->command); + $output = Artisan::output(); + } if($this->remove_after_completed) $this->delete(); + else{ + $result->status = $exitCode > 0 ? self::STATUS_ERROR : self::STATUS_COMPLETED; + $result->verbose .= $output . PHP_EOL; + $result->ellapsed = microtime(1) - $t1; + $result->completed_at = Carbon::now()->format('Y-m-d H:i:s'); + $result->save(); + + $this->status = $result->status; + + $this->save(); + } } public function runInBackground(){ chdir(base_path()); - exec("php artisan scheduled-task:run --id={$this->id} > /dev/null 2>&1 &", $output, $return_var); + $log_path = storage_path('logs/laravel.log'); + + exec("php artisan scheduled-task:run --id={$this->id} > {$log_path} 2>&1 &", $output, $return_var); } public static function check(Command $cmd = null){ @@ -216,103 +249,36 @@ public static function runOnceThenRemove(array $params, Command $cmd = null){ return $task; } - public function createInstances(){ - - if($this->status != self::STATUS_ACTIVE) return; - - //\Illuminate\Support\Facades\Log::info("create instance: {$this->id}"); - - switch($this->repeat){ - - case self::REPEAT_NONE: - if(count($this->instances) <= 0){ - $this->instances()->create([ - 'command'=>$this->command, - 'start'=>$this->start - ]); - } - break; - - case self::REPEAT_MINUTELY: - if($this->instances->where('status', ScheduledTaskInstance::STATUS_SCHEDULED)->count() <= 0){ + public static function runOnce($command, $description = ''){ - $instances = []; - for($i = 1 ; $i <= 10 ; $i++){ - $instances[] = new ScheduledTaskInstance([ - 'command'=>$this->command, - 'start'=>Carbon::now()->addMinutes($i)->format('Y-m-d H:i:00') - ]); - } - $this->instances()->saveMany($instances); - } - break; - - case self::REPEAT_EVERY_FIVE_MINUTE: - if($this->instances->where('status', ScheduledTaskInstance::STATUS_SCHEDULED)->count() <= 0){ - - $instances = []; - $currentMinute = Carbon::now()->minute; - $addMinute = ((floor($currentMinute / 5) * 5) + 5) - $currentMinute; - for($i = 1 ; $i <= 10 ; $i++){ - $instances[] = new ScheduledTaskInstance([ - 'command'=>$this->command, - 'start'=>Carbon::now()->addMinutes($addMinute)->format('Y-m-d H:i:00') - ]); - $addMinute += 5; - } + if($command instanceof \Closure){ - $this->instances()->saveMany($instances); - } - break; - - case self::REPEAT_EVERY_TEN_MINUTE: - if($this->instances->where('status', ScheduledTaskInstance::STATUS_SCHEDULED)->count() <= 0){ - - $instances = []; - $currentMinute = Carbon::now()->minute; - $addMinute = ((floor($currentMinute / 10) * 10) + 10) - $currentMinute; - for($i = 1 ; $i <= 10 ; $i++){ - $instances[] = new ScheduledTaskInstance([ - 'command'=>$this->command, - 'start'=>Carbon::now()->addMinutes($addMinute)->format('Y-m-d H:i:00') - ]); - $addMinute += 10; - } + if (null !== $securityProvider = SerializableClosure::getSecurityProvider()) { + SerializableClosure::removeSecurityProvider(); + } - $this->instances()->saveMany($instances); - } - break; + $command = serialize(new SerializableClosure($command)); - case self::REPEAT_HOURLY: - if($this->instances->where('status', ScheduledTaskInstance::STATUS_SCHEDULED)->count() <= 0){ + if ($securityProvider !== null) { + SerializableClosure::addSecurityProvider($securityProvider); + } + } - $instances = []; - for($i = 1 ; $i <= 10 ; $i++){ - $instances[] = new ScheduledTaskInstance([ - 'command'=>$this->command, - 'start'=>Carbon::now()->addHours($i)->format('Y-m-d H:00:00') - ]); - } - $this->instances()->saveMany($instances); - } - break; + if(!$description) + $description = "Scheduled task - " . Str::random(5); - case self::REPEAT_DAILY: - if($this->instances->where('status', ScheduledTaskInstance::STATUS_SCHEDULED)->count() <= 0){ + $task = new ScheduledTask([ + 'command'=>$command, + 'description'=>$description, + 'repeat'=>self::REPEAT_NONE, + 'remove_after_completed'=>0 + ]); - $instances = []; - for($i = 1 ; $i <= 10 ; $i++){ - $instances[] = new ScheduledTaskInstance([ - 'command'=>$this->command, - 'start'=>Carbon::now()->addDays($i)->format('Y-m-d 00:00:00') - ]); - } - $this->instances()->saveMany($instances); - } - break; + $task->save(); - } + $task->runInBackground(); + return $task; } diff --git a/src/Models/ScheduledTaskInstance.php b/src/Models/ScheduledTaskInstance.php deleted file mode 100644 index 0d36052..0000000 --- a/src/Models/ScheduledTaskInstance.php +++ /dev/null @@ -1,112 +0,0 @@ -self::STATUS_SCHEDULED - ]; - - protected $casts = [ - 'result_details'=>'array', - 'completed_at'=>'datetime' - ]; - - - public function __construct(array $attributes = []) - { - $this->log = false; - - parent::__construct($attributes); - } - - public function calculate() - { - $this->task->calculate(); - } - - public function run(){ - - if($this->task->status != ScheduledTask::STATUS_ACTIVE) return; - - $start_time = microtime(1); - $this->status = ScheduledTaskInstance::STATUS_RUNNING; - $this->pid = getmypid(); - $this->save([ 'log'=>false ]); - - $exitCode = Artisan::call($this->command); - $output = Artisan::output(); - - $this->status = ScheduledTaskInstance::STATUS_COMPLETED; - $this->ellapsed = microtime(1) - $start_time; - $this->completed_at = Carbon::now()->toDateTimeString(); - $this->result = $exitCode; - $this->result_details = [ - 'output'=>$output - ]; - $this->save(); - } - - public function runInBackground(){ - - chdir(base_path()); - - exec("php artisan scheduled-task:run --id={$this->id} > /dev/null 2>&1 & disown", $output, $return_var); - } - - public function task(){ - - return $this->belongsTo('Andiwijaya\AppCore\Models\ScheduledTask', 'task_id'); - } - - - public static function check(){ - - // Execute task instance - ScheduledTaskInstance::select('id') - ->where('status', ScheduledTaskInstance::STATUS_SCHEDULED) - ->where(function($query){ - - $query->whereNull('start') - ->orWhere('start', Carbon::now()->format('Y-m-d H:i') . ':00'); - }) - ->orderBy('id') - ->chunk(1000, function($instances){ - - foreach($instances as $instance){ - - exec("php artisan scheduled-task:run --id={$instance->id} > /dev/null 2>&1 & disown", $output, $return_var); - - //Log::info(implode("\n", $output) . "\n" . $return_var); - } - }); - - // Create more instances for repeated task - ScheduledTask::where('repeat', '>', 0) - ->chunk(1000, function($tasks){ - - foreach($tasks as $task){ - - $task->createInstances(); - } - }); - } -} diff --git a/src/Models/ScheduledTaskResult.php b/src/Models/ScheduledTaskResult.php index 7b66b28..1b3b64d 100644 --- a/src/Models/ScheduledTaskResult.php +++ b/src/Models/ScheduledTaskResult.php @@ -2,9 +2,10 @@ namespace Andiwijaya\AppCore\Models; +use Andiwijaya\AppCore\Interfaces\VerboseOutputInterface; use Illuminate\Database\Eloquent\Model; -class ScheduledTaskResult extends Model{ +class ScheduledTaskResult extends Model implements VerboseOutputInterface{ protected $table = 'scheduled_task_result'; @@ -28,4 +29,11 @@ public function getStatusTextAttribute(){ } } + public function info($text) + { + $this->verbose .= $text . PHP_EOL; + + $this->save(); + } + } \ No newline at end of file diff --git a/src/Models/Traits/FilterableTrait.php b/src/Models/Traits/FilterableTrait.php index 17b9cda..e4cada5 100644 --- a/src/Models/Traits/FilterableTrait.php +++ b/src/Models/Traits/FilterableTrait.php @@ -3,6 +3,7 @@ namespace Andiwijaya\AppCore\Models\Traits; +use App\Models\Session; use Carbon\Carbon; trait FilterableTrait{ @@ -98,46 +99,51 @@ public function scopeFilter($model, array $params, $callback = null){ if(is_null($value)) continue; if(in_array($key, [ 'columns', 'filters', 'search' ])) continue; - if(!in_array($key, array_merge($this->getFillable(), $this->getHidden(), $this->getGuarded(), [ 'created_at', 'updated_at' ]))) continue; + if(!in_array($key, array_merge($this->getFillable(), $this->getHidden(), $this->getGuarded(), [ 'created_at', 'updated_at' ]))){ + + if(strpos($key, '_created_at') !== false) $key = str_replace('_created_at', '.created_at', $key); + else if(strpos($key, '_updated_at') !== false) $key = str_replace('_updated_at', '.updated_at', $key); + else continue; + } if(isset($value['date_range'])){ switch($value['date_range']){ - case 'today': $model->whereRaw("DATE(`$key`) = ?", [ Carbon::now()->format('Y-m-d') ]); break; - case 'yesterday': $model->whereRaw("DATE(`$key`) = ?", [ Carbon::now()->addDays(-1)->format('Y-m-d') ]); break; - case 'tomorrow': $model->whereRaw("DATE(`$key`) = ?", [ Carbon::now()->addDays(1)->format('Y-m-d') ]); break; + case 'today': $model->whereRaw("DATE($key) = ?", [ Carbon::now()->format('Y-m-d') ]); break; + case 'yesterday': $model->whereRaw("DATE($key) = ?", [ Carbon::now()->addDays(-1)->format('Y-m-d') ]); break; + case 'tomorrow': $model->whereRaw("DATE($key) = ?", [ Carbon::now()->addDays(1)->format('Y-m-d') ]); break; case 'this-week': - $model->whereRaw("DATE(`$key`) BETWEEN ? AND ?", [ + $model->whereRaw("DATE($key) BETWEEN ? AND ?", [ Carbon::now()->startOfWeek()->format('Y-m-d'), Carbon::now()->endOfWeek()->format('Y-m-d'), ]); break; case 'this-month': - $model->whereRaw("DATE(`$key`) BETWEEN ? AND ?", [ + $model->whereRaw("DATE({$key}) BETWEEN ? AND ?", [ Carbon::now()->startOfMonth()->format('Y-m-d'), Carbon::now()->endOfMonth()->format('Y-m-d'), ]); break; case 'this-quarter': - $model->whereRaw("DATE(`$key`) BETWEEN ? AND ?", [ + $model->whereRaw("DATE($key) BETWEEN ? AND ?", [ Carbon::now()->startOfQuarter()->format('Y-m-d'), Carbon::now()->endOfQuarter()->format('Y-m-d'), ]); break; case 'this-year': - $model->whereRaw("DATE(`$key`) BETWEEN ? AND ?", [ + $model->whereRaw("DATE($key) BETWEEN ? AND ?", [ Carbon::now()->startOfYear()->format('Y-m-d'), Carbon::now()->endOfYear()->format('Y-m-d'), ]); break; case 'this-decade': - $model->whereRaw("DATE(`$key`) BETWEEN ? AND ?", [ + $model->whereRaw("DATE($key) BETWEEN ? AND ?", [ Carbon::now()->startOfDecade()->format('Y-m-d'), Carbon::now()->endOfDecade()->format('Y-m-d'), ]); @@ -147,7 +153,7 @@ public function scopeFilter($model, array $params, $callback = null){ $custom_from = date('Y-m-d', strtotime($value['date_range_from'])); $custom_to = date('Y-m-d', strtotime($value['date_range_to'])); - $model->whereRaw("DATE(`$key`) BETWEEN ? AND ?", [ + $model->whereRaw("DATE($key) BETWEEN ? AND ?", [ $custom_from, $custom_to, ]); diff --git a/src/Models/UserNotification.php b/src/Models/UserNotification.php index f7938ac..8d07f98 100644 --- a/src/Models/UserNotification.php +++ b/src/Models/UserNotification.php @@ -7,6 +7,9 @@ class UserNotification extends Model{ + const TARGET_ALL = -1; + const TARGET_ALL_ONLINE = -2; + protected $table = 'user_notification'; protected $fillable = [ 'status', 'title', 'body', 'target', 'user_id' ]; @@ -29,37 +32,34 @@ public function save(array $options = []) { $return = parent::save($options); - $this->pushNotification(); - return $return; } - public function pushNotification(){ - - if(redis_available()) { - $currentCursor = '0'; - $k = []; - do { - $response = Redis::scan($currentCursor, 'MATCH', 'notification*', 'COUNT', 100); - $currentCursor = $response[0]; - $k = array_merge($k, $response[1]); - } while ($currentCursor !== '0'); - exc($k); + public static function notify($user_id, $title, $description = '', $target = '', $timing = null, $persist = false){ + $title = str_replace('"', '', $title); + $description = str_replace('"', '', $description); + $target = str_replace('"', '', $target); - Redis::publish('notification-1', json_encode($this)); + if(redis_available()) { - /*$keys = Redis::keys('name'); + Redis::publish('user-notif-' . $user_id, json_encode([ + 'script'=>"$.notify({ title:\"{$title}\", description:\"{$description}\", target:\"{$target}\" });" + ])); + } - foreach ($keys as $key){ - \Illuminate\Support\Facades\Log::info("Push notification to {$key}, title: {$this->title}"); + if($persist){ - Redis::publish($key, json_encode($this)); - }*/ + $instance = new UserNotification([ + 'user_id'=>$user_id, + 'title'=>$title, + 'description'=>$description, + 'target'=>$target + ]); + $instance->save(); } - } } \ No newline at end of file diff --git a/src/Services/AuthService.php b/src/Services/AuthService.php index 9fc7576..a2ff6e1 100644 --- a/src/Services/AuthService.php +++ b/src/Services/AuthService.php @@ -70,6 +70,8 @@ public function load() $this->user = $user; } + + return $this->user; } public function user() diff --git a/src/Services/WebCacheService.php b/src/Services/WebCacheService.php index a2eba9a..9980a09 100644 --- a/src/Services/WebCacheService.php +++ b/src/Services/WebCacheService.php @@ -113,7 +113,7 @@ public function store(Request $request, $response){ } else{ - Log::warning("Unable to create cache from response type of " . get_class($response)); + //Log::warning("Unable to create cache from response type of " . get_class($response)); } diff --git a/src/WebHistoryServiceProvider.php b/src/WebHistoryServiceProvider.php index 8dec8db..7438c81 100644 --- a/src/WebHistoryServiceProvider.php +++ b/src/WebHistoryServiceProvider.php @@ -65,7 +65,8 @@ public function saveHistory($request, $data){ $queries = $params = []; - $session_id = Crypt::decrypt($request->cookies->get(strtolower(env('APP_NAME')) . '_session'), false); + $session_cookie_value = $request->cookies->get(strtolower(env('APP_NAME')) . '_session'); + $session_id = $session_cookie_value ? Crypt::decrypt($session_cookie_value, false) : 'N/A'; if(is_assoc($data)) $data = [ $data ]; diff --git a/src/database/default/migrations/2020_06_06_153609_create_scheduled_task_instance_table.php b/src/database/default/migrations/2020_07_22_231332_create_scheduled_task_result_table.php similarity index 57% rename from src/database/default/migrations/2020_06_06_153609_create_scheduled_task_instance_table.php rename to src/database/default/migrations/2020_07_22_231332_create_scheduled_task_result_table.php index 253859a..7b7a2d5 100644 --- a/src/database/default/migrations/2020_06_06_153609_create_scheduled_task_instance_table.php +++ b/src/database/default/migrations/2020_07_22_231332_create_scheduled_task_result_table.php @@ -4,7 +4,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; -class CreateScheduledTaskInstanceTable extends Migration +class CreateScheduledTaskResultTable extends Migration { /** * Run the migrations. @@ -13,24 +13,20 @@ class CreateScheduledTaskInstanceTable extends Migration */ public function up() { - Schema::create('scheduled_task_instance', function (Blueprint $table) { + Schema::create('scheduled_task_result', function (Blueprint $table) { $table->bigIncrements('id'); $table->bigInteger('task_id')->unsigned(); - $table->smallInteger('status'); // scheduled, running, completed, failed - $table->string('command'); + $table->smallInteger('status'); - $table->dateTime('start')->nullable(); - - $table->smallInteger('result')->nullable(); - $table->text('result_details')->nullable(); - $table->dateTime('completed_at')->nullable(); - $table->double('ellapsed', 13, 3)->nullable(); + $table->longText('verbose')->nullable(); $table->timestamps(); - + $table->dateTime('started_at')->nullable(); + $table->dateTime('completed_at')->nullable(); + $table->double('ellapsed', 6, 3)->nullable(); $table->integer('pid')->nullable(); $table->foreign('task_id')->references('id')->on('scheduled_task')->onDelete('cascade')->onUpdate('cascade'); @@ -44,6 +40,6 @@ public function up() */ public function down() { - Schema::dropIfExists('scheduled_task_instance'); + Schema::dropIfExists('scheduled_task_result'); } } diff --git a/src/helpers.php b/src/helpers.php index 1b515e3..046d41b 100644 --- a/src/helpers.php +++ b/src/helpers.php @@ -5,6 +5,8 @@ * Check if variable is assosiative array */ +use Illuminate\Support\Str; + if(!function_exists('is_assoc')){ function is_assoc($array) { if(gettype($array) == "array") @@ -14,7 +16,7 @@ function is_assoc($array) { } if (! function_exists('exc')) { - function exc($message) + function exc($message = '') { if(is_array($message)) $message = json_encode($message); throw new \Andiwijaya\AppCore\Exceptions\KnownException($message); @@ -400,40 +402,54 @@ function array_index($arr, $indexes, $objResult = false){ if(!is_array($arr)) return null; $result = array(); + $indexes_is_callback = is_callable($indexes); + for($i = 0 ; $i < count($arr) ; $i++){ $obj = $arr[$i]; - switch(count($indexes)){ - case 1 : - $idx0 = $indexes[0]; - if(!isset($obj[$idx0])) continue; - if(!isset($result[$obj[$idx0]])) $result[$obj[$idx0]] = array(); - $result[$obj[$idx0]][] = $obj; - break; - case 2 : - $idx0 = $indexes[0]; - $idx1 = $indexes[1]; - if(!isset($obj[$idx0]) || !isset($obj[$idx1])) continue; - $key0 = $obj[$idx0]; - $key1 = $obj[$idx1]; - if(!isset($result[$key0])) $result[$key0] = array(); - if(!isset($result[$key0][$key1])) $result[$key0][$key1] = array(); - $result[$key0][$key1][] = $obj; - break; - case 3 : - $idx0 = $indexes[0]; - $idx1 = $indexes[1]; - $idx2 = $indexes[2]; - if(!isset($obj[$idx0]) || !isset($obj[$idx1]) || !isset($obj[$idx2])) continue; - $key0 = $obj[$idx0]; - $key1 = $obj[$idx1]; - $key2 = $obj[$idx2]; - if(!isset($result[$key0])) $result[$key0] = array(); - if(!isset($result[$key0][$key1])) $result[$key0][$key1] = array(); - $result[$key0][$key1][$key2] = $obj; - break; - default: - throw new Exception("Unsupported index level."); + if($indexes_is_callback){ + + $key = call_user_func_array($indexes, [ $obj ]); + if(!isset($result[$key])) $result[$key] = []; + $result[$key][] = $obj; + } + else{ + + switch(count($indexes)){ + case 1 : + $idx0 = $indexes[0]; + if(isset($obj[$idx0])){ + if(!isset($result[$obj[$idx0]])) $result[$obj[$idx0]] = array(); + $result[$obj[$idx0]][] = $obj; + } + break; + case 2 : + $idx0 = $indexes[0]; + $idx1 = $indexes[1]; + if(isset($obj[$idx0]) && isset($obj[$idx1])){ + $key0 = $obj[$idx0]; + $key1 = $obj[$idx1]; + if(!isset($result[$key0])) $result[$key0] = array(); + if(!isset($result[$key0][$key1])) $result[$key0][$key1] = array(); + $result[$key0][$key1][] = $obj; + } + break; + case 3 : + $idx0 = $indexes[0]; + $idx1 = $indexes[1]; + $idx2 = $indexes[2]; + if(isset($obj[$idx0]) && !isset($obj[$idx1]) && !isset($obj[$idx2])){ + $key0 = $obj[$idx0]; + $key1 = $obj[$idx1]; + $key2 = $obj[$idx2]; + if(!isset($result[$key0])) $result[$key0] = array(); + if(!isset($result[$key0][$key1])) $result[$key0][$key1] = array(); + $result[$key0][$key1][$key2] = $obj; + } + break; + default: + throw new Exception("Unsupported index level."); + } } } @@ -476,32 +492,35 @@ function array_index_obj($arr, $indexes, $objResult = false) switch (count($indexes)) { case 1 : $idx0 = $indexes[0]; - if (!isset($obj->{$idx0})) continue; - if (!isset($result[$obj->{$idx0}])) $result[$obj->{$idx0}] = array(); - $result[$obj->{$idx0}][] = $obj; + if (isset($obj->{$idx0})) { + if (!isset($result[$obj->{$idx0}])) $result[$obj->{$idx0}] = array(); + $result[$obj->{$idx0}][] = $obj; + } break; case 2 : $idx0 = $indexes[0]; $idx1 = $indexes[1]; - if (!isset($obj->{$idx0}) || !isset($obj->{$idx1})) continue; - $key0 = $obj->{$idx0}; - $key1 = $obj->{$idx1}; - if (!isset($result[$key0])) $result[$key0] = array(); - if (!isset($result[$key0][$key1])) $result[$key0][$key1] = array(); - $result[$key0][$key1][] = $obj; + if (isset($obj->{$idx0}) && isset($obj->{$idx1})){ + $key0 = $obj->{$idx0}; + $key1 = $obj->{$idx1}; + if (!isset($result[$key0])) $result[$key0] = array(); + if (!isset($result[$key0][$key1])) $result[$key0][$key1] = array(); + $result[$key0][$key1][] = $obj; + } break; case 3 : $idx0 = $indexes[0]; $idx1 = $indexes[1]; $idx2 = $indexes[2]; - if (!isset($obj->{$idx0}) || !isset($obj->{$idx1}) || !isset($obj->{$idx2})) continue; - $key0 = $obj->{$idx0}; - $key1 = $obj->{$idx1}; - $key2 = $obj->{$idx2}; - - if (!isset($result[$key0])) $result[$key0] = array(); - if (!isset($result[$key0][$key1])) $result[$key0][$key1] = array(); - $result[$key0][$key1][$key2][] = $obj; + if (isset($obj->{$idx0}) && !isset($obj->{$idx1}) && !isset($obj->{$idx2})){ + $key0 = $obj->{$idx0}; + $key1 = $obj->{$idx1}; + $key2 = $obj->{$idx2}; + + if (!isset($result[$key0])) $result[$key0] = array(); + if (!isset($result[$key0][$key1])) $result[$key0][$key1] = array(); + $result[$key0][$key1][$key2][] = $obj; + } break; default: throw new Exception("Unsupported index level."); @@ -1026,6 +1045,7 @@ function list_page_filter_item($key, $param){ $custom_from = \Carbon\Carbon::now()->addDays(-7)->format('j M Y'); $custom_to = \Carbon\Carbon::now()->format('j M Y'); + $key = Str::slug($key); $html .= << @@ -1309,22 +1329,124 @@ function imgresizer($image, $resize){ } } -if(!function_exists('appcore_boot')){ +if(!function_exists('checked_if')){ + + function checked_if($key, $arr){ + + if(is_array($arr)) + return in_array($key, $arr) ? ' checked' : ''; + return ''; + } +} + +if(!function_exists('action_route')){ - function appcore_boot($provider){ + function action_route($namespace){ + $f = function(\Illuminate\Http\Request $request) use($namespace){ + $namespace = 'Admin'; + if(!empty($namespace)) $namespace .= '\\'; - } + $method = $request->method(); + $path = $request->path(); + $paths = $path != '/' ? explode('/', $path) : []; + $key = null; + $action = explode('|', $request->input('action'))[0] ?? null; + + if(preg_match('/^\d+$/', end($paths)) || in_array(end($paths), [ 'create' ])){ + $key = end($paths); + $paths = array_splice($paths, 0, count($paths) - 1); + } + + $controller = "App\\Http\\Controllers\\{$namespace}" . Str::ucfirst(Str::camel(count($paths) > 0 ? implode('-', $paths) : 'index') . 'Controller'); + if(class_exists($controller)){ + + $controller = new $controller(); + + if(!$key){ + + switch($method){ + + case 'GET': + $method = Str::camel($action ? $action : 'view'); + + return call_user_func_array([ $controller, $method ], [ $request ]); + + case 'POST': + $method = Str::camel($action ? $action : 'save'); + + return call_user_func_array([ $controller, $method ], [ $request ]); + + case 'PATCH': + $method = Str::camel($action ? $action : 'update'); + + return call_user_func_array([ $controller, $method ], [ $request ]); + } + + } + else{ + + switch($method){ + + case 'GET': + $method = Str::camel($action ? $action : ($key == 'create' ? 'create' : 'open')); + + return call_user_func_array([ $controller, $method ], [ $request, $key ]); + + case 'DELETE': + $method = Str::camel($action ? $action : 'destroy'); + + return call_user_func_array([ $controller, $method ], [ $request, $key ]); + + } + } + + + } + + else{ + + return json_encode([ + $namespace, + $method, + $path, + $controller, + class_exists($controller) + ]); + } + + }; + + return function() use($f){ + + \Illuminate\Support\Facades\Route::any('', $f); + \Illuminate\Support\Facades\Route::any('{p1}', $f); + \Illuminate\Support\Facades\Route::any('{p1}/{p2}', $f); + \Illuminate\Support\Facades\Route::any('{p1}/{p2}/{p3}', $f); + }; + }; } -if(!function_exists('checked_if')){ +if(!function_exists('greeting')){ - function checked_if($key, $arr){ + function greeting($name = ''){ - if(is_array($arr)) - return in_array($key, $arr) ? ' checked' : ''; - return ''; + $hour = \Carbon\Carbon::now()->format('H'); + if($hour >= 5 && $hour < 11) + $greeting = __('Good morning'); + elseif($hour >= 11 && $hour < 15) + $greeting = __('Good afternoon'); + elseif($hour >= 15 && $hour < 19) + $greeting = __('Good evening'); + else + $greeting = __('Good night'); + + $greeting .= !empty($name) ? ', ' . $name : ''; + + return $greeting; } -} \ No newline at end of file + +} + diff --git a/src/views/components/chat-admin-message-head.blade.php b/src/views/components/chat-admin-message-head.blade.php index a241ac4..d9007d0 100644 --- a/src/views/components/chat-admin-message-head.blade.php +++ b/src/views/components/chat-admin-message-head.blade.php @@ -11,15 +11,24 @@
@component('andiwijaya::components.chat-admin-online-status', compact('customer_is_online', 'discussion'))@endcomponent
- @if(isset($discussion->extra['phone_number'])) + @if(isset($discussion->extra['phone_number']) && strlen($discussion->extra['phone_number']) > 0)
+ @elseif(strlen($discussion->mobile_number) > 0) +
+ +
@endif - @if(isset($discussion->extra['whatsapp_number'])) + + @if(isset($discussion->extra['whatsapp_number']) && strlen($discussion->extra['whatsapp_number']) > 0)
+ @elseif(strlen($discussion->whatsapp_number) > 0) +
+ +
@endif diff --git a/src/views/components/syslog-edit.blade.php b/src/views/components/syslog-edit.blade.php index ff98589..4505dcc 100644 --- a/src/views/components/syslog-edit.blade.php +++ b/src/views/components/syslog-edit.blade.php @@ -11,16 +11,37 @@
-
+
Type
-
+
Console
+
+ Session ID
+ +
+ +
+
+ IP Address
+ +
+
+ Timestamp
+ +
+
+ +
+ User Agent
+ +
+
Message
@@ -41,8 +62,18 @@
{!! $instance->data['traces'] !!}
+
+ Session +
{!! json_encode($instance->data['session'] ?? [], JSON_PRETTY_PRINT) !!}
+
+ +
+ Cookies +
{!! json_encode($instance->data['cookies'] ?? [], JSON_PRETTY_PRINT) !!}
+
+
- +
diff --git a/src/views/sections/cms-import-completed2.blade.php b/src/views/sections/cms-import-completed2.blade.php new file mode 100644 index 0000000..e9066f5 --- /dev/null +++ b/src/views/sections/cms-import-completed2.blade.php @@ -0,0 +1,34 @@ +
+ +
+
+
+

Import sedang Berjalan

+

Proses import sedang berjalan, kamu akan menerima notifikasi setelah proses import ini selesai.

+ @csrf +
+ + + +
+
+ +
+ +
+ +
+ + + +
+ +
+ +
+ +
+ +
+ +
\ No newline at end of file