diff --git a/apps/Core/Components/System/Filters/FiltersComponent.php b/apps/Core/Components/System/Filters/FiltersComponent.php index 4585de0df..2f0beebce 100644 --- a/apps/Core/Components/System/Filters/FiltersComponent.php +++ b/apps/Core/Components/System/Filters/FiltersComponent.php @@ -22,82 +22,83 @@ public function initialize() */ public function viewAction() { - if ($this->app['id'] == 1) { - $components = $this->modules->components->components; - - foreach ($components as $key => $component) { - $components[$key]['name'] = $component['name'] . ' (' . $component['category'] . ')'; - } - - $this->view->components = $components; - - if (isset($this->getData()['id'])) { - if ($this->getData()['id'] != 0) { - $filter = $this->filters->getById($this->getData()['id']); + if (isset($this->getData()['id'])) { + if ($this->getData()['id'] != 0) { + $filter = $this->filters->getById($this->getData()['id']); - if (!$filter) { - return $this->throwIdNotFound(); - } - - $this->view->filter = $filter; + if (!$filter) { + return $this->throwIdNotFound(); } - $this->view->pick('filters/view'); - - return; + $this->view->filter = $filter; } - if ($this->request->isPost()) { - $replaceColumns = - [ - 'filter_type' => ['html' => - [ - '0' => 'System', - '1' => 'User', - '2' => 'User', - ] - ], - 'is_default' => ['html' => - [ - '0' => 'No', - '1' => 'Yes' - ] - ], - 'auto_generated' => ['html' => - [ - '0' => 'No', - '1' => 'Yes' - ] - ] - ]; + $this->view->pick('filters/view'); + + return; + } else { + if ($this->app['id'] == 1) { + $components = $this->modules->components->components; } else { - $replaceColumns = null; + $components = $this->modules->components->getComponentsForAppType($this->app['app_type']); } - $controlActions = + foreach ($components as $key => $component) { + $components[$key]['name'] = $component['name'] . ' (' . $component['category'] . ')'; + } + + $this->view->components = $components; + } + + if ($this->request->isPost()) { + $replaceColumns = [ - 'actionsToEnable' => - [ - 'edit' => 'system/filters', - 'remove' => 'system/filters/remove' + 'filter_type' => ['html' => + [ + '0' => 'System', + '1' => 'User' + ] + ], + 'is_default' => ['html' => + [ + '0' => 'No', + '1' => 'Yes' + ] + ], + 'auto_generated' => ['html' => + [ + '0' => 'No', + '1' => 'Yes' + ] ] ]; - - $this->generateDTContent( - $this->filters, - 'system/filters/view', - null, - ['name', 'filter_type', 'auto_generated', 'is_default'], - true, - ['name', 'filter_type', 'auto_generated', 'is_default'], - $controlActions, - null, - $replaceColumns, - 'name' - ); - - $this->view->pick('filters/list'); + } else { + $replaceColumns = null; } + + $controlActions = + [ + 'actionsToEnable' => + [ + 'edit' => 'system/filters', + 'remove' => 'system/filters/remove' + ] + ]; + + $this->generateDTContent( + $this->filters, + 'system/filters/view', + null, + ['name', 'app_type', 'filter_type', 'auto_generated', 'is_default'], + true, + ['name', 'app_type', 'filter_type', 'auto_generated', 'is_default'], + $controlActions, + null, + $replaceColumns, + 'name' + ); + + $this->view->pick('filters/list'); } /** @@ -112,7 +113,7 @@ public function addAction() $this->view->filters = $this->filters->packagesData->filters; } else { - //Adding close in add as cloning requires add permission so both add and clone can be performed in same action. + //Adding clone in add as cloning requires add permission so both add and clone can be performed in same action. if (isset($this->postData()['clone']) && $this->postData()['clone']) { $this->filters->cloneFilter($this->postData()); } else { diff --git a/apps/Core/Components/System/Users/Accounts/AccountsComponent.php b/apps/Core/Components/System/Users/Accounts/AccountsComponent.php index f6425cb96..cbe0c2650 100644 --- a/apps/Core/Components/System/Users/Accounts/AccountsComponent.php +++ b/apps/Core/Components/System/Users/Accounts/AccountsComponent.php @@ -82,6 +82,10 @@ public function viewAction() $this->view->apps = $this->accounts->packagesData->apps; $this->view->roles = $this->accounts->packagesData->roles; + + $this->view->countries = $this->basepackages->geoCountries->getAll()->geoCountries; + + $this->view->timezones = $this->basepackages->geoTimezones->getAll()->geoTimezones; } $this->addResponse( diff --git a/apps/Core/Components/System/Users/Profile/ProfileComponent.php b/apps/Core/Components/System/Users/Profile/ProfileComponent.php index 66f61da0c..ce96cf0e3 100644 --- a/apps/Core/Components/System/Users/Profile/ProfileComponent.php +++ b/apps/Core/Components/System/Users/Profile/ProfileComponent.php @@ -60,6 +60,10 @@ public function viewAction() $this->view->canUse2fa = $this->profiles->packagesData->canUse2fa; + $this->view->countries = $this->basepackages->geoCountries->getAll()->geoCountries; + + $this->view->timezones = $this->basepackages->geoTimezones->getAll()->geoTimezones; + $apis = $this->api->getApiInfo(false, true); $passwordApis = []; if ($apis && count($apis) > 0) { diff --git a/apps/Core/Components/System/Workers/Tasks/TasksComponent.php b/apps/Core/Components/System/Workers/Tasks/TasksComponent.php index fc807c794..5453412b4 100644 --- a/apps/Core/Components/System/Workers/Tasks/TasksComponent.php +++ b/apps/Core/Components/System/Workers/Tasks/TasksComponent.php @@ -11,11 +11,15 @@ class TasksComponent extends BaseComponent protected $tasks; + protected $calls; + protected $schedules; public function initialize() { $this->tasks = $this->basepackages->workers->tasks; + + $this->calls = $this->basepackages->workers->calls->calls; } /** @@ -26,7 +30,29 @@ public function viewAction() $this->schedules = $this->basepackages->workers->schedules->schedules; if (isset($this->getData()['id'])) { - $calls = $this->tasks->getAllCalls(); + $calls = []; + + if ($this->calls && count($this->calls) > 0) { + foreach ($this->calls as $thisCalls) { + if (!$thisCalls['package']) { + continue; + } + + if (!isset($calls[$thisCalls['id']])) { + $calls[$thisCalls['id']] = []; + } + + $calls[$thisCalls['id']]['id'] = $thisCalls['id']; + $calls[$thisCalls['id']]['name'] = $thisCalls['display_name'] ?? $thisCalls['name']; + $calls[$thisCalls['id']]['description'] = $thisCalls['description']; + $calls[$thisCalls['id']]['package_id'] = $thisCalls['package_id']; + $calls[$thisCalls['id']]['package_name'] = $thisCalls['package']['display_name'] ?? $thisCalls['package']['name']; + } + } + + $this->tasks->setFFRelations(true); + + // $calls = $this->tasks->getAllCalls(); $this->view->calls = $calls; @@ -45,6 +71,7 @@ public function viewAction() $this->view->task = $task; } + $this->view->pick('tasks/view'); return; diff --git a/apps/Core/Packages/Adminltetags/Tags/Buttons/ButtonGroup.php b/apps/Core/Packages/Adminltetags/Tags/Buttons/ButtonGroup.php index 33a63ad07..7d22581a0 100644 --- a/apps/Core/Packages/Adminltetags/Tags/Buttons/ButtonGroup.php +++ b/apps/Core/Packages/Adminltetags/Tags/Buttons/ButtonGroup.php @@ -143,7 +143,9 @@ protected function buildButton() if ($this->params['groupRadioButtonChecked'] === $button['value']) { $hasButtonChecked = 'checked'; $hasButtonCheckedClasses = 'active focus'; - if ($this->params['groupRadioButtonStyle'] === 'outline') { + if (isset($this->params['groupRadioButtonStyle']) && + $this->params['groupRadioButtonStyle'] === 'outline' + ) { $hasButtonCheckedBgClass = ''; } else { $hasButtonCheckedBgClass = 'bg-' . $button['type']; @@ -157,7 +159,9 @@ protected function buildButton() if (isset($button['checked']) && $button['checked'] === true) { $hasButtonChecked = 'checked'; $hasButtonCheckedClasses = 'active focus'; - if ($this->params['groupRadioButtonStyle'] === 'outline') { + if (isset($this->params['groupRadioButtonStyle']) && + $this->params['groupRadioButtonStyle'] === 'outline' + ) { $hasButtonCheckedBgClass = ''; } else { $hasButtonCheckedBgClass = 'bg-' . $button['type']; @@ -169,7 +173,7 @@ protected function buildButton() } } - if (isset($buton['disabled']) && $buton['disabled'] === true) { + if (isset($button['disabled']) && $button['disabled'] === true) { $hasButtonDisabled = 'disabled'; $hasButtonCursor = 'style=cursor:default;'; } else { diff --git a/apps/Core/Packages/Adminltetags/Tags/Tree.php b/apps/Core/Packages/Adminltetags/Tags/Tree.php index dbc63acc2..8a1087b4a 100644 --- a/apps/Core/Packages/Adminltetags/Tags/Tree.php +++ b/apps/Core/Packages/Adminltetags/Tags/Tree.php @@ -398,7 +398,22 @@ protected function treeItem($key, $items, $itemIcon, $children = null) $key = $itemValue[$this->fieldParams['fieldDataSelect' . $selectType . 'OptionsKey']]; if (count($this->fieldParams['fieldDataSelect' . $selectType . 'OptionsValue']) === 1) { - $value = $itemValue[$this->fieldParams['fieldDataSelect' . $selectType . 'OptionsValue'][0]]; + if (str_contains($this->fieldParams['fieldDataSelect' . $selectType . 'OptionsValue'][0], '/')) { + $hierarchyOptionValue = explode('/', $this->fieldParams['fieldDataSelect' . $selectType . 'OptionsValue'][0]); + + if (count($hierarchyOptionValue) === 1) { + $value = $itemValue[$hierarchyOptionValue[0]]; + } else { + $itemValueArr = []; + $itemValueArr = $itemValue; + foreach ($hierarchyOptionValue as $optionsValueArr) { + $itemValueArr = $itemValueArr[$optionsValueArr]; + } + $value = $itemValueArr; + } + } else { + $value = $itemValue[$this->fieldParams['fieldDataSelect' . $selectType . 'OptionsValue'][0]]; + } } else { foreach ($this->fieldParams['fieldDataSelect' . $selectType . 'OptionsValue'] as $optionsValueKey) { if (is_string($optionsValueKey)) { diff --git a/apps/Core/Packages/Adminltetags/Traits/DynamicTable.php b/apps/Core/Packages/Adminltetags/Traits/DynamicTable.php index b004cf455..d8b8295f9 100644 --- a/apps/Core/Packages/Adminltetags/Traits/DynamicTable.php +++ b/apps/Core/Packages/Adminltetags/Traits/DynamicTable.php @@ -21,7 +21,8 @@ public function generateDTContent( int $componentId = null, $resetCache = false, $enableCache = true, - $packageData = [] + $packageData = [], + $excludeColumns = [] ) { if (gettype($package) === 'string') { $package = $this->usePackage($package); @@ -43,9 +44,9 @@ public function generateDTContent( $modelsColumnMap = $package->getModelsColumnMap($this->removeEscapeFromName($columnsForTable)); if (isset($modelsColumnMap['columns'])) { - $table['columns'] = $this->sortColumns($columnsForTable, $modelsColumnMap['columns']); + $table['columns'] = $this->sortColumns($columnsForTable, $modelsColumnMap['columns'], $excludeColumns); } else { - $table['columns'] = $this->sortColumns($columnsForTable, $modelsColumnMap); + $table['columns'] = $this->sortColumns($columnsForTable, $modelsColumnMap, $excludeColumns); } if ($dtReplaceColumnsTitle && count($dtReplaceColumnsTitle) > 0) { @@ -80,9 +81,9 @@ public function generateDTContent( $modelsColumnMap = $package->getModelsColumnMap($this->removeEscapeFromName($columnsForFilter)); if (isset($modelsColumnMap['columns'])) { - $table['filterColumns'] = $this->sortColumns($columnsForFilter, $modelsColumnMap['columns']); + $table['filterColumns'] = $this->sortColumns($columnsForFilter, $modelsColumnMap['columns'], $excludeColumns); } else { - $table['filterColumns'] = $this->sortColumns($columnsForFilter, $modelsColumnMap); + $table['filterColumns'] = $this->sortColumns($columnsForFilter, $modelsColumnMap, $excludeColumns); } foreach ($filtersArr as $key => $filter) { @@ -281,7 +282,7 @@ protected function extractColumnsForTable($columnsForTable, $rows) return $rows; } - protected function sortColumns($columnsForTable, $dbColumns) + protected function sortColumns($columnsForTable, $dbColumns, $excludeColumns = []) { $columnsForTable = $this->removeEscapeFromName($columnsForTable); @@ -290,6 +291,10 @@ protected function sortColumns($columnsForTable, $dbColumns) $sortedColumns = array_merge(['id' => $dbColumns['id']]); foreach ($columnsForTable as $key => $column) { + if (in_array($column, $excludeColumns)) { + continue; + } + if ($column !== 'id') { if ($dbColumns[$column]) { $sortedColumns[$column] = $dbColumns[$column]; diff --git a/apps/Core/Packages/Devtools/Modules/DevtoolsModules.php b/apps/Core/Packages/Devtools/Modules/DevtoolsModules.php index f71fc4d5e..e651ca3e8 100644 --- a/apps/Core/Packages/Devtools/Modules/DevtoolsModules.php +++ b/apps/Core/Packages/Devtools/Modules/DevtoolsModules.php @@ -647,7 +647,7 @@ public function validateFilesHash($module) (isset($module['repo_details']['latestRelease']['name']) && $module['repo_details']['latestRelease']['name'] !== $module['version']) ) { - $module = $this->modules->manager->getModuleInfo( + $moduleSync = $this->modules->manager->getModuleInfo( [ 'module_type' => $module['module_type'], 'module_id' => $module['id'], @@ -655,11 +655,16 @@ public function validateFilesHash($module) 'getLatestRelease' => true ] ); + + if ($moduleSync) { + $module = array_merge($module, $moduleSync); + } } $module['repoExists'] = true; if (isset($module['repo_details']['latestRelease']['name'])) { + $module['latestRelease'] = []; $module['latestRelease'] = $module['repo_details']['latestRelease']['name']; } else { $module['latestRelease'] = false; @@ -3520,7 +3525,9 @@ public function generateModuleRepoUrl($data) $this->validation->init()->add('api_id', PresenceOf::class, ["message" => "Please provide api id."]); $this->validation->add('app_type', PresenceOf::class, ["message" => "Please provide app type."]); $this->validation->add('module_type', PresenceOf::class, ["message" => "Please provide module type."]); - $this->validation->add('category', PresenceOf::class, ["message" => "Please provide module category."]); + if ($data['module_type'] !== 'bundles') { + $this->validation->add('category', PresenceOf::class, ["message" => "Please provide module category."]); + } if (!$this->validateData($data)) { return false; diff --git a/apps/Core/Views/Default/html/devtools/modules/module.html b/apps/Core/Views/Default/html/devtools/modules/module.html index 542fcbbac..764a6602d 100644 --- a/apps/Core/Views/Default/html/devtools/modules/module.html +++ b/apps/Core/Views/Default/html/devtools/modules/module.html @@ -3515,16 +3515,18 @@ path += routeArr.join('/'); } else { + var nameArr; if (moduleType === 'views') { if (dataCollectionSectionForm['vars']['subview']) { path += dataCollectionSectionForm['vars']['moduleDependencies']['views'][0]['name'] + '/html/'; - path += $('#{{componentId}}-{{sectionId}}-name').val().toLowerCase(); + nameArr = $('#{{componentId}}-{{sectionId}}-name').val().split(/(?=[A-Z])/); + path += nameArr.join('/').toLowerCase(); } else { path += $('#{{componentId}}-{{sectionId}}-name').val(); } pathPublic += $('#{{componentId}}-{{sectionId}}-name').val().toLowerCase(); } else { - var nameArr = $('#{{componentId}}-{{sectionId}}-name').val().split(/(?=[A-Z])/); + nameArr = $('#{{componentId}}-{{sectionId}}-name').val().split(/(?=[A-Z])/); path += nameArr.join('/'); } } diff --git a/apps/Core/Views/Default/html/modules/queue/analyse.html b/apps/Core/Views/Default/html/modules/queue/analyse.html index d82d44a83..cf5e6834b 100644 --- a/apps/Core/Views/Default/html/modules/queue/analyse.html +++ b/apps/Core/Views/Default/html/modules/queue/analyse.html @@ -250,7 +250,7 @@ dataCollectionSectionForm['vars']['queue'] = JSON.parse('{{queue}}'); dataCollectionSectionForm['funcs'] = { }; dataCollectionSectionForm['funcs']['init'] = function() { - BazProgress.buildProgressBar($('#installer-progress'), false, true, true, false); + BazProgress.buildProgressBar($('#installer-progress'), false, true, true, true); if ($.fn.DataTable && !$.fn.DataTable.isDataTable('#{{componentId}}-{{sectionId}}-queue-table')) { $('#{{componentId}}-{{sectionId}}-queue-table').DataTable({ diff --git a/apps/Core/Views/Default/html/system/users/accounts/form.html b/apps/Core/Views/Default/html/system/users/accounts/form.html index b016778ae..33bbb4457 100644 --- a/apps/Core/Views/Default/html/system/users/accounts/form.html +++ b/apps/Core/Views/Default/html/system/users/accounts/form.html @@ -63,6 +63,11 @@ [ 'tabTitle' : 'Tools', 'tabInclude' : 'accounts/form/tools' + ], + 'locale' : + [ + 'tabTitle' : 'Locale', + 'tabInclude' : 'accounts/form/locale' ] ] ] @@ -115,6 +120,12 @@ '{{componentId}}-{{sectionId}}-force_pwreset' : { }, '{{componentId}}-{{sectionId}}-force_logout' : { }, '{{componentId}}-{{sectionId}}-disable_twofa_otp' : { }, + '{{componentId}}-{{sectionId}}-locale_country_id' : { + placeholder : 'SELECT COUNTRY' + }, + '{{componentId}}-{{sectionId}}-locale_timezone_id' : { + placeholder : 'SELECT TIMEZONE' + }, //Validation '{{componentId}}-{{sectionId}}-form' : { ignore: ':submit, :reset, :image, :disabled, .ignore, .cr-slider', diff --git a/apps/Core/Views/Default/html/system/users/accounts/form/locale.html b/apps/Core/Views/Default/html/system/users/accounts/form/locale.html new file mode 100644 index 000000000..a88463875 --- /dev/null +++ b/apps/Core/Views/Default/html/system/users/accounts/form/locale.html @@ -0,0 +1,60 @@ +{% set countryId = 0 %} +{% if account['profile']['locale_country_id'] is defined %} + {% set countryId = account['profile']['locale_country_id'] %} +{% endif %} +{% set timezoneId = 0 %} +{% if account['profile']['locale_timezone_id'] is defined %} + {% set timezoneId = account['profile']['locale_timezone_id'] %} +{% endif %} +
+
+ {{adminltetags.useTag('fields', + [ + 'component' : component, + 'componentName' : componentName, + 'componentId' : componentId, + 'sectionId' : sectionId, + 'fieldId' : 'locale_country_id', + 'fieldLabel' : 'Country', + 'fieldType' : 'select2', + 'fieldHelp' : true, + 'fieldHelpTooltipContent' : 'Select country', + 'fieldRequired' : false, + 'fieldBazScan' : true, + 'fieldBazJstreeSearch' : true, + 'fieldBazPostOnCreate' : true, + 'fieldBazPostOnUpdate' : true, + 'fieldDataSelect2Options' : countries, + 'fieldDataSelect2OptionsKey' : 'id', + 'fieldDataSelect2OptionsValue' : 'name', + 'fieldDataSelect2OptionsArray' : true, + 'fieldDataSelect2OptionsSelected' : countryId + ] + )}} +
+
+ {{adminltetags.useTag('fields', + [ + 'component' : component, + 'componentName' : componentName, + 'componentId' : componentId, + 'sectionId' : sectionId, + 'fieldId' : 'locale_timezone_id', + 'fieldLabel' : 'Timezone', + 'fieldType' : 'select2', + 'fieldHelp' : true, + 'fieldHelpTooltipContent' : 'Select timezone', + 'fieldRequired' : false, + 'fieldBazScan' : true, + 'fieldBazJstreeSearch' : true, + 'fieldBazPostOnCreate' : true, + 'fieldBazPostOnUpdate' : true, + 'fieldDataSelect2Options' : timezones, + 'fieldDataSelect2OptionsKey' : 'id', + 'fieldDataSelect2OptionsValue' : 'zone_name', + 'fieldDataSelect2OptionsArray' : true, + 'fieldDataSelect2OptionsSelected' : timezoneId + ] + )}} +
+
\ No newline at end of file diff --git a/apps/Core/Views/Default/html/system/users/profile/form.html b/apps/Core/Views/Default/html/system/users/profile/form.html index a5fe97874..805d121d8 100644 --- a/apps/Core/Views/Default/html/system/users/profile/form.html +++ b/apps/Core/Views/Default/html/system/users/profile/form.html @@ -82,6 +82,12 @@ 'tabInclude' : 'profile/form/contactdetails', 'tabIncludeParams' : ['profile' : profile, 'account' : account] ], + 'locale' : + [ + 'tabTitle' : 'Locale', + 'tabInclude' : 'profile/form/locale', + 'tabIncludeParams' : ['profile' : profile, 'account' : account] + ], 'address' : [ 'tabTitle' : 'Address', @@ -326,6 +332,12 @@ '{{componentId}}-{{sectionId}}-secondary_email' : { }, '{{componentId}}-{{sectionId}}-cc_emails_to_secondary_email' : { }, '{{componentId}}-{{sectionId}}-contact_notes' : { }, + '{{componentId}}-{{sectionId}}-locale_country_id' : { + placeholder : 'SELECT COUNTRY' + }, + '{{componentId}}-{{sectionId}}-locale_timezone_id' : { + placeholder : 'SELECT TIMEZONE' + }, '{{componentId}}-{{sectionId}}-address_id' : { }, '{{componentId}}-{{sectionId}}-current_password' : { afterInit: function() { diff --git a/apps/Core/Views/Default/html/system/users/profile/form/locale.html b/apps/Core/Views/Default/html/system/users/profile/form/locale.html new file mode 100644 index 000000000..b7aaad65e --- /dev/null +++ b/apps/Core/Views/Default/html/system/users/profile/form/locale.html @@ -0,0 +1,60 @@ +{% set countryId = 0 %} +{% if profile['locale_country_id'] is defined %} + {% set countryId = profile['locale_country_id'] %} +{% endif %} +{% set timezoneId = 0 %} +{% if profile['locale_timezone_id'] is defined %} + {% set timezoneId = profile['locale_timezone_id'] %} +{% endif %} +
+
+ {{adminltetags.useTag('fields', + [ + 'component' : component, + 'componentName' : componentName, + 'componentId' : componentId, + 'sectionId' : sectionId, + 'fieldId' : 'locale_country_id', + 'fieldLabel' : 'Country', + 'fieldType' : 'select2', + 'fieldHelp' : true, + 'fieldHelpTooltipContent' : 'Select country', + 'fieldRequired' : false, + 'fieldBazScan' : true, + 'fieldBazJstreeSearch' : true, + 'fieldBazPostOnCreate' : true, + 'fieldBazPostOnUpdate' : true, + 'fieldDataSelect2Options' : countries, + 'fieldDataSelect2OptionsKey' : 'id', + 'fieldDataSelect2OptionsValue' : 'name', + 'fieldDataSelect2OptionsArray' : true, + 'fieldDataSelect2OptionsSelected' : countryId + ] + )}} +
+
+ {{adminltetags.useTag('fields', + [ + 'component' : component, + 'componentName' : componentName, + 'componentId' : componentId, + 'sectionId' : sectionId, + 'fieldId' : 'locale_timezone_id', + 'fieldLabel' : 'Timezone', + 'fieldType' : 'select2', + 'fieldHelp' : true, + 'fieldHelpTooltipContent' : 'Select timezone', + 'fieldRequired' : false, + 'fieldBazScan' : true, + 'fieldBazJstreeSearch' : true, + 'fieldBazPostOnCreate' : true, + 'fieldBazPostOnUpdate' : true, + 'fieldDataSelect2Options' : timezones, + 'fieldDataSelect2OptionsKey' : 'id', + 'fieldDataSelect2OptionsValue' : 'zone_name', + 'fieldDataSelect2OptionsArray' : true, + 'fieldDataSelect2OptionsSelected' : timezoneId + ] + )}} +
+
\ No newline at end of file diff --git a/apps/Core/Views/Default/html/system/workers/tasks/form.html b/apps/Core/Views/Default/html/system/workers/tasks/form.html index f5988a750..039d03a47 100644 --- a/apps/Core/Views/Default/html/system/workers/tasks/form.html +++ b/apps/Core/Views/Default/html/system/workers/tasks/form.html @@ -22,7 +22,7 @@ {% set taskScheduleDisabled = true %} {% endif %} {% set taskExecType = task['exec_type'] %} - {% set taskCall = task['call'] %} + {% set taskCall = task['cid'] %} {% set taskCallArgs = task['call_args'] %} {% else %} {% set taskId = '' %} @@ -259,8 +259,8 @@ 'componentName' : componentName, 'componentId' : componentId, 'sectionId' : sectionId, - 'fieldId' : 'call', - 'fieldLabel' : 'Call Function', + 'fieldId' : 'cid', + 'fieldLabel' : 'Call Function (Package)', 'fieldType' : 'select2', 'fieldHelp' : true, 'fieldHelpTooltipContent' : "Task's function to call", @@ -269,14 +269,34 @@ 'fieldBazPostOnCreate' : true, 'fieldBazPostOnUpdate' : true, 'fieldDataSelect2Options' : calls, - 'fieldDataSelect2OptionsKey' : 'func', - 'fieldDataSelect2OptionsValue' : 'name', + 'fieldDataSelect2OptionsKey' : 'id', + 'fieldDataSelect2OptionsValue' : 'name:package_name', 'fieldDataSelect2OptionsArray' : true, 'fieldDataSelect2OptionsSelected' : taskCall ] )}} +
+
+ {{adminltetags.useTag('fields', + [ + 'component' : component, + 'componentName' : componentName, + 'componentId' : componentId, + 'sectionId' : sectionId, + 'fieldId' : 'call_description', + 'fieldLabel' : false, + 'fieldType' : 'html', + 'fieldHelp' : false, + 'fieldHelpTooltipContent' : '', + 'fieldBazJstreeSearch' : false, + 'fieldBazScan' : false + ] + )}} +
+
+ {% set calls = json_encode(calls, 16) %}
{{adminltetags.useTag('fields', @@ -333,6 +353,9 @@ dataCollectionSection['{{componentId}}-{{sectionId}}-form']; } +dataCollectionSectionForm['vars'] = { }; +dataCollectionSectionForm['vars']['calls'] = JSON.parse('{{calls}}'); + dataCollectionSection = $.extend(dataCollectionSection, { '{{componentId}}-{{sectionId}}-id' : { }, @@ -361,21 +384,40 @@ '{{componentId}}-{{sectionId}}-schedule_id' : { placeholder : "SELECT SCHEDULE" }, - '{{componentId}}-{{sectionId}}-call' : { - placeholder : "SELECT FUNCTION TO CALL" + '{{componentId}}-{{sectionId}}-cid' : { + placeholder : "SELECT FUNCTION TO CALL", + afterInit: function() { + var id; + + $('#{{componentId}}-{{sectionId}}-call').on('select2:select', function(e) { + id = e.params.data.id; + + if (dataCollectionSectionForm['vars']['calls'][id]) { + if (dataCollectionSectionForm['vars']['calls'][id]['description'] && + dataCollectionSectionForm['vars']['calls'][id]['description'] !== '' + ) { + $('#{{componentId}}-{{sectionId}}-call_description').html(' ' + dataCollectionSectionForm['vars']['calls'][id]['description'] + ''); + } else { + $('#{{componentId}}-{{sectionId}}-call_description').html(''); + } + } else { + $('#{{componentId}}-{{sectionId}}-call_description').html(''); + } + }); + } }, '{{componentId}}-{{sectionId}}-form' : { rules: { '{{componentId}}-{{sectionId}}-name' : 'required', '{{componentId}}-{{sectionId}}-priority' : 'required', '{{componentId}}-{{sectionId}}-schedule_id' : 'required', - '{{componentId}}-{{sectionId}}-call' : 'required' + '{{componentId}}-{{sectionId}}-cid' : 'required' }, messages: { '{{componentId}}-{{sectionId}}-name' : 'Please enter Service name', '{{componentId}}-{{sectionId}}-priority' : 'Please enter priority between 1 and 10', '{{componentId}}-{{sectionId}}-schedule_id' : 'Please select a schedule', - '{{componentId}}-{{sectionId}}-call' : 'Please select a function to call' + '{{componentId}}-{{sectionId}}-cid' : 'Please select a function to call' } } }); diff --git a/public/core/default/js/footer/core/Baz/BazContentSectionWithListing.js b/public/core/default/js/footer/core/Baz/BazContentSectionWithListing.js index bead534ca..23cb8a766 100644 --- a/public/core/default/js/footer/core/Baz/BazContentSectionWithListing.js +++ b/public/core/default/js/footer/core/Baz/BazContentSectionWithListing.js @@ -1125,6 +1125,8 @@ next : '' }, zeroRecords : datatableOptions.zeroRecords, + emptyTable : ' Loading...', + info : 'Showing _START_ to _END_ of _TOTAL_ entries', infoEmpty : 'No entries found', infoFiltered : ' - filtered from _MAX_ shown entries', searchPlaceholder: 'Search shown ' + thisOptions.listOptions.componentName + '...', @@ -1211,6 +1213,18 @@ } that._tableInit(reDraw); that._registerEvents(); + if (response.rows) { + if (typeof response.rows === 'string') { + response.rows = JSON.parse(response.rows); + } + + if (response.rows.data && response.rows.data.length === 0) { + if ($('#' + sectionId + '-table tbody td.dataTables_empty').length === 1) { + $('.dataTables_empty').last().html('No entries found'); + $('.dataTables_info').html('No entries found'); + } + } + } }); // TODO: fix card-body height when more rows are loaded. // TODO: BULK Edit/Delete @@ -1298,33 +1312,32 @@ // Datatable Events //Responsive - thisOptions['datatable'].on('draw responsive-resize responsive-display', function() { + thisOptions['datatable'].on('draw responsive-resize responsive-display', function(e, datatable, row, showHide) { + if (e.type === 'responsive-display') { + if (showHide) { + $($(row.node()).next('.child')).find('li').prepend( + '' + ); + + that._changeResponsiveLiWidths($($(row.node()).next('.child'))); + + $($(row.node()).next('.child')).find('.dtr-expand').click(function() { + if ($(this).parent().is('.text-truncate')) { + $(this).parent().removeClass('text-truncate dt-colTextTruncate'); + $(this).removeClass('fa-plus-circle text-info').addClass('fa-minus-circle text-danger'); + } else { + $(this).parent().addClass('text-truncate dt-colTextTruncate'); + $(this).removeClass('fa-minus-circle text-danger').addClass('fa-plus-circle text-info'); + that._changeResponsiveLiWidths($($(row.node()).next('.child'))); + } + }); + } + } + BazContentLoader.init({}); thisOptions['datatable'].columns.adjust().responsive.recalc(); }); - //Toggle response rows open/close - thisOptions['datatable'].on('responsive-display', function(e, datatable, row, showHide) { - if (showHide) { - $($(row.node()).next('.child')).find('li').prepend( - '' - ); - - that._changeResponsiveLiWidths($($(row.node()).next('.child'))); - - $($(row.node()).next('.child')).find('.dtr-expand').click(function() { - if ($(this).parent().is('.text-truncate')) { - $(this).parent().removeClass('text-truncate dt-colTextTruncate'); - $(this).removeClass('fa-plus-circle text-info').addClass('fa-minus-circle text-danger'); - } else { - $(this).parent().addClass('text-truncate dt-colTextTruncate'); - $(this).removeClass('fa-minus-circle text-danger').addClass('fa-plus-circle text-info'); - that._changeResponsiveLiWidths($($(row.node()).next('.child'))); - } - }); - } - }); - //Search $('.dataTables_filter').find('input').keyup(function() { if ($(this).val() === '') { @@ -1332,12 +1345,6 @@ } }); - thisOptions['datatable'].on('draw', function () { - if ($('#' + sectionId + '-table tbody td.dataTables_empty').length === 1) { - $('.dataTables_empty').last().html('No entries found'); - } - }); - //Length Change thisOptions['datatable'].on('length.dt', function (e, settings, len) { if (len === -1) { diff --git a/public/core/default/js/footer/core/Baz/BazProgress.js b/public/core/default/js/footer/core/Baz/BazProgress.js index 646a13da1..3c2ae7099 100644 --- a/public/core/default/js/footer/core/Baz/BazProgress.js +++ b/public/core/default/js/footer/core/Baz/BazProgress.js @@ -203,7 +203,9 @@ var BazProgress = function() { if (hasDetails) { $('#' + $(element)[0].id + '-details-button').off(); - $('#' + $(element)[0].id + '-details-button').click(function() { + $('#' + $(element)[0].id + '-details-button').click(function(e) { + e.preventDefault(); + var text = $('#' + $(element)[0].id + '-details-button').text().toLowerCase(); if (text === 'show details') { diff --git a/public/core/default/js/footer/jsFooterCore.js b/public/core/default/js/footer/jsFooterCore.js index 67a732a4b..8146c4d58 100644 --- a/public/core/default/js/footer/jsFooterCore.js +++ b/public/core/default/js/footer/jsFooterCore.js @@ -6710,6 +6710,8 @@ Object.defineProperty(exports, '__esModule', { value: true }); next : '' }, zeroRecords : datatableOptions.zeroRecords, + emptyTable : ' Loading...', + info : 'Showing _START_ to _END_ of _TOTAL_ entries', infoEmpty : 'No entries found', infoFiltered : ' - filtered from _MAX_ shown entries', searchPlaceholder: 'Search shown ' + thisOptions.listOptions.componentName + '...', @@ -6796,6 +6798,18 @@ Object.defineProperty(exports, '__esModule', { value: true }); } that._tableInit(reDraw); that._registerEvents(); + if (response.rows) { + if (typeof response.rows === 'string') { + response.rows = JSON.parse(response.rows); + } + + if (response.rows.data && response.rows.data.length === 0) { + if ($('#' + sectionId + '-table tbody td.dataTables_empty').length === 1) { + $('.dataTables_empty').last().html('No entries found'); + $('.dataTables_info').html('No entries found'); + } + } + } }); // TODO: fix card-body height when more rows are loaded. // TODO: BULK Edit/Delete @@ -6883,31 +6897,30 @@ Object.defineProperty(exports, '__esModule', { value: true }); // Datatable Events //Responsive - thisOptions['datatable'].on('draw responsive-resize responsive-display', function() { - BazContentLoader.init({}); - thisOptions['datatable'].columns.adjust().responsive.recalc(); - }); - - //Toggle response rows open/close - thisOptions['datatable'].on('responsive-display', function(e, datatable, row, showHide) { - if (showHide) { - $($(row.node()).next('.child')).find('li').prepend( - '' - ); + thisOptions['datatable'].on('draw responsive-resize responsive-display', function(e, datatable, row, showHide) { + if (e.type === 'responsive-display') { + if (showHide) { + $($(row.node()).next('.child')).find('li').prepend( + '' + ); - that._changeResponsiveLiWidths($($(row.node()).next('.child'))); + that._changeResponsiveLiWidths($($(row.node()).next('.child'))); - $($(row.node()).next('.child')).find('.dtr-expand').click(function() { - if ($(this).parent().is('.text-truncate')) { - $(this).parent().removeClass('text-truncate dt-colTextTruncate'); - $(this).removeClass('fa-plus-circle text-info').addClass('fa-minus-circle text-danger'); - } else { - $(this).parent().addClass('text-truncate dt-colTextTruncate'); - $(this).removeClass('fa-minus-circle text-danger').addClass('fa-plus-circle text-info'); - that._changeResponsiveLiWidths($($(row.node()).next('.child'))); - } - }); + $($(row.node()).next('.child')).find('.dtr-expand').click(function() { + if ($(this).parent().is('.text-truncate')) { + $(this).parent().removeClass('text-truncate dt-colTextTruncate'); + $(this).removeClass('fa-plus-circle text-info').addClass('fa-minus-circle text-danger'); + } else { + $(this).parent().addClass('text-truncate dt-colTextTruncate'); + $(this).removeClass('fa-minus-circle text-danger').addClass('fa-plus-circle text-info'); + that._changeResponsiveLiWidths($($(row.node()).next('.child'))); + } + }); + } } + + BazContentLoader.init({}); + thisOptions['datatable'].columns.adjust().responsive.recalc(); }); //Search @@ -6917,12 +6930,6 @@ Object.defineProperty(exports, '__esModule', { value: true }); } }); - thisOptions['datatable'].on('draw', function () { - if ($('#' + sectionId + '-table tbody td.dataTables_empty').length === 1) { - $('.dataTables_empty').last().html('No entries found'); - } - }); - //Length Change thisOptions['datatable'].on('length.dt', function (e, settings, len) { if (len === -1) { @@ -12061,7 +12068,9 @@ var BazProgress = function() { if (hasDetails) { $('#' + $(element)[0].id + '-details-button').off(); - $('#' + $(element)[0].id + '-details-button').click(function() { + $('#' + $(element)[0].id + '-details-button').click(function(e) { + e.preventDefault(); + var text = $('#' + $(element)[0].id + '-details-button').text().toLowerCase(); if (text === 'show details') { diff --git a/public/index.php b/public/index.php index 482532023..fb46a35f0 100644 --- a/public/index.php +++ b/public/index.php @@ -94,4 +94,4 @@ } } } -} +} \ No newline at end of file diff --git a/system/Base/BaseComponent.php b/system/Base/BaseComponent.php index 2797efbc2..074992f29 100644 --- a/system/Base/BaseComponent.php +++ b/system/Base/BaseComponent.php @@ -7,8 +7,8 @@ use Phalcon\Mvc\View; use System\Base\Exceptions\ControllerNotFoundException; use System\Base\Exceptions\IdNotFoundException; -use System\Base\Providers\ErrorServiceProvider\Exceptions\IncorrectCSRF; -use System\Base\Providers\ErrorServiceProvider\Exceptions\IncorrectRequestType; +use System\Base\Providers\ErrorServiceProvider\Exceptions\IncorrectCSRFException; +use System\Base\Providers\ErrorServiceProvider\Exceptions\IncorrectRequestTypeException; abstract class BaseComponent extends Controller { @@ -179,11 +179,11 @@ public function checkComponentWidgets() protected function requestIsPost($checkCSRF = true) { if (!$this->request->isPost()) { - throw new IncorrectRequestType('post'); + throw new IncorrectRequestTypeException('post'); } - if (!$this->checkCSRF()) { - return false; + if ($checkCSRF) { + $this->checkCSRF(); } } @@ -498,11 +498,12 @@ protected function checkCSRF() { if ($this->request->isPost() || $this->request->isPut() || $this->request->isDelete()) { if (!$this->security->checkToken(null, null, false)) { - $this->view->responseCode = 2; + throw new IncorrectCSRFException('CSRF Token Error! Please refresh page.'); + // $this->view->responseCode = 2; - $this->view->responseMessage = 'CSRF Token Error! Please refresh page.'; + // $this->view->responseMessage = 'CSRF Token Error! Please refresh page.'; - return $this->sendJson(); + // return $this->sendJson(); } } diff --git a/system/Base/BasePackage.php b/system/Base/BasePackage.php index 9b276cba3..2991a7e6d 100644 --- a/system/Base/BasePackage.php +++ b/system/Base/BasePackage.php @@ -190,7 +190,9 @@ public function getById(int $id, bool $resetCache = false, bool $enableCache = t return false; } else { - $this->ffStore = $this->ff->store($this->ffStoreToUse); + if (!$this->ffStore) { + $this->ffStore = $this->ff->store($this->ffStoreToUse); + } $this->ffData = $this->ffStore->findById($id, $this->ffRelations, $this->ffRelationsConditions); @@ -247,7 +249,9 @@ public function getFirst($by = null, $value = null, bool $resetCache = false, bo throw $e; } } else { - $this->ffStore = $this->ff->store($this->ffStoreToUse); + if (!$this->ffStore) { + $this->ffStore = $this->ff->store($this->ffStoreToUse); + } if ($by === 'id') { $value = (int) $value; @@ -277,9 +281,11 @@ public function getAll(bool $resetCache = false, bool $enableCache = true, $mode if ($this->config->databasetype === 'db') { $allPackages = $this->getByParams(['conditions'=>''], $resetCache, $enableCache, $model); } else { - $this->ffStore = $this->ff->store($this->ffStoreToUse); + if (!$this->ffStore) { + $this->ffStore = $this->ff->store($this->ffStoreToUse); + } - $allPackages = $this->ffStore->findAll(); + $allPackages = $this->ffStore->findAll(null, null, null, $this->ffRelations, $this->ffRelationsConditions); $this->setFfStoreToUse(); } @@ -357,7 +363,9 @@ public function getByParams(array $params, bool $resetCache = false, bool $enabl throw new \Exception('getByParams needs parameter conditions to be set.'); } else { - $this->ffStore = $this->ff->store($this->ffStoreToUse); + if (!$this->ffStore) { + $this->ffStore = $this->ff->store($this->ffStoreToUse); + } $relationColumns = []; @@ -1234,7 +1242,9 @@ public function add(array $data, $resetCache = true) $create = ${$this->packageNameModel}->create(); } else { - $this->ffStore = $this->ff->store($this->ffStoreToUse); + if (!$this->ffStore) { + $this->ffStore = $this->ff->store($this->ffStoreToUse); + } if ($this->ffAddUsingUpdateOrInsert) { if (isset($data['id']) && (int) $data['id'] !== 0) { @@ -1308,7 +1318,9 @@ public function update(array $data, $resetCache = true) $update = ${$this->packageNameModel}->update(); } else { - $this->ffStore = $this->ff->store($this->ffStoreToUse); + if (!$this->ffStore) { + $this->ffStore = $this->ff->store($this->ffStoreToUse); + } $update = $this->ffData = $this->ffStore->update($data); diff --git a/system/Base/Helpers.php b/system/Base/Helpers.php index 189780ee2..3ca32cf8f 100644 --- a/system/Base/Helpers.php +++ b/system/Base/Helpers.php @@ -248,17 +248,19 @@ function checkCtype($str, $ctype = 'alnum', $ignoreChars = null) { $ignoreChars = [' ', '&', '&', ',', ':', ';']; } + $string = trim(str_replace($ignoreChars, '' , $str)); + if ($ctype === 'alnum') { - if (ctype_alnum(trim(str_replace($ignoreChars, '' , $str)))) { - return trim(str_replace($ignoreChars, '' , $str)); + if (ctype_alnum($string)) { + return $string; } } else if ($ctype === 'alpha') { - if (ctype_alpha(trim(str_replace($ignoreChars, '' , $str)))) { - return trim(str_replace($ignoreChars, '' , $str)); + if (ctype_alpha($string)) { + return $string; } } else if ($ctype === 'digits') { - if (ctype_digit(trim(str_replace($ignoreChars, '' , $str)))) { - return trim(str_replace($ignoreChars, '' , $str)); + if (ctype_digit($string)) { + return $string; } } diff --git a/system/Base/Installer/Components/Setup.php b/system/Base/Installer/Components/Setup.php index 9d8ff6309..7f93ca565 100644 --- a/system/Base/Installer/Components/Setup.php +++ b/system/Base/Installer/Components/Setup.php @@ -788,8 +788,8 @@ protected function renderView($precheckFail = false, $onlyUpdateDb = false, $mes $this->session->getId(), time() + 600, '/', - null, - null, + false, + $this->request->getHttpHost(), true, [ 'samesite' => 'Strict' diff --git a/system/Base/Installer/Packages/Setup.php b/system/Base/Installer/Packages/Setup.php index b91cf62c4..287da976d 100644 --- a/system/Base/Installer/Packages/Setup.php +++ b/system/Base/Installer/Packages/Setup.php @@ -303,8 +303,8 @@ protected function cleanOldCookies() '0', 1, '/', - null, - null, + false, + $this->request->getHttpHost(), true ); @@ -315,8 +315,8 @@ protected function cleanOldCookies() '0', 1, '/', - null, - null, + false, + $this->request->getHttpHost(), true ); @@ -325,8 +325,8 @@ protected function cleanOldCookies() '0', 1, '/', - null, - null, + false, + $this->request->getHttpHost(), true ); @@ -611,7 +611,7 @@ protected function registerCoreMenu($componentJsonFile) protected function registerCorePackage(array $packageFile) { - return (new RegisterPackage())->register($this->db, $this->ff, $packageFile, $this->helper); + return (new RegisterPackage())->register($this->db, $this->ff, $packageFile, $this->helper, $this->basepackages, $this->container, $this->postData['databasetype']); } protected function registerCoreMiddleware(array $middlewareFile) @@ -754,7 +754,7 @@ protected function registerSchedules() protected function registerTasks() { - (new RegisterTasks())->register($this->db, $this->ff); + (new RegisterTasks())->register($this->db, $this->ff, $this->postData['databasetype']); return true; } diff --git a/system/Base/Installer/Packages/Setup/Register/Basepackages/Filter.php b/system/Base/Installer/Packages/Setup/Register/Basepackages/Filter.php index 45079dfe3..8c04f4edd 100644 --- a/system/Base/Installer/Packages/Setup/Register/Basepackages/Filter.php +++ b/system/Base/Installer/Packages/Setup/Register/Basepackages/Filter.php @@ -21,6 +21,7 @@ public function register($db, $ff) $filter = [ 'name' => 'Exclude Auto Generated Filters', + 'app_type' => 'core', 'component_id' => $filterComponent[0]['id'], 'conditions' => '-|auto_generated|equals|0&', 'filter_type' => 0, @@ -41,6 +42,7 @@ public function register($db, $ff) $filter = [ 'name' => 'Exclude Auto Generated Filters', + 'app_type' => 'core', 'component_id' => $filterComponent['id'], 'conditions' => '-|auto_generated|equals|0&', 'filter_type' => 0, diff --git a/system/Base/Installer/Packages/Setup/Register/Basepackages/Workers/Calls.php b/system/Base/Installer/Packages/Setup/Register/Basepackages/Workers/Calls.php new file mode 100644 index 000000000..9eea448c6 --- /dev/null +++ b/system/Base/Installer/Packages/Setup/Register/Basepackages/Workers/Calls.php @@ -0,0 +1,78 @@ +utils->init($container)->scanDir( + 'system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/' + ); + + if (count($callsArr['files']) > 0) { + foreach ($callsArr['files'] as $key => $call) { + $call = ucfirst($call); + $call = str_replace('/', '\\', $call); + $call = str_replace('.php', '', $call); + + $callClass = new $call; + $callReflection = new \ReflectionClass($call); + + if ($databasetype !== 'db') { + $callStorage = $ff->store('basepackages_workers_calls'); + + $dbCall = $callStorage->findBy(['name', '=', $callReflection->getShortName()]); + } else { + $dbCall = + $db->fetchAll( + "SELECT * FROM basepackages_workers_calls WHERE name = :name", + Enum::FETCH_ASSOC, + [ + "name" => $callReflection->getShortName(), + ] + ); + } + + if ($dbCall && count($dbCall) > 0) { + $dbCall = $dbCall[0]; + } + + if (!$dbCall) { + $dbCall = []; + $dbCall['name'] = $callReflection->getShortName(); + $dbCall['display_name'] = $callReflection->getShortName(); + $dbCall['class'] = $callReflection->getName(); + if ($callReflection->hasProperty('funcDisplayName')) { + $dbCall['display_name'] = $callReflection->getProperty('funcDisplayName')->getValue($callClass); + } + $dbCall['description'] = ''; + if ($callReflection->hasProperty('funcDescription')) { + $dbCall['description'] = $callReflection->getProperty('funcDescription')->getValue($callClass); + } + $dbCall['can_be_scheduled'] = true; + if ($callReflection->hasProperty('funcCanBeScheduled')) { + $dbCall['can_be_scheduled'] = $callReflection->getProperty('funcCanBeScheduled')->getValue($callClass); + } + $dbCall['can_be_run_on_demand'] = true; + if ($callReflection->hasProperty('funcCanBeRunOnDemand')) { + $dbCall['can_be_run_on_demand'] = $callReflection->getProperty('funcCanBeRunOnDemand')->getValue($callClass); + } + $dbCall['package_id'] = $corePackageId; + + if ($db) { + $db->insertAsDict('basepackages_workers_calls', $dbCall); + } + + if ($ff) { + $callStore = $ff->store('basepackages_workers_calls'); + + $callStore->updateOrInsert($dbCall); + } + } + } + } + } +} \ No newline at end of file diff --git a/system/Base/Installer/Packages/Setup/Register/Basepackages/Workers/Tasks.php b/system/Base/Installer/Packages/Setup/Register/Basepackages/Workers/Tasks.php index ee8494107..a78431312 100644 --- a/system/Base/Installer/Packages/Setup/Register/Basepackages/Workers/Tasks.php +++ b/system/Base/Installer/Packages/Setup/Register/Basepackages/Workers/Tasks.php @@ -4,8 +4,20 @@ class Tasks { - public function register($db, $ff) + protected $db; + + protected $ff; + + protected $databasetype; + + public function register($db, $ff, $databasetype) { + $this->db = $db; + + $this->ff = $ff; + + $this->databasetype = $databasetype; + $taskArr = $this->systemSchedules(); foreach ($taskArr as $key => $task) { @@ -23,6 +35,25 @@ public function register($db, $ff) protected function systemSchedules() { + if ($this->databasetype !== 'db') { + $callStore = $this->ff->store('basepackages_workers_calls'); + + $dbCall = $callStore->findBy(['name', '=', 'ProcessEmailQueue']); + } else { + $dbCall = + $this->db->fetchAll( + "SELECT * FROM basepackages_workers_calls WHERE name = :name", + Enum::FETCH_ASSOC, + [ + "name" => 'ProcessEmailQueue', + ] + ); + } + + if ($dbCall && count($dbCall) > 0) { + $dbCall = $dbCall[0]; + } + $taskArr = []; //Email High Priority (encrypted - with codes) @@ -31,7 +62,7 @@ protected function systemSchedules() 'name' => 'Email (Confidential)', 'description' => 'High priority emails that are confidential (with passwords or codes) that are time sensitive.', 'exec_type' => 'php', - 'call' => 'processemailqueue', + 'cid' => $dbCall['id'], 'call_args' => '{"priority":"1", "confidential":true}', 'schedule_id' => 1, 'is_on_demand' => 0, @@ -47,7 +78,7 @@ protected function systemSchedules() 'name' => 'Email (High Priority)', 'description' => 'High priority emails.', 'exec_type' => 'php', - 'call' => 'processemailqueue', + 'cid' => $dbCall['id'], 'call_args' => '{"priority":"1"}', 'schedule_id' => 0, 'is_on_demand' => 1, @@ -63,7 +94,7 @@ protected function systemSchedules() 'name' => 'Email (Medium Priority)', 'description' => 'Medium priority emails like notification emails.', 'exec_type' => 'php', - 'call' => 'processemailqueue', + 'cid' => $dbCall['id'], 'call_args' => '{"priority":"2"}', 'schedule_id' => 0, 'is_on_demand' => 1, @@ -79,7 +110,7 @@ protected function systemSchedules() 'name' => 'Email (Low Priority)', 'description' => 'Low priority emails like notification emails.', 'exec_type' => 'php', - 'call' => 'processemailqueue', + 'cid' => $dbCall['id'], 'call_args' => '{"priority":"3"}', 'schedule_id' => 0, 'is_on_demand' => 1, @@ -89,13 +120,30 @@ protected function systemSchedules() ]; array_push($taskArr, $taskEntry); + if ($this->databasetype !== 'db') { + $dbCall = $callStore->findBy(['name', '=', 'ProcessImportExportQueue']); + } else { + $dbCall = + $this->db->fetchAll( + "SELECT * FROM basepackages_workers_calls WHERE name = :name", + Enum::FETCH_ASSOC, + [ + "name" => 'ProcessImportExportQueue', + ] + ); + } + + if ($dbCall && count($dbCall) > 0) { + $dbCall = $dbCall[0]; + } + //Import/Export (Export) $taskEntry = [ 'name' => 'Import/Export (Export)', 'description' => 'Import/Export Tools - Export', 'exec_type' => 'php', - 'call' => 'processimportexportqueue', + 'cid' => $dbCall['id'], 'call_args' => '{"process":"export"}', 'schedule_id' => 0, 'is_on_demand' => 1, @@ -111,7 +159,7 @@ protected function systemSchedules() 'name' => 'Import/Export (Low Priority)', 'description' => 'Import/Export Tools - Import', 'exec_type' => 'php', - 'call' => 'processimportexportqueue', + 'cid' => $dbCall['id'], 'call_args' => '{"process":"import"}', 'schedule_id' => 0, 'is_on_demand' => 1, @@ -121,13 +169,31 @@ protected function systemSchedules() ]; array_push($taskArr, $taskEntry); + if ($this->databasetype !== 'db') { + $dbCall = $callStore->findBy(['name', '=', 'ProcessDbSync']); + } else { + $dbCall = + $this->db->fetchAll( + "SELECT * FROM basepackages_workers_calls WHERE name = :name", + Enum::FETCH_ASSOC, + [ + "name" => 'ProcessDbSync', + ] + ); + } + + if ($dbCall && count($dbCall) > 0) { + $dbCall = $dbCall[0]; + } + + //DB Sync (Hybrid Mode) $taskEntry = [ 'name' => 'DB Sync (Hybric Mode)', 'description' => 'Update database with changed made to the FF Store.', 'exec_type' => 'php', - 'call' => 'processdbsync', + 'cid' => $dbCall['id'], 'call_args' => '{}', 'schedule_id' => 0, 'is_on_demand' => 1, diff --git a/system/Base/Installer/Packages/Setup/Register/Modules/External.php b/system/Base/Installer/Packages/Setup/Register/Modules/External.php index 4f9beed19..c5aabcc82 100644 --- a/system/Base/Installer/Packages/Setup/Register/Modules/External.php +++ b/system/Base/Installer/Packages/Setup/Register/Modules/External.php @@ -2,6 +2,8 @@ namespace System\Base\Installer\Packages\Setup\Register\Modules; +use Phalcon\Db\Enum; + class External { public function register($db, $ff, $composerJsonFile, $helper) @@ -126,7 +128,7 @@ protected function getCoreId($db, $ff) ); if ($core) { - return $core['id']; + return $core[0]['id']; } } diff --git a/system/Base/Installer/Packages/Setup/Register/Modules/Package.php b/system/Base/Installer/Packages/Setup/Register/Modules/Package.php index 928a73473..9101c2dfd 100644 --- a/system/Base/Installer/Packages/Setup/Register/Modules/Package.php +++ b/system/Base/Installer/Packages/Setup/Register/Modules/Package.php @@ -2,9 +2,11 @@ namespace System\Base\Installer\Packages\Setup\Register\Modules; +use System\Base\Installer\Packages\Setup\Register\Basepackages\Workers\Calls; + class Package { - public function register($db, $ff, $packageFile, $helper) + public function register($db, $ff, $packageFile, $helper, $basepackages, $container, $databasetype) { $package = [ @@ -32,14 +34,30 @@ public function register($db, $ff, $packageFile, $helper) 'updated_by' => 0 ]; + $corePackageId = null; + if ($db) { $db->insertAsDict('modules_packages', $package); + + if ($package['name'] === 'Core') { + $corePackageId = (int) $db->lastInsertId(); + } } if ($ff) { $packageStore = $ff->store('modules_packages'); $packageStore->updateOrInsert($package); + + if ($package['name'] === 'Core') { + $corePackageId = (int) $packageStore->getLastInsertedId(); + } + } + + if ($corePackageId) { + $registerCalls = new Calls; + + $registerCalls->register($db, $ff, $basepackages, $container, $corePackageId, $databasetype); } } } \ No newline at end of file diff --git a/system/Base/Installer/Packages/Setup/Schema.php b/system/Base/Installer/Packages/Setup/Schema.php index 21fe9a780..9647bdef0 100644 --- a/system/Base/Installer/Packages/Setup/Schema.php +++ b/system/Base/Installer/Packages/Setup/Schema.php @@ -37,6 +37,7 @@ use System\Base\Installer\Packages\Setup\Schema\Basepackages\Users\Profiles; use System\Base\Installer\Packages\Setup\Schema\Basepackages\Users\Roles; use System\Base\Installer\Packages\Setup\Schema\Basepackages\Widgets; +use System\Base\Installer\Packages\Setup\Schema\Basepackages\Workers\Calls; use System\Base\Installer\Packages\Setup\Schema\Basepackages\Workers\Jobs; use System\Base\Installer\Packages\Setup\Schema\Basepackages\Workers\Schedules; use System\Base\Installer\Packages\Setup\Schema\Basepackages\Workers\Tasks; @@ -105,6 +106,7 @@ use System\Base\Providers\BasepackagesServiceProvider\Packages\Model\Users\BasepackagesUsersAccounts; use System\Base\Providers\BasepackagesServiceProvider\Packages\Model\Users\BasepackagesUsersProfiles; use System\Base\Providers\BasepackagesServiceProvider\Packages\Model\Users\BasepackagesUsersRoles; +use System\Base\Providers\BasepackagesServiceProvider\Packages\Model\Workers\BasepackagesWorkersCalls; use System\Base\Providers\BasepackagesServiceProvider\Packages\Model\Workers\BasepackagesWorkersJobs; use System\Base\Providers\BasepackagesServiceProvider\Packages\Model\Workers\BasepackagesWorkersSchedules; use System\Base\Providers\BasepackagesServiceProvider\Packages\Model\Workers\BasepackagesWorkersTasks; @@ -290,6 +292,10 @@ public function getSchema($dev) 'schema' => new Schedules, 'model' => new BasepackagesWorkersSchedules, ], + 'basepackages_workers_calls' => [ + 'schema' => new Calls, + 'model' => new BasepackagesWorkersCalls, + ], 'basepackages_workers_tasks' => [ 'schema' => new Tasks, 'model' => new BasepackagesWorkersTasks, diff --git a/system/Base/Installer/Packages/Setup/Schema/Basepackages/Filters.php b/system/Base/Installer/Packages/Setup/Schema/Basepackages/Filters.php index 216b96cfc..f82ad33e7 100644 --- a/system/Base/Installer/Packages/Setup/Schema/Basepackages/Filters.php +++ b/system/Base/Installer/Packages/Setup/Schema/Basepackages/Filters.php @@ -28,6 +28,14 @@ public function columns() 'notNull' => true, ] ), + new Column( + 'app_type', + [ + 'type' => Column::TYPE_VARCHAR, + 'size' => 50, + 'notNull' => true, + ] + ), new Column( 'component_id', [ diff --git a/system/Base/Installer/Packages/Setup/Schema/Basepackages/Users/Profiles.php b/system/Base/Installer/Packages/Setup/Schema/Basepackages/Users/Profiles.php index 4bfe32a5e..3e7a26e92 100644 --- a/system/Base/Installer/Packages/Setup/Schema/Basepackages/Users/Profiles.php +++ b/system/Base/Installer/Packages/Setup/Schema/Basepackages/Users/Profiles.php @@ -137,6 +137,20 @@ public function columns() 'notNull' => false, ] ), + new Column( + 'locale_country_id', + [ + 'type' => Column::TYPE_SMALLINTEGER, + 'notNull' => false, + ] + ), + new Column( + 'locale_timezone_id', + [ + 'type' => Column::TYPE_SMALLINTEGER, + 'notNull' => false, + ] + ), new Column( 'settings', [ diff --git a/system/Base/Installer/Packages/Setup/Schema/Basepackages/Workers/Calls.php b/system/Base/Installer/Packages/Setup/Schema/Basepackages/Workers/Calls.php new file mode 100644 index 000000000..2399eec68 --- /dev/null +++ b/system/Base/Installer/Packages/Setup/Schema/Basepackages/Workers/Calls.php @@ -0,0 +1,103 @@ + [ + new Column( + 'id', + [ + 'type' => Column::TYPE_SMALLINTEGER, + 'notNull' => true, + 'autoIncrement' => true, + 'primary' => true, + ] + ), + new Column( + 'name', + [ + 'type' => Column::TYPE_VARCHAR, + 'size' => 100, + 'notNull' => true, + ] + ), + new Column( + 'display_name', + [ + 'type' => Column::TYPE_VARCHAR, + 'size' => 255, + 'notNull' => true, + ] + ), + new Column( + 'description', + [ + 'type' => Column::TYPE_VARCHAR, + 'size' => 2048, + 'notNull' => false, + ] + ), + new Column( + 'class', + [ + 'type' => Column::TYPE_VARCHAR, + 'size' => 512, + 'notNull' => true, + ] + ), + new Column( + 'can_be_scheduled', + [ + 'type' => Column::TYPE_BOOLEAN, + 'notNull' => true, + ] + ), + new Column( + 'can_be_run_on_demand', + [ + 'type' => Column::TYPE_BOOLEAN, + 'notNull' => true, + ] + ), + new Column( + 'package_id', + [ + 'type' => Column::TYPE_INTEGER, + 'notNull' => true, + ] + ) + ], + 'indexes' => [ + new Index( + 'column_UNIQUE', + [ + 'class' + ], + 'UNIQUE' + ) + ] + ]; + } + + public function indexes() + { + return + [ + new Index( + 'column_INDEX', + [ + 'name' + ], + 'INDEX' + ) + ]; + } +} \ No newline at end of file diff --git a/system/Base/Installer/Packages/Setup/Schema/Basepackages/Workers/Tasks.php b/system/Base/Installer/Packages/Setup/Schema/Basepackages/Workers/Tasks.php index 5faa6adb3..f21545687 100644 --- a/system/Base/Installer/Packages/Setup/Schema/Basepackages/Workers/Tasks.php +++ b/system/Base/Installer/Packages/Setup/Schema/Basepackages/Workers/Tasks.php @@ -86,11 +86,10 @@ public function columns() 'notNull' => true, ] ), - new Column( - 'call', + new Column(//Call ID + 'cid', [ - 'type' => Column::TYPE_VARCHAR, - 'size' => 2048, + 'type' => Column::TYPE_INTEGER, 'notNull' => false, ] ), @@ -101,7 +100,7 @@ public function columns() 'notNull' => false, ] ), - new Column( + new Column(//Raw Process Id 'pid', [ 'type' => Column::TYPE_INTEGER, diff --git a/system/Base/Installer/Packages/Setup/Schema/Modules/Externals.php b/system/Base/Installer/Packages/Setup/Schema/Modules/Externals.php index df1756c5d..8dca5b5cf 100644 --- a/system/Base/Installer/Packages/Setup/Schema/Modules/Externals.php +++ b/system/Base/Installer/Packages/Setup/Schema/Modules/Externals.php @@ -148,7 +148,8 @@ public function columns() new Index( 'column_UNIQUE', [ - 'name' + 'name', + 'developer' ], 'UNIQUE' ) diff --git a/system/Base/Providers/AccessServiceProvider/Access/Auth.php b/system/Base/Providers/AccessServiceProvider/Access/Auth.php index 9cbc2d514..cfe969da2 100644 --- a/system/Base/Providers/AccessServiceProvider/Access/Auth.php +++ b/system/Base/Providers/AccessServiceProvider/Access/Auth.php @@ -246,7 +246,7 @@ protected function clearAccountRecaller() '0', 1, '/', - null, + $this->config->dev === true ? false : true, $this->domains->getDomain()['name'], true ); @@ -258,7 +258,7 @@ protected function clearAccountRecaller() '0', 1, '/', - null, + $this->config->dev === true ? false : true, $this->domains->getDomain()['name'], true ); @@ -495,7 +495,7 @@ protected function setUserIdCooikie() $this->account['id'], $this->cookieTimeout, '/', - null, + $this->config->dev === true ? false : true, $this->domains->getDomain()['name'], true ); @@ -647,7 +647,7 @@ protected function setRecaller() $identifier . $this->separator . $token, $this->cookieTimeout, '/', - null, + $this->config->dev === true ? false : true, $this->domains->getDomain()['name'], true ); diff --git a/system/Base/Providers/AccessServiceProvider/Access/Auth/Password.php b/system/Base/Providers/AccessServiceProvider/Access/Auth/Password.php index 4587b67af..a86379e01 100644 --- a/system/Base/Providers/AccessServiceProvider/Access/Auth/Password.php +++ b/system/Base/Providers/AccessServiceProvider/Access/Auth/Password.php @@ -280,8 +280,8 @@ protected function checkPwPolicyComplex($data) $stringLengthArr['max']['checkLength'] = (int) $this->core->core['settings']['security']['passwordPolicySettings']['passwordPolicyLengthMax']; $stringLengthArr['messageMinimum']['checkLength'] = "passwordPolicyLengthMin|Password minimum length requirement failed."; $stringLengthArr['messageMaximum']['checkLength'] = "passwordPolicyLengthMax|Password maximum length requirement failed."; - $stringLengthArr['includedMinimum']['checkLength'] = false; - $stringLengthArr['includedMaximum']['checkLength'] = false; + $stringLengthArr['includedMinimum']['checkLength'] = true; + $stringLengthArr['includedMaximum']['checkLength'] = true; //Uppercase if ($this->core->core['settings']['security']['passwordPolicySettings']['passwordPolicyUppercase'] == true) { @@ -305,8 +305,8 @@ protected function checkPwPolicyComplex($data) $stringLengthArr['max']['checkUpperLength'] = (int) $this->core->core['settings']['security']['passwordPolicySettings']['passwordPolicyUppercaseMaxCount']; $stringLengthArr['messageMinimum']['checkUpperLength'] = "passwordPolicyUppercaseMinCount|Password minimum length requirement failed."; $stringLengthArr['messageMaximum']['checkUpperLength'] = "passwordPolicyUppercaseMaxCount|Password maximum length requirement failed."; - $stringLengthArr['includedMinimum']['checkUpperLength'] = false; - $stringLengthArr['includedMaximum']['checkUpperLength'] = false; + $stringLengthArr['includedMinimum']['checkUpperLength'] = true; + $stringLengthArr['includedMaximum']['checkUpperLength'] = true; } $this->passwordPolicyErrors['passwordPolicyUppercaseInclude'] = false; @@ -329,8 +329,8 @@ protected function checkPwPolicyComplex($data) $stringLengthArr['max']['checkUpperInclude'] = 0; $stringLengthArr['messageMinimum']['checkUpperInclude'] = "passwordPolicyUppercaseInclude|Password has invalid uppercase character."; $stringLengthArr['messageMaximum']['checkUpperInclude'] = "passwordPolicyUppercaseInclude|Password has invalid uppercase character."; - $stringLengthArr['includedMinimum']['checkUpperInclude'] = false; - $stringLengthArr['includedMaximum']['checkUpperInclude'] = false; + $stringLengthArr['includedMinimum']['checkUpperInclude'] = true; + $stringLengthArr['includedMaximum']['checkUpperInclude'] = true; } } @@ -364,8 +364,8 @@ protected function checkPwPolicyComplex($data) $stringLengthArr['max']['checkLowerLength'] = (int) $this->core->core['settings']['security']['passwordPolicySettings']['passwordPolicyLowercaseMaxCount']; $stringLengthArr['messageMinimum']['checkLowerLength'] = "passwordPolicyLowercaseMinCount|Password minimum length requirement failed."; $stringLengthArr['messageMaximum']['checkLowerLength'] = "passwordPolicyLowercaseMaxCount|Password maximum length requirement failed."; - $stringLengthArr['includedMinimum']['checkLowerLength'] = false; - $stringLengthArr['includedMaximum']['checkLowerLength'] = false; + $stringLengthArr['includedMinimum']['checkLowerLength'] = true; + $stringLengthArr['includedMaximum']['checkLowerLength'] = true; } $this->passwordPolicyErrors['passwordPolicyLowercaseInclude'] = false; @@ -388,8 +388,8 @@ protected function checkPwPolicyComplex($data) $stringLengthArr['max']['checkLowerInclude'] = 0; $stringLengthArr['messageMinimum']['checkLowerInclude'] = "passwordPolicyLowercaseInclude|Password has invalid lowercase character."; $stringLengthArr['messageMaximum']['checkLowerInclude'] = "passwordPolicyLowercaseInclude|Password has invalid lowercase character."; - $stringLengthArr['includedMinimum']['checkLowerInclude'] = false; - $stringLengthArr['includedMaximum']['checkLowerInclude'] = false; + $stringLengthArr['includedMinimum']['checkLowerInclude'] = true; + $stringLengthArr['includedMaximum']['checkLowerInclude'] = true; } } @@ -423,8 +423,8 @@ protected function checkPwPolicyComplex($data) $stringLengthArr['max']['checkNumbersLength'] = (int) $this->core->core['settings']['security']['passwordPolicySettings']['passwordPolicyNumbersMaxCount']; $stringLengthArr['messageMinimum']['checkNumbersLength'] = "passwordPolicyNumbersMinCount|Password minimum length requirement failed."; $stringLengthArr['messageMaximum']['checkNumbersLength'] = "passwordPolicyNumbersMaxCount|Password maximum length requirement failed."; - $stringLengthArr['includedMinimum']['checkNumbersLength'] = false; - $stringLengthArr['includedMaximum']['checkNumbersLength'] = false; + $stringLengthArr['includedMinimum']['checkNumbersLength'] = true; + $stringLengthArr['includedMaximum']['checkNumbersLength'] = true; } $this->passwordPolicyErrors['passwordPolicyNumbersInclude'] = false; @@ -447,8 +447,8 @@ protected function checkPwPolicyComplex($data) $stringLengthArr['max']['checkNumbersInclude'] = 0; $stringLengthArr['messageMinimum']['checkNumbersInclude'] = "passwordPolicyNumbersInclude|Password has invalid numbers."; $stringLengthArr['messageMaximum']['checkNumbersInclude'] = "passwordPolicyNumbersInclude|Password has invalid numbers."; - $stringLengthArr['includedMinimum']['checkNumbersInclude'] = false; - $stringLengthArr['includedMaximum']['checkNumbersInclude'] = false; + $stringLengthArr['includedMinimum']['checkNumbersInclude'] = true; + $stringLengthArr['includedMaximum']['checkNumbersInclude'] = true; } } @@ -482,8 +482,8 @@ protected function checkPwPolicyComplex($data) $stringLengthArr['max']['checkSymbolsLength'] = (int) $this->core->core['settings']['security']['passwordPolicySettings']['passwordPolicySymbolsMaxCount']; $stringLengthArr['messageMinimum']['checkSymbolsLength'] = "passwordPolicySymbolsMinCount|Password minimum length requirement failed."; $stringLengthArr['messageMaximum']['checkSymbolsLength'] = "passwordPolicySymbolsMaxCount|Password maximum length requirement failed."; - $stringLengthArr['includedMinimum']['checkSymbolsLength'] = false; - $stringLengthArr['includedMaximum']['checkSymbolsLength'] = false; + $stringLengthArr['includedMinimum']['checkSymbolsLength'] = true; + $stringLengthArr['includedMaximum']['checkSymbolsLength'] = true; } $this->passwordPolicyErrors['passwordPolicySymbolsInclude'] = false; @@ -506,8 +506,8 @@ protected function checkPwPolicyComplex($data) $stringLengthArr['max']['checkSymbolsInclude'] = 0; $stringLengthArr['messageMinimum']['checkSymbolsInclude'] = "passwordPolicySymbolsInclude|Password has invalid symbols."; $stringLengthArr['messageMaximum']['checkSymbolsInclude'] = "passwordPolicySymbolsInclude|Password has invalid symbols."; - $stringLengthArr['includedMinimum']['checkSymbolsInclude'] = false; - $stringLengthArr['includedMaximum']['checkSymbolsInclude'] = false; + $stringLengthArr['includedMinimum']['checkSymbolsInclude'] = true; + $stringLengthArr['includedMaximum']['checkSymbolsInclude'] = true; } } diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/ApiClientServices/ApiClientServices.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/ApiClientServices/ApiClientServices.php index cfcbafbf6..df0812cfe 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/ApiClientServices/ApiClientServices.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/ApiClientServices/ApiClientServices.php @@ -183,6 +183,10 @@ protected function switchApiModel($api = null) $this->packageName = 'apiClientServices'; } + + if ($this->config->databasetype !== 'db') { + $this->ffStore = null; + } } public function addApi(array $data) diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Filters.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Filters.php index 88bb46ab7..6396eb868 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Filters.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Filters.php @@ -2,7 +2,6 @@ namespace System\Base\Providers\BasepackagesServiceProvider\Packages; -// use Apps\Core\Packages\Hrms\Employees\Employees; use System\Base\BasePackage; use System\Base\Providers\BasepackagesServiceProvider\Packages\Model\BasepackagesFilters; @@ -20,7 +19,6 @@ public function getFiltersForComponent(int $componentId) if ($checkShowAllFilters) { return $this->getFilters($componentId); - } else { $this->addShowAllFilter($componentId); @@ -48,15 +46,24 @@ protected function checkShowAllFilters(int $componentId) return $this->getByParams( [ - 'conditions' => 'component_id = :cid: AND auto_generated = :ag:', + 'conditions' => 'component_id = :cid: AND auto_generated = :ag: AND app_type = :at:', 'bind' => [ 'cid' => $componentId, - 'ag' => 1 + 'ag' => 1, + 'at' => $this->app['app_type'] ] ], true ); } else { - return $this->getByParams(['conditions' => [['component_id', '=', $componentId], ['auto_generated', '=', 1]]]); + return $this->getByParams( + ['conditions' => + [ + ['component_id', '=', $componentId], + ['auto_generated', '=', 1], + ['app_type', '=', $this->app['app_type']] + ] + ] + ); } } @@ -64,20 +71,15 @@ protected function getFilters(int $componentId, array $account = null) { $component = $this->modules->components->getComponentById($componentId); - // $employeesPackage = $this->init()->checkPackage('Apps\Core\Packages\Hrms\Employees\Employees'); - - // if ($employeesPackage) { - // $employeesPackage = new \Apps\Core\Packages\Hrms\Employees\Employees; - // } - if ($account && isset($account['id'])) { if ($this->config->databasetype === 'db') { $filtersArr = $this->getByParams( [ - 'conditions' => 'component_id = :cid: AND (account_id = :aid: OR account_id = :aid0:)', + 'conditions' => 'component_id = :cid: AND app_type = :at: AND (account_id = :aid: OR account_id = :aid0:)', 'bind' => [ 'cid' => $componentId, + 'at' => $this->app['app_type'], 'aid' => $account['id'], 'aid0' => 0 ] @@ -90,6 +92,7 @@ protected function getFilters(int $componentId, array $account = null) 'conditions' => [ ['component_id', '=', $componentId], + ['app_type', '=', $this->app['app_type']] ], [ ['account_id', '=', $account['id']], @@ -150,18 +153,6 @@ protected function getFilters(int $componentId, array $account = null) 'name' => $sharingAccount['email'] ]; } - - // if ($employeesPackage) { - // $employee = $employeesPackage->searchByAccountId($sharingAid); - - // if ($employee) { - // $filter['shared_ids']['eids'][$sharingAidKey] = - // [ - // 'id' => $sharingAid, - // 'name' => $employee['full_name'] - // ]; - // } - // } } } @@ -176,9 +167,10 @@ protected function getFilters(int $componentId, array $account = null) $sharedFiltersArr = $this->getByParams( [ - 'conditions' => 'component_id = :cid: AND shared_ids IS NOT NULL', + 'conditions' => 'component_id = :cid: AND app_type = :at: AND shared_ids IS NOT NULL', 'bind' => [ - 'cid' => $componentId + 'cid' => $componentId, + 'at' => $this->app['app_type'] ] ] ); @@ -188,6 +180,7 @@ protected function getFilters(int $componentId, array $account = null) [ 'conditions' => [ ['component_id', '=', $componentId], + ['app_type', '=', $this->app['app_type']], ['shared_ids', '!=', null] ] ] @@ -207,20 +200,11 @@ protected function getFilters(int $componentId, array $account = null) ) { foreach ($filter['shared_ids']['rids'] as $ridKey => $rid) { if ($rid == $account['role_id']) { + $sharedBy = $this->basepackages->accounts->getById($filter['account_id']); - // if ($employeesPackage) { - // $employee = $employeesPackage->searchByAccountId($filter['account_id']); - - // if ($employee) { - // $filter['employee_full_name'] = $employee['full_name']; - // } - // } else { - $sharedBy = $this->basepackages->accounts->getById($filter['account_id']); - - if ($sharedBy) { - $filter['account_email'] = $sharedBy['email']; - } - // } + if ($sharedBy) { + $filter['account_email'] = $sharedBy['email']; + } $filter['shared_ids'] = $this->escaper->escapeHtml($this->helper->encode($filter['shared_ids'])); @@ -235,20 +219,11 @@ protected function getFilters(int $componentId, array $account = null) ) { foreach ($filter['shared_ids']['aids'] as $aidKey => $aid) { if ($aid == $account['id']) { + $sharedBy = $this->basepackages->accounts->getById($filter['account_id']); - // if ($employeesPackage) { - // $employee = $employeesPackage->searchByAccountId($filter['account_id']); - - // if ($employee) { - // $filter['employee_full_name'] = $employee['full_name']; - // } - // } else { - $sharedBy = $this->basepackages->accounts->getById($filter['account_id']); - - if ($sharedBy) { - $filter['account_email'] = $sharedBy['email']; - } - // } + if ($sharedBy) { + $filter['account_email'] = $sharedBy['email']; + } $filter['shared_ids'] = $this->escaper->escapeHtml($this->helper->encode($filter['shared_ids'])); @@ -273,9 +248,10 @@ protected function getFilters(int $componentId, array $account = null) $filtersArr = $this->getByParams( [ - 'conditions' => 'component_id = :cid:', + 'conditions' => 'component_id = :cid: AND app_type = :at:', 'bind' => [ - 'cid' => $componentId + 'cid' => $componentId, + 'at' => $this->app['app_type'] ] ] ); @@ -284,7 +260,8 @@ protected function getFilters(int $componentId, array $account = null) $this->getByParams( [ 'conditions' => [ - ['component_id', '=', $componentId] + ['component_id', '=', $componentId], + ['app_type', '=', $this->app['app_type']] ] ] ); @@ -332,6 +309,7 @@ protected function addShowAllFilter(int $componentId) $this->addFilter( [ 'name' => 'Show All ' . $component['name'], + 'app_type' => $this->app['app_type'], 'conditions' => '', 'component_id' => $componentId, 'filter_type' => 0,//System @@ -386,6 +364,7 @@ protected function addFilterForNotifications($component) $this->addFilter( [ 'name' => $name, + 'app_type' => $this->app['app_type'], 'conditions' => $condition, 'component_id' => $component['id'], 'filter_type' => 0,//System @@ -445,6 +424,7 @@ protected function addFilterForEmailQueue($component) $this->addFilter( [ 'name' => $name, + 'app_type' => $this->app['app_type'], 'conditions' => $condition, 'component_id' => $component['id'], 'filter_type' => 0,//System @@ -504,6 +484,7 @@ protected function addFilterForWorkersJobs($component) $this->addFilter( [ 'name' => $name, + 'app_type' => $this->app['app_type'], 'conditions' => $condition, 'component_id' => $component['id'], 'filter_type' => 0,//System @@ -577,20 +558,8 @@ public function updateFilter(array $data) } if (isset($data['shared_ids']) && is_array($data['shared_ids'])) { - //Convert EmployeeIds to AccountIds $data['shared_ids']['aids'] = []; - // if (isset($data['shared_ids']['eids']) && count($data['shared_ids']['eids']) > 0) { - // $employees = $this->usePackage(Employees::class); - - // foreach ($data['shared_ids']['eids'] as $eidKey => $eid) { - // $searchEmployee = $employees->getById($eid); - - // if ($searchEmployee) { - // array_push($data['shared_ids']['aids'], $searchEmployee['id']); - // } - // } - // unset($data['shared_ids']['eids']); - // } + $data['shared_ids'] = $this->helper->encode($data['shared_ids']); } @@ -701,30 +670,39 @@ public function getDefaultFilter(int $componentId) if ($this->config->databasetype === 'db') { $params = [ - 'conditions' => 'component_id = :cid: AND is_default = :isd: AND account_id = :aid:', + 'conditions' => 'component_id = :cid: AND is_default = :isd: AND account_id = :aid: AND app_type = :at:', 'bind' => [ 'cid' => $componentId, 'isd' => '1', - 'aid' => $account['id'] + 'aid' => $account['id'], + 'at' => $this->app['app_type'] ] ]; } else { - $params = ['conditions' => [['component_id', '=', $componentId], ['is_default', '=', 1], ['account_id', '=', $account['id']]]]; + $params = ['conditions' => + [ + ['component_id', '=', $componentId], + ['is_default', '=', 1], + ['account_id', '=', $account['id']], + ['app_type', '=', $this->app['app_type']], + ] + ]; } } else { if ($this->config->databasetype === 'db') { $params = [ - 'conditions' => 'component_id = :cid: AND is_default = :isd:', + 'conditions' => 'component_id = :cid: AND is_default = :isd: AND app_type = :at:', 'bind' => [ 'cid' => $componentId, - 'isd' => '1' + 'isd' => '1', + 'at' => $this->app['app_type'] ] ]; } else { - $params = ['conditions' => [['component_id', '=', $componentId], ['is_default', '=', 1]]]; + $params = ['conditions' => [['component_id', '=', $componentId], ['is_default', '=', 1], ['app_type', '=', $this->app['app_type']]]]; } } diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/BasepackagesFilters.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/BasepackagesFilters.php index 78249dfe1..68e089d4b 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/BasepackagesFilters.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/BasepackagesFilters.php @@ -10,6 +10,8 @@ class BasepackagesFilters extends BaseModel public $name; + public $app_type; + public $component_id; public $conditions; diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Users/BasepackagesUsersProfiles.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Users/BasepackagesUsersProfiles.php index ea8b6076d..243d8c1bc 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Users/BasepackagesUsersProfiles.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Users/BasepackagesUsersProfiles.php @@ -42,6 +42,10 @@ class BasepackagesUsersProfiles extends BaseModel public $contact_notes; + public $locale_country_id; + + public $locale_timezone_id; + public $settings; public function initialize() diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Workers/BasepackagesWorkersCalls.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Workers/BasepackagesWorkersCalls.php new file mode 100644 index 000000000..c6c5b3f92 --- /dev/null +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Workers/BasepackagesWorkersCalls.php @@ -0,0 +1,50 @@ +modelRelations['package']['relationObj'] = $this->hasOne( + 'package_id', + ModulesPackages::class, + 'id', + [ + 'alias' => 'package' + ] + ); + + parent::initialize(); + } + + public function getModelRelations() + { + if (count($this->modelRelations) === 0) { + $this->initialize(); + } + + return $this->modelRelations; + } +} \ No newline at end of file diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Workers/BasepackagesWorkersTasks.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Workers/BasepackagesWorkersTasks.php index 1bbc9c91c..15cc45bb8 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Workers/BasepackagesWorkersTasks.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Model/Workers/BasepackagesWorkersTasks.php @@ -3,9 +3,12 @@ namespace System\Base\Providers\BasepackagesServiceProvider\Packages\Model\Workers; use System\Base\BaseModel; +use System\Base\Providers\BasepackagesServiceProvider\Packages\Model\Workers\BasepackagesWorkersCalls; class BasepackagesWorkersTasks extends BaseModel { + protected $modelRelations = []; + public $id; public $name; @@ -26,7 +29,7 @@ class BasepackagesWorkersTasks extends BaseModel public $exec_type; - public $call; + public $cid; public $call_args; @@ -41,4 +44,27 @@ class BasepackagesWorkersTasks extends BaseModel public $email; public $result; + + public function initialize() + { + $this->modelRelations['call']['relationObj'] = $this->hasOne( + 'cid', + BasepackagesWorkersCalls::class, + 'id', + [ + 'alias' => 'call' + ] + ); + + parent::initialize(); + } + + public function getModelRelations() + { + if (count($this->modelRelations) === 0) { + $this->initialize(); + } + + return $this->modelRelations; + } } \ No newline at end of file diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php index 93f0f8b9d..9a7e493fc 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Progress.php @@ -164,7 +164,6 @@ public function getProgress($session = null, $returnArray = false) 'totalPercentComplete' => $this->getPercentComplete($progressFile, false), 'percentComplete' => $this->getPercentComplete($progressFile), 'runners' => $progressFile['runners'] ?? false, - 'callResult' => $callResult, 'errors' => $errors, 'details' => $details ]; @@ -292,6 +291,10 @@ public function updateProgress($method, $callResult = null, $deleteFile = true, public function checkProcessIsRunning($progressFile = null) { + if ($this->progressFileName === 'setup') { + return; + } + if (!$progressFile) { $progressFile = $this->checkProgressFile(); } @@ -483,7 +486,11 @@ public function resetProgress($reRegisterMethods = true) $this->deleteProgressFile(true); if ($reRegisterMethods) { - $this->registerMethods($progressFile['registeredMethods']); + if (isset($progressFile['registeredMethods'])) { + $this->registerMethods($progressFile['registeredMethods']); + } else { + $this->registerMethods($progressFile['allProcesses']); + } } } @@ -519,41 +526,46 @@ public function cancelProgress($fileName = null) if ($progressFile) { if (isset($progressFile['pid']) && $progressFile['pid'] > 0) { - exec('ps -aux | grep ' . $progressFile['pid'], $output, $result); + return $this->terminatePid($progressFile); + } else { + $progressFile['runners']['running'] = false; + $progressFile['runners']['next'] = false; + $this->writeProgressFile(methods: [], progressFile: $progressFile, register: true); - if ($result === 0 && - count($output) > 0 - ) { - if (str_contains($output[0], 'php')) { - exec('kill -9 ' . $progressFile['pid'], $output, $result); + $this->addResponse('Process not running', 1); - if ($result !== 0) { - $this->addResponse('Error terminating process', 1, ['output' => $output]); + return false; + } + } else { + $this->addResponse('Error loading progressfile!', 1); - return false; - } + return false; + } + } - $this->writeProgressFile(methods: [],progressFile: $progressFile); + public function terminatePid($progressFile) + { + exec('ps -aux | grep ' . $progressFile['pid'], $output, $result); - $this->addResponse('Successfully terminating process'); + if ($result === 0 && count($output) > 0) { + if (str_contains($output[0], 'php')) { + exec('kill -9 ' . $progressFile['pid'], $output, $result); - return $this->resetProgress(); - } - } - } + if ($result !== 0) { + $this->addResponse('Error terminating process', 1, ['output' => $output]); - $progressFile['runners']['running'] = false; - $progressFile['runners']['next'] = false; - $this->writeProgressFile(methods: [], progressFile: $progressFile, register: true); + return false; + } - $this->addResponse('Process not running', 1); + $this->writeProgressFile(methods: [],progressFile: $progressFile); - return false; - } else { - $this->addResponse('Error loading progressfile!', 1); + $this->addResponse('Successfully terminating process'); - return false; + return $this->resetProgress(); + } } + + return true; } protected function readProgressFile($session = null) @@ -602,7 +614,11 @@ protected function writeProgressFile( $file['allProcesses'] = $file['registeredMethods'] = $methods; } else if ($unregister) { $progressFile = $this->readProgressFile(); - $file['allProcesses'] = $progressFile['registeredMethods']; + if (isset($progressFile['registeredMethods'])) { + $file['allProcesses'] = $progressFile['registeredMethods']; + } else { + $file['allProcesses'] = $progressFile['allProcesses']; + } } } @@ -667,7 +683,11 @@ protected function writeProgressFile( $file['runners'] = $runners; } - $file['registeredMethods'] = $progressFile['registeredMethods']; + if (isset($progressFile['registeredMethods'])) { + $file['registeredMethods'] = $progressFile['registeredMethods']; + } else { + $file['registeredMethods'] = $progressFile['allProcesses']; + } } $file['processes'] = $methods; diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Users/Accounts.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Users/Accounts.php index 915c9c48f..2d0fcdbbe 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Users/Accounts.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Users/Accounts.php @@ -24,6 +24,8 @@ class Accounts extends BasePackage public function getAccountById(int $id) { + $this->ffStore = $this->ff->store($this->ffStoreToUse); + $this->setFFRelations(true); $this->setFFRelationsConditions( @@ -886,6 +888,8 @@ function($allowed) use ($id, $appId) { } else { $this->ffStoreToUse = 'basepackages_users_accounts_canlogin'; + $this->ffStore = $this->ff->store($this->ffStoreToUse); + $this->getByParams(['conditions' => [['account_id', '=', $id],['app_id', '=', $appId]]]); $canLogin = $this->ffData; @@ -915,6 +919,8 @@ function($allowed) use ($id, $appId) { foreach ($canLogin as $login) { $this->ffStoreToUse = 'basepackages_users_accounts_canlogin'; + $this->ffStore = $this->ff->store($this->ffStoreToUse); + $this->remove($login['id']); } } @@ -945,6 +951,8 @@ function($sessionObj) use ($id, $session) { if ($this->ffData) { $this->ffStoreToUse = 'basepackages_users_accounts_sessions'; + $this->ffStore = $this->ff->store($this->ffStoreToUse); + $this->getByParams(['conditions' => [['account_id', '=', $id],['session_id', '=', $session]]]); $hasSession = $this->ffData; diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Utils.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Utils.php index 328a46547..8c4baacc9 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Utils.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Utils.php @@ -238,16 +238,16 @@ protected function initPasswordGenerator($params = []) $maxCountTotal = 0; if (isset($params['passwordpolicyuppercase'])) { - $uppercase = $params['passwordpolicyuppercase'] == true ? true : false ; + $uppercase = $params['passwordpolicyuppercase'] == 'true' ? true : false ; } if (isset($params['passwordpolicylowercase'])) { - $lowercase = $params['passwordpolicylowercase'] == true ? true : false ; + $lowercase = $params['passwordpolicylowercase'] == 'true' ? true : false ; } if (isset($params['passwordpolicynumbers'])) { - $numbers = $params['passwordpolicynumbers'] == true ? true : false ; + $numbers = $params['passwordpolicynumbers'] == 'true' ? true : false ; } if (isset($params['passwordpolicysymbols'])) { - $symbols = $params['passwordpolicysymbols'] == true ? true : false ; + $symbols = $params['passwordpolicysymbols'] == 'true' ? true : false ; } if (isset($params['passwordpolicyavoidsimilar'])) { $avoid_similar = $params['passwordpolicyavoidsimilar'] == 'true' ? true : false ; diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers.php index 252844a61..380b0d549 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers.php @@ -2,16 +2,16 @@ namespace System\Base\Providers\BasepackagesServiceProvider\Packages; -use GO\Scheduler; use Carbon\Carbon; +use GO\Scheduler; use GO\Traits\Interval; -use System\Base\BasePackage; -use League\Flysystem\UnableToReadFile; use League\Flysystem\FilesystemException; -use System\Base\Providers\BasepackagesServiceProvider\Packages\Workers\Jobs; +use League\Flysystem\UnableToReadFile; +use System\Base\BasePackage; use System\Base\Providers\BasepackagesServiceProvider\Packages\Workers\Calls; -use System\Base\Providers\BasepackagesServiceProvider\Packages\Workers\Tasks; +use System\Base\Providers\BasepackagesServiceProvider\Packages\Workers\Jobs; use System\Base\Providers\BasepackagesServiceProvider\Packages\Workers\Schedules; +use System\Base\Providers\BasepackagesServiceProvider\Packages\Workers\Tasks; use System\Base\Providers\BasepackagesServiceProvider\Packages\Workers\Workers as WorkersWorkers; class Workers extends BasePackage @@ -30,6 +30,8 @@ class Workers extends BasePackage public $jobs; + public $calls; + protected $cron; protected $scheduledJobs = []; @@ -46,12 +48,10 @@ class Workers extends BasePackage protected $enabledTasks; - protected $availableCalls; + // protected $availableCalls; protected $outputDir; - protected $calls; - public function init(bool $resetCache = false) { $this->workers = (new WorkersWorkers())->init(true); @@ -62,6 +62,8 @@ public function init(bool $resetCache = false) $this->jobs = (new Jobs())->init(); + $this->calls = (new Calls())->init(); + if ($this->checkPath('var/workers')) { $this->schedulerSettings['tempDir'] = base_path('var/workers'); } @@ -79,7 +81,23 @@ public function init(bool $resetCache = false) $this->enabledTasks = $this->tasks->getEnabledTasks(); - $this->availableCalls = array_keys($this->tasks->getAllCalls()); + $this->availableCalls = []; + + if ($this->calls->calls && count($this->calls->calls) > 0) { + foreach ($this->calls->calls as $thisCalls) { + if (!$thisCalls['package']) { + continue; + } + + if (!isset($calls[$thisCalls['id']])) { + $calls[$thisCalls['id']] = []; + } + + $this->availableCalls[$thisCalls['id']]['id'] = $thisCalls['id']; + $this->availableCalls[$thisCalls['id']]['name'] = $thisCalls['name']; + $this->availableCalls[$thisCalls['id']]['package_class'] = $thisCalls['package']['class']; + } + } return $this; } @@ -108,8 +126,16 @@ public function run() $schedule = $this->schedules->getSchedulesSchedule($task['schedule_id']); $class = null; - if (in_array($task['call'], $this->availableCalls)) { - $class = 'System\\Base\\Providers\\BasepackagesServiceProvider\\Packages\\Workers\\Calls\\' . ucfirst($task['call']); + if (isset($this->availableCalls[$task['cid']])) { + if (str_starts_with($this->availableCalls[$task['cid']]['package_class'], 'System')) { + $class = 'System\\Base\\Providers\\BasepackagesServiceProvider\\Packages\\Workers\\Calls\\' . ucfirst($this->availableCalls[$task['cid']]['name']); + } else if (str_starts_with($this->availableCalls[$task['cid']]['package_class'], 'Apps')) { + $packageClassArr = explode('\\', $this->availableCalls[$task['cid']]['package_class']); + unset($packageClassArr[$this->helper->lastKey($packageClassArr)]); + $this->availableCalls[$task['cid']]['package_class'] = implode('\\', $packageClassArr); + + $class = $this->availableCalls[$task['cid']]['package_class'] . '\\TaskCalls\\' . ucfirst($this->availableCalls[$task['cid']]['name']); + } } else { $task['enabled'] = 0; $task['status'] = 3;//Error @@ -430,7 +456,6 @@ protected function shouldSchedule($task, $schedule) (int) $schedule['params']['minutes'] )->executionTime; - // $secsLeft = $this->cron->getNextRunDate()->getTimestamp() - time(); $nextRun = $this->cron->getNextRunDate()->format('Y-m-d H:i:s'); } else if ($schedule['type'] === 'hourly') { $this->cron = @@ -438,7 +463,6 @@ protected function shouldSchedule($task, $schedule) (int) $schedule['params']['hourly_minutes'] )->executionTime; - // $secsLeft = $this->cron->getNextRunDate()->getTimestamp() - time(); $nextRun = $this->cron->getNextRunDate()->format('Y-m-d H:i:s'); } else if ($schedule['type'] === 'daily') { $this->cron = @@ -447,7 +471,6 @@ protected function shouldSchedule($task, $schedule) (int) $schedule['params']['daily_minutes'] )->executionTime; - // $secsLeft = $this->cron->getNextRunDate()->getTimestamp() - time(); $nextRun = $this->cron->getNextRunDate()->format('Y-m-d H:i:s'); if ($task['next_run'] !== $this->cron->getNextRunDate()) { @@ -670,7 +693,7 @@ protected function schedulePhpSchedules($class, $args, $schedule) $args['job']['id'] => null ]; - if (property_exists($class, 'php_args') && method_exists($class,'getPhpArgs')) { + if (method_exists($class,'getPhpArgs')) { $phpArgs = array_merge($phpArgs, (new $class)->getPhpArgs()); } @@ -813,21 +836,49 @@ protected function schedulePhpSchedules($class, $args, $schedule) protected function scheduleRawSchedules($class, $args, $schedule) { + $class = new $class; + + $rawCmd = null; + + if (method_exists($class, 'getRawCmd')) { + $rawCmd = $class->getRawCmd(); + } + + if (is_null($rawCmd)) { + $this->calls->packagesData->responseCode = 1; + $this->calls->packagesData->responseMessage = 'Raw command not provided in the Calls class file.'; + + $this->calls->addJobResult($this->calls->packagesData, $args); + + $this->calls->updateJobTask(4, $args); + + return false; + } + $rawArgs = []; - if (property_exists($class, 'raw_args') && method_exists($class,'getRawArgs')) { - $rawArgs = (new $class)->getRawArgs(); + if (method_exists($class,'getRawArgs')) { + $rawArgs = $class->getRawArgs(); } if ($schedule['type'] === 'everyminute') { $this->scheduler->raw( - $task['raw'], + $rawCmd, $rawArgs, $args['task']['id'] . '-' . $schedule['type'] - )->everyminute(); + )-> + onlyOne(null, $this->removeStuckLockFile($args['task'], $schedule, null, $rawCmd))-> + output($this->outputDir . '/' . $args['task']['id'] . '-' . $schedule['type'] . '.log')-> + before(function() use ($args) { + $this->processBefore($args); + })-> + then(function () use ($args) { + $this->processThen($args); + }, true) + ->everyminute(); } else if ($schedule['type'] === 'everyxminutes') { $this->scheduler->raw( - $task['raw'], + $rawCmd, $rawArgs, $args['task']['id'] . '-' . $schedule['type'] )->everyminute( @@ -835,45 +886,90 @@ protected function scheduleRawSchedules($class, $args, $schedule) ); } else if ($schedule['type'] === 'everyxminutesbetween') { $this->scheduler->raw( - $task['raw'], + $rawCmd, $rawArgs, $args['task']['id'] . '-' . $schedule['type'] - )->everyminute( + )-> + onlyOne(null, $this->removeStuckLockFile($args['task'], $schedule, null, $rawCmd))-> + output($this->outputDir . '/' . $args['task']['id'] . '-' . $schedule['type'] . '.log')-> + before(function() use ($args) { + $this->processBefore($args); + })-> + then(function () use ($args) { + $this->processThen($args); + }, true) + ->everyminute( (int) $schedule['params']['minutes'] ); } else if ($schedule['type'] === 'hourly') { $this->scheduler->raw( - $task['raw'], + $rawCmd, $rawArgs, $args['task']['id'] . '-' . $schedule['type'] - )->hourly( + )-> + onlyOne(null, $this->removeStuckLockFile($args['task'], $schedule, null, $rawCmd))-> + output($this->outputDir . '/' . $args['task']['id'] . '-' . $schedule['type'] . '.log')-> + before(function() use ($args) { + $this->processBefore($args); + })-> + then(function () use ($args) { + $this->processThen($args); + }, true) + ->hourly( (int) $schedule['params']['hourly_minutes'] ); } else if ($schedule['type'] === 'daily') { $this->scheduler->raw( - $task['raw'], + $rawCmd, $rawArgs, $args['task']['id'] . '-' . $schedule['type'] - )->daily( + )-> + onlyOne(null, $this->removeStuckLockFile($args['task'], $schedule, null, $rawCmd))-> + output($this->outputDir . '/' . $args['task']['id'] . '-' . $schedule['type'] . '.log')-> + before(function() use ($args) { + $this->processBefore($args); + })-> + then(function () use ($args) { + $this->processThen($args); + }, true) + ->daily( (int) $schedule['params']['daily_hours'], (int) $schedule['params']['daily_minutes'] ); } else if ($schedule['type'] === 'weekly') { $this->scheduler->raw( - $task['raw'], + $rawCmd, $rawArgs, $args['task']['id'] . '-' . $schedule['type'] . '-' . $day - )->weekly( + )-> + onlyOne(null, $this->removeStuckLockFile($args['task'], $schedule, null, $rawCmd))-> + output($this->outputDir . '/' . $args['task']['id'] . '-' . $schedule['type'] . '.log')-> + before(function() use ($args) { + $this->processBefore($args); + })-> + then(function () use ($args) { + $this->processThen($args); + }, true) + ->weekly( $this->dayOfWeek, (int) $schedule['params']['weekly_hours'], (int) $schedule['params']['weekly_minutes'] ); } else if ($schedule['type'] === 'monthly') { $this->scheduler->raw( - $task['raw'], + $rawCmd, $rawArgs, $args['task']['id'] . '-' . $schedule['type'] . '-' . $month - )->monthly( + )-> + onlyOne(null, $this->removeStuckLockFile($args['task'], $schedule, null, $rawCmd))-> + output($this->outputDir . '/' . $args['task']['id'] . '-' . $schedule['type'] . '.log')-> + before(function() use ($args) { + $this->processBefore($args); + })-> + then(function () use ($args) { + $this->processThen($args); + }, true) + ->monthly( (int) $this->month, (int) $this->dateOfMonth, (int) $schedule['params']['monthly_hours'], @@ -884,14 +980,16 @@ protected function scheduleRawSchedules($class, $args, $schedule) protected function processBefore($args) { - $this->calls = new Calls; - $this->calls->updateJobTask(2, $args); } - protected function processThen($args) + protected function processThen($args, $rawCmd = false) { - $args['task']['pid'] = $this->getTaskProcessId($args['task'], base_path('public/index.php workers exec')); + if ($rawCmd) { + $args['task']['pid'] = $this->getTaskProcessId($args['task'], null, $rawCmd); + } else { + $args['task']['pid'] = $this->getTaskProcessId($args['task'], base_path('public/index.php workers exec')); + } $this->basepackages->workers->tasks->updateTask($args['task']); // var_dump($args); @@ -951,6 +1049,7 @@ protected function getTaskProcessId($task, $phpScript = null, $rawCommand = null } else if ($task['exec_type'] === 'raw' && $rawCommand) { // } + return $pid; } diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls.php index 7b2684088..5f86f5636 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls.php @@ -3,13 +3,88 @@ namespace System\Base\Providers\BasepackagesServiceProvider\Packages\Workers; use System\Base\BasePackage; +use System\Base\Providers\BasepackagesServiceProvider\Packages\Model\Workers\BasepackagesWorkersCalls; class Calls extends BasePackage { + protected $modelToUse = BasepackagesWorkersCalls::class; + + protected $packageName = 'calls'; + + public $calls; + protected $startTime; protected $stopTime; + public function init(bool $resetCache = false) + { + $this->setFFRelations(true); + + $this->getAll($resetCache); + + return $this; + } + + public function getByCallName($name) + { + if ($this->config->databasetype === 'db') { + $conditions = + [ + 'conditions' => 'name = :name:', + 'bind' => + [ + 'name' => $name + ] + ]; + + $call = $this->getByParams($conditions); + } else { + $this->ffStore = $this->ff->store($this->ffStoreToUse); + + $call = $this->ffStore->findBy(['name', '=', $name]); + } + + if ($call && count($call) > 0) { + return $call[0]; + } + + return false; + } + + public function addCall(array $data) + { + if ($this->add($data)) { + $this->addResponse('Added new call ' . $data['name']); + } else { + $this->addResponse('Error adding new call', 1); + } + } + + public function updateCall(array $data) + { + $call = $this->getById($data['id']); + + $call = array_merge($call, $data); + + if ($this->update($call)) { + $this->addResponse('Updated call ' . $call['name']); + } else { + $this->addResponse('Error updating call', 1); + } + } + + public function removeCall(array $data) + { + $call = $this->getById($data['id']); + + if ($this->remove($data['id'])) { + $this->addResponse('Call removed'); + } else { + $this->addResponse('Error removing call', 1); + } + } + public function updateJobTask($status, $args) { $this->updateJob($status, $args); diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessDbSync.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessDbSync.php index 1e77f895c..892e82ea3 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessDbSync.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessDbSync.php @@ -7,7 +7,9 @@ class ProcessDbSync extends Calls { - public $funcName = 'Process DB Sync (Hybrid mode)'; + public $funcDisplayName = 'Process DB Sync (Hybrid mode)'; + + public $funcDescription = 'Process sync of FF data with DB data.'; public function run(array $args = []) { diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessEmailQueue.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessEmailQueue.php index 0836a5c24..98b5171ba 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessEmailQueue.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessEmailQueue.php @@ -6,7 +6,9 @@ class ProcessEmailQueue extends Calls { - public $funcName = 'Process Email Queue'; + public $funcDisplayName = 'Process Email Queue'; + + public $funcDescription = 'Process email queue with this call.'; protected $args; diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessImportExportQueue.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessImportExportQueue.php index 1d3f65a25..d343f3f46 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessImportExportQueue.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessImportExportQueue.php @@ -7,7 +7,9 @@ class ProcessImportExportQueue extends Calls { - public $funcName = 'Process Import/Export Queue'; + public $funcDisplayName = 'Process Import/Export Queue'; + + public $funcDescription = 'Process import/export processes with this call.'; protected $args; diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessPsef.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessPsef.php new file mode 100644 index 000000000..5a0e3fccb --- /dev/null +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/ProcessPsef.php @@ -0,0 +1,21 @@ +raw_cwd = 'ls -al /'; + + return $this->raw_cwd; + } +} \ No newline at end of file diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Schedules.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Schedules.php index a63e7af8a..435ce79a8 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Schedules.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Schedules.php @@ -76,16 +76,24 @@ public function removeSchedule(array $data) return false; } - $assignedToTasks = - $this->basepackages->workers->tasks->getByParams( + if ($this->config->databasetype === 'db') { + $params = [ 'conditions' => 'schedule_id = :sid:', 'bind' => [ 'sid' => $schedule['id'] ] - ] - ); + ]; + } else { + $params = [ + 'conditions' => [ + ['schedule_id', '=', $schedule['id']] + ] + ]; + } + + $assignedToTasks = $this->basepackages->workers->tasks->getByParams($params); if ($assignedToTasks && count($assignedToTasks) > 0) { $this->addResponse('Schedule assigned to task. Cannot remove schedule.', 1); diff --git a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Tasks.php b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Tasks.php index bdf4fb839..93c4ae35a 100644 --- a/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Tasks.php +++ b/system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Tasks.php @@ -13,65 +13,19 @@ class Tasks extends BasePackage protected $packageName = 'tasks'; - protected $callsDir = 'system/Base/Providers/BasepackagesServiceProvider/Packages/Workers/Calls/'; - public $tasks; - public function getFunctionsDir() - { - return $this->callsDir; - } - public function init(bool $resetCache = false) { + $this->setFFRelations(true); + $this->getAll($resetCache); return $this; } - public function getAllCalls() - { - $callsArr = - $this->localContent->listContents($this->callsDir, true) - ->filter(fn (StorageAttributes $attributes) => $attributes->isFile()) - ->map(fn (StorageAttributes $attributes) => $attributes->path()) - ->toArray(); - - $calls = []; - - if (count($callsArr) > 0) { - foreach ($callsArr as $key => $call) { - $call = ucfirst($call); - $call = str_replace('/', '\\', $call); - $call = str_replace('.php', '', $call); - - try { - $call = new $call(); - - $calls[$call->packageName]['func'] = $call->packageName; - $calls[$call->packageName]['name'] = $call->funcName; - - } catch (\throwable $e) { - - if ($this->config->logs->exceptions) { - $this->logger->logExceptions->critical(json_trace($e)); - } - continue; - } - } - } - - return $calls; - } - public function addTask(array $data) { - if (isset($data['type']) && $data['type'] == 0) { - $this->addResponse('Cannot add system task.', 1); - - return false; - } - if (!isset($data['priority']) || (isset($data['priority']) && $data['priority'] == '0')) { $data['priority'] = '1'; } @@ -90,14 +44,6 @@ public function updateTask(array $data) { $task = $this->getById($data['id']); - if (!isset($data['via_job']) && - (isset($task['type']) && $task['type'] == 0) - ) { - $this->addResponse('Cannot update system task.', 1); - - return false; - } - if (!isset($data['priority']) || (isset($data['priority']) && $data['priority'] == '0')) { $data['priority'] = '1'; } @@ -130,6 +76,8 @@ public function removeTask(array $data) public function forceNextRun(array $data) { + $this->setFFRelations(true); + $task = $this->getById($data['id']); $task = array_merge($task, $data); @@ -138,7 +86,7 @@ public function forceNextRun(array $data) if (isset($data['cancel']) && $data['cancel'] == 'true') { if ($this->config->databasetype === 'hybrid' && - $task['call'] === 'processdbsync' + $task['call']['name'] === 'ProcessDbSync' ) { $this->ff->setSync(false); } @@ -219,7 +167,7 @@ public function findByCallArgs($argValue, $argKey = null, $function = null) } foreach ($this->tasks as $taskKey => $task) { - if ($function && $task['call'] !== $function) { + if ($function && $task['call']['name'] !== $function) { continue; } @@ -242,7 +190,7 @@ public function findByCall($function) } foreach ($this->tasks as $taskKey => $task) { - if ($task['call'] === $function) { + if ($task['call']['name'] === $function) { return $task; } } diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff.php b/system/Base/Providers/DatabaseServiceProvider/Ff.php index 2de3aaf2f..3bf5e53ac 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff.php @@ -329,6 +329,8 @@ public function generateConfig($tableName, $tableClass, $tableModel, $configArr return $config; } + $config['uniqueFields'] = []; + $config['indexes'] = []; if (isset($tableClass->columns()['indexes'])) { foreach ($tableClass->columns()['indexes'] as $index) { if ($index->getType() === 'UNIQUE' && $index->getColumns() && count($index->getColumns()) > 0) { @@ -339,7 +341,7 @@ public function generateConfig($tableName, $tableClass, $tableModel, $configArr if (method_exists($tableClass, 'indexes')) { $columns = []; - $columnsTypeToIndex = [0,2,5,7,9,14];//int, chars, varchars + $columnsTypeToIndex = [0,2,5,7,9,14,22];//int, chars, varchars foreach ($tableClass->columns()['columns'] as $column) { $columns[$column->getName()] = $column; diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php b/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php index f61d8b518..a829443c6 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/DocumentFinder.php @@ -20,6 +20,14 @@ class DocumentFinder protected $storeConfiguration; + protected $minIndexChars = 3; + + protected $multiWords = true; + + protected $multiWordsSeparator = '+'; + + protected $minMultiWordsChars = 4; + public function __construct(string $storePath, array $queryBuilderProperties, string $primaryKey, $store) { $this->storePath = $storePath; @@ -31,6 +39,19 @@ public function __construct(string $storePath, array $queryBuilderProperties, st $this->store = $store; $this->storeConfiguration = $this->store->getStoreConfiguration(); + + if (isset($this->storeConfiguration['min_index_chars'])) { + $this->minIndexChars = $this->storeConfiguration['min_index_chars']; + } + if (isset($this->storeConfiguration['multi_words'])) { + $this->multiWords = $this->storeConfiguration['multi_words']; + } + if (isset($this->storeConfiguration['multi_words_separator'])) { + $this->multiWordsSeparator = $this->storeConfiguration['multi_words_separator']; + } + if (isset($this->storeConfiguration['min_multi_words_chars'])) { + $this->minMultiWordsChars = $this->storeConfiguration['min_multi_words_chars']; + } } public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible): array @@ -59,94 +80,19 @@ public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible) $indexSearched = false; - if ($this->storeConfiguration['indexing']) { - // This has to be rewritten to include multiple keywords using spaces - // Example: If we want to search for wes aus, it should search for all entries with Wes keyword and that also includes Aus keyword. + //Note: for now index searches are using "OR" condition. If there are 2 more conditions to search, + //both conditions data will be searched. This needs to be extended to include keywords like "OR" and "AND" + if ($this->storeConfiguration['readIndex']) { if (count($conditions) > 0) { - foreach ($conditions as $condition) { - if (isset($condition[0]) && - in_array($condition[0][0], $this->storeConfiguration['indexes']) - ) { - $indexSearched = true; - - $keyword = trim($condition[0][2], '%');//This needs to extend - - if (strlen($keyword) < $this->storeConfiguration['min_index_chars']) { - continue; - } - - $indexChars = strtolower(substr($keyword, 0, $this->storeConfiguration['min_index_chars'])); - - try { - $indexFile = IoHelper::getFileContent( - $this->storeConfiguration['indexesPath'] . $condition[0][0] . '/' . $indexChars . '.json' - ); - - $indexFile = strtolower($indexFile); - - $indexJson = json_decode($indexFile, true); - - if (count($indexJson) > 0) { - if ($limit && count($indexJson) > 0) { - self::skip($indexJson, $skip); - self::limit($indexJson, $limit); - } + foreach ($conditions as $conditionKey => $condition) { + $conditionArr = $condition; - if (isset($indexJson[strtolower($keyword)])) { - if (count($indexJson[strtolower($keyword)]) === 1) { - $indexIdData = $this->store->findById($indexJson[strtolower($keyword)][0]); - - if ($indexIdData) { - $found[] = $indexIdData; - } - } else { - foreach ($indexJson[strtolower($keyword)] as $id) { - $indexIdData = $this->store->findById($id); - - if ($indexIdData) { - $found[] = $indexIdData; - } - } - } - } else { - foreach ($indexJson as $key => $ids) { - if ($limit && count($ids) > $limit) { - - self::skip($ids, $skip); - self::limit($ids, $limit); - } - - $key = strtolower($key); - - if (strtolower($condition[0][1]) === 'like') { - if (str_starts_with($key, strtolower($keyword))) { - foreach ($ids as $id) { - $indexIdData = $this->store->findById($id); - - if ($indexIdData) { - $found[] = $indexIdData; - } - } - } - } else if ($condition[0][1] === '=' || - $condition[0][1] === '===' - ) { - if ($key === strtolower($keyword)) { - foreach ($ids as $id) { - $indexIdData = $this->store->findById($id); - - if ($indexIdData) { - $found[] = $indexIdData; - } - } - } - } - } - } - } - } catch (\Exception $e) { - $found = []; + if (is_array($condition[0])) { + foreach ($condition as $conditionArr) { + $this->processIndexes($conditionArr, $found, $skip, $limit); } + } else { + $this->processIndexes($conditionArr, $found, $skip, $limit); } } } @@ -236,6 +182,129 @@ public function findDocuments(bool $getOneDocument, bool $reduceAndJoinPossible) return $found; } + protected function processIndexes($conditionArr, &$found, $skip, $limit) + { + if (isset($conditionArr[0]) && + in_array($conditionArr[0], $this->storeConfiguration['indexes']) + ) { + $indexSearched = true; + + //trim % (like), change space to + for multikeyword search. + if (is_string($conditionArr[2])) { + $keyword = str_replace(' ', '+', strtolower(trim($conditionArr[0][2], '%'))); + } else { + $keyword = $conditionArr[2]; + } + + if ($this->multiWords === true && str_contains($keyword, '+')) { + $keywordArr = explode('+', $keyword); + + foreach ($keywordArr as $key => $keyword) { + if (strlen($keyword) < $this->minMultiWordsChars) { + continue; + } + + if (is_string($keyword)) { + $indexChars = strtolower(mb_substr($keyword, 0, $this->minIndexChars, 'UTF-8')); + } else { + $indexChars = $keyword; + } + + $found = array_merge($found, $this->searchIndexes($conditionArr, $indexChars, $skip, $limit, $keyword)); + } + } else { + if (is_string($keyword)) { + if (strlen($keyword) < $this->minIndexChars) { + return []; + } + + $indexChars = strtolower(mb_substr($keyword, 0, $this->minIndexChars, 'UTF-8')); + } else { + $indexChars = $keyword; + } + + $found = array_merge($found, $this->searchIndexes($conditionArr, $indexChars, $skip, $limit, $keyword)); + } + } + + return $found ?? []; + } + + protected function searchIndexes($condition, $indexChars, $skip, $limit, $keyword) + { + try { + $indexFile = IoHelper::getFileContent( + $this->storeConfiguration['indexesPath'] . $condition[0] . '/' . $indexChars . '.json' + ); + + $indexFile = strtolower($indexFile); + + $indexJson = json_decode($indexFile, true); + + if (count($indexJson) > 0) { + if ($limit && count($indexJson) > 0) { + self::skip($indexJson, $skip); + self::limit($indexJson, $limit); + } + + if (isset($indexJson[$keyword])) { + if (count($indexJson[$keyword]) === 1) { + $indexIdData = $this->store->findById($indexJson[$keyword][0]); + + if ($indexIdData) { + $found[] = $indexIdData; + } + } else { + foreach ($indexJson[$keyword] as $id) { + $indexIdData = $this->store->findById($id); + + if ($indexIdData) { + $found[] = $indexIdData; + } + } + } + } else { + foreach ($indexJson as $key => $ids) { + if ($limit && count($ids) > $limit) { + self::skip($ids, $skip); + self::limit($ids, $limit); + } + + $key = strtolower($key); + + if (strtolower($condition[1]) === 'like') { + if (str_starts_with($key, $indexChars)) { + foreach ($ids as $id) { + $indexIdData = $this->store->findById($id); + + if ($indexIdData) { + $found[] = $indexIdData; + } + } + } + } else if ($condition[1] === '=' || + $condition[1] === '===' + ) { + if ($key === $indexChars) { + foreach ($ids as $id) { + $indexIdData = $this->store->findById($id); + + if ($indexIdData) { + $found[] = $indexIdData; + } + } + } + } + } + } + } + } catch (\Exception $e) { + $found = []; + } + + return $found ?? []; + } + protected function getDataPath(): string { return $this->storePath . Store::dataDirectory; @@ -278,7 +347,7 @@ protected static function skip(array &$found, $skip) return; } - $found = array_slice($found, $skip); + $found = array_slice($found, $skip, null, true); } protected static function limit(array &$found, $limit) @@ -287,7 +356,7 @@ protected static function limit(array &$found, $limit) return; } - $found = array_slice($found, 0, $limit); + $found = array_slice($found, 0, $limit, true); } protected static function performSearch(array &$found, array $search, array $searchOptions) diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/IndexHandler.php b/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/IndexHandler.php index 5f2fb5364..e00ebb564 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/IndexHandler.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff/Classes/IndexHandler.php @@ -18,10 +18,12 @@ class IndexHandler protected $multiWordsSeparator = ' '; - protected $minMultiWordsChars = 5; + protected $minMultiWordsChars = 4; protected $folderPermissions = 0777; + protected $reIndexIndexes = []; + public function __construct(array $storeConfiguration) { $this->storeConfiguration = $storeConfiguration; @@ -56,13 +58,13 @@ public function __construct(array $storeConfiguration) } } - public function setIndex($content, $remove = false) + public function setIndex($content, $remove = false, $reIndex = false) { if (is_string($content)) { $content = json_decode($content, true); } - $indexPointer = $content['id']; + $contentId = $content['id']; IoHelper::createFolder($this->indexesPath, $this->folderPermissions); @@ -75,49 +77,110 @@ public function setIndex($content, $remove = false) $contentArr = explode($this->multiWordsSeparator, $content[$index]); if (count($contentArr) > 1) { - foreach ($contentArr as $content) { - if (strlen($content) < $this->minMultiWordsChars) { + foreach ($contentArr as $contentWord) { + $contentWord = strtolower($contentWord); + + if (strlen($contentWord) < $this->minMultiWordsChars) { continue; } - $indexChars = strtolower(mb_substr($content, 0, $this->minIndexChars, 'UTF-8')); + $indexChars = strtolower(mb_substr($contentWord, 0, $this->minIndexChars, 'UTF-8')); if (str_contains($indexChars, '/')) {//this will result in subdirectories continue; } - $this->writeIndex($indexPointer, $index, $indexChars, $content, $remove); + if (!checkCtype($contentWord, 'alpha')) {//Ignore Special chars + continue; + } + + if ($reIndex) { + $this->addToReindexIndexes($contentId, $index, $indexChars, $contentWord); + } else { + $this->writeIndex($contentId, $index, $indexChars, $contentWord, $remove); + } } } else { + $content[$index] = strtolower($content[$index]); + $indexChars = strtolower(mb_substr($content[$index], 0, $this->minIndexChars, 'UTF-8')); if (str_contains($indexChars, '/')) {//this will result in subdirectories continue; } - $this->writeIndex($indexPointer, $index, $indexChars, $content[$index], $remove); + if (!checkCtype($content[$index], 'alpha')) {//Ignore Special chars + continue; + } + + if ($reIndex) { + $this->addToReindexIndexes($contentId, $index, $indexChars, $content[$index]); + } else { + $this->writeIndex($contentId, $index, $indexChars, $content[$index], $remove); + } } } else { - $this->writeIndex($indexPointer, $index, $content[$index], $content[$index], $remove); + if ($reIndex) { + $this->addToReindexIndexes($contentId, $index, $content[$index], $content[$index]); + } else { + $this->writeIndex($contentId, $index, $content[$index], $content[$index], $remove); + } } } else { if (is_string($content[$index])) { + if (strlen($content[$index]) < $this->minIndexChars) { + continue; + } + + $content[$index] = strtolower($content[$index]); + $indexChars = strtolower(mb_substr($content[$index], 0, $this->minIndexChars, 'UTF-8')); if (str_contains($indexChars, '/')) {//this will result in subdirectories continue; } - $this->writeIndex($indexPointer, $index, $indexChars, $content[$index], $remove); + if (!checkCtype($content[$index], 'alpha')) {//Ignore Special chars + continue; + } + + if ($reIndex) { + $this->addToReindexIndexes($contentId, $index, $indexChars, $content[$index]); + } else { + $this->writeIndex($contentId, $index, $indexChars, $content[$index], $remove); + } } else { - $this->writeIndex($indexPointer, $index, $content[$index], $content[$index], $remove); + if ($reIndex) { + $this->addToReindexIndexes($contentId, $index, $content[$index], $content[$index]); + } else { + $this->writeIndex($contentId, $index, $content[$index], $content[$index], $remove); + } } } } } } - protected function writeIndex($indexPointer, $index, $indexChars, $content, $remove = false) + protected function addToReindexIndexes($contentId, $index, $indexChars, $content) + { + if (!isset($this->reIndexIndexes[$index])) { + $this->reIndexIndexes[$index] = []; + } + + if (!isset($this->reIndexIndexes[$index][$indexChars])) { + $this->reIndexIndexes[$index][$indexChars] = []; + } + + if (!isset($this->reIndexIndexes[$index][$indexChars][$content])) { + $this->reIndexIndexes[$index][$indexChars][$content] = []; + } + + if (!in_array($contentId, $this->reIndexIndexes[$index][$indexChars][$content])) { + array_push($this->reIndexIndexes[$index][$indexChars][$content], $contentId); + } + } + + protected function writeIndex($contentId, $index, $indexChars, $content, $remove = false) { try { $indexFile = $this->getIndex($index, $indexChars); @@ -129,7 +192,7 @@ protected function writeIndex($indexPointer, $index, $indexChars, $content, $rem if (isset($indexJson[$content])) { if ($remove) { - $key = array_search($indexPointer, $indexJson[$content]); + $key = array_search($contentId, $indexJson[$content]); if ($key !== false) { unset($indexJson[$content][$key]); @@ -138,14 +201,17 @@ protected function writeIndex($indexPointer, $index, $indexChars, $content, $rem if (count($indexJson[$content]) === 0) { return IoHelper::deleteFile($this->indexesPath . $index . '/' . $indexChars . '.json'); } + + $indexJson[$content] = array_values($indexJson[$content]); } else { - if (!in_array($indexPointer, $indexJson[$content])) { - array_push($indexJson[$content], $indexPointer); + if (!in_array($contentId, $indexJson[$content])) { + array_push($indexJson[$content], $contentId); } } } else { if (!$remove) { - $indexJson[$content] = [$indexPointer]; + $indexJson[$content] = [$contentId]; + $indexJson[$content] = array_values($indexJson[$content]); } } @@ -183,24 +249,32 @@ public function reIndex($dataPath = null) $dataPath = $this->storeConfiguration['storePath'] . 'data/'; } - if ($handle = opendir($dataPath)) { - while (false !== ($entry = readdir($handle))) { - if ($entry === "." || $entry === "..") { - continue; - } + $scanDir = scandir($dataPath); + $files = []; + array_walk($scanDir, function($file) use (&$files) { + if ($file !== '..' && $file !== '.') { + array_push($files, (int) str_replace('.json', '', $file)); + } + }); + sort($files); - $documentPath = $dataPath . $entry; + foreach ($files as $entry) { + $documentPath = $dataPath . $entry . '.json'; - try { - $data = IoHelper::getFileContent($documentPath); + try { + $data = IoHelper::getFileContent($documentPath); - $this->setIndex($data); - } catch (\Exception $exception) { - continue; - } + $this->setIndex($data, false, true); + } catch (Exception $exception) { + continue; } + } - closedir($handle); + //We write all index files here + foreach ($this->reIndexIndexes as $index => $files) { + foreach ($files as $content => $values) { + IoHelper::writeContentToFile($this->indexesPath . $index . '/' . $content . '.json', json_encode($values)); + } } } } \ No newline at end of file diff --git a/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php b/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php index 9fcfe38a9..f2d345965 100644 --- a/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php +++ b/system/Base/Providers/DatabaseServiceProvider/Ff/Store.php @@ -27,11 +27,12 @@ class Store protected $defaultCacheLifetime = null; protected $indexesPath = ''; + protected $readIndex = false; protected $indexing = false; protected $minIndexChars = 3; protected $multiWords = true; protected $multiWordsSeparator = ' '; - protected $minMultiWordsChars = 5; + protected $minMultiWordsChars = 4; protected $indexes = []; protected $model = null; @@ -129,27 +130,18 @@ public function getSchemaMetaData($relations = false) $rmd['columnUnique'] = []; $rmd['storeRelations'] = []; - if (isset($schemaArr['properties'])) { - foreach ($schemaArr['properties'] as $column => $property) { - if (isset($property['type'][1]) && $property['type'][1] === 'array') { - if (isset($property['relation'])) { - $relation = explode('|', $property['relation']); - - if (count($relation) > 0 && isset($relation[2])) { - try { - $relation[2] = explode('+', $relation[2])[0]; - $relationsStore = new Store($relation[2], $this->databasePath, $this->ff); - - $rmd = array_replace_recursive($rmd, $relationsStore->getSchemaMetaData()); - - $rmd['storeRelations'][$column] = []; - $rmd['storeRelations'][$column] = $relationsStore->getSchemaMetaData(); - $rmd['storeRelations'][$column]['relationStore'] = $relation[2]; - } catch (\Exception $e) { - throw $e; - } - } - } + if (isset($schemaArr['relations'])) { + foreach ($schemaArr['relations'] as $alias => $relation) { + if (isset($relation['table']) && isset($this->relationStores[$relation['table']])) { + $rmd = array_replace_recursive($rmd, $this->relationStores[$relation['table']]->getSchemaMetaData()); + $rmd['storeRelations'][$alias] = []; + $rmd['storeRelations'][$alias] = $this->relationStores[$relation['table']]->getSchemaMetaData(); + $rmd['storeRelations'][$alias]['relationStore'] = $relation['table']; + } else if (isset($relation[1]) && isset($this->relationStores[$relation[1]['table']])) { + $rmd = array_replace_recursive($rmd, $this->relationStores[$relation[1]['table']]->getSchemaMetaData()); + $rmd['storeRelations'][$alias] = []; + $rmd['storeRelations'][$alias] = $this->relationStores[$relation[1]['table']]->getSchemaMetaData(); + $rmd['storeRelations'][$alias]['relationStore'] = $relation[1]['table']; } } } @@ -1046,7 +1038,7 @@ public function getRelations($data, $relationsConditions = false) } if (isset($relationsConditions[$relation['alias']])) {//Relation with condition - $criteria = array_merge($criteria, $relationsConditions[$relation['alias']]); + array_push($criteria, [$relationsConditions[$relation['alias']]]); } try { @@ -1085,7 +1077,7 @@ public function getRelations($data, $relationsConditions = false) } if (isset($relationsConditions[$relation['alias']])) {//Relation with condition - $criteria = array_merge($criteria, $relationsConditions[$relation['alias']]); + array_push($criteria, [$relationsConditions[$relation['alias']]]); } try { @@ -1269,6 +1261,7 @@ protected function setConfigurationAndSchema(array $configuration = [], array $s if (count($configuration["indexes"]) > 0) { $configuration['indexing'] = true; + $configuration['readIndex'] = true; } } @@ -1280,6 +1273,14 @@ protected function setConfigurationAndSchema(array $configuration = [], array $s $this->indexing = $configuration["indexing"]; } + if (array_key_exists("readIndex", $configuration)) { + if (!is_bool($configuration["readIndex"])) { + throw new InvalidConfigurationException("readIndex has to be boolean"); + } + + $this->readIndex = $configuration["readIndex"]; + } + if (array_key_exists("auto_cache", $configuration)) { if (!is_bool($configuration["auto_cache"])) { throw new InvalidConfigurationException("auto_cache has to be boolean"); @@ -1405,27 +1406,28 @@ protected function storeConfiguration() { $this->storeConfiguration = [ - "auto_cache" => $this->useCache, - "cache_lifetime" => $this->defaultCacheLifetime, - "primary_key" => $this->primaryKey, + "auto_cache" => &$this->useCache, + "cache_lifetime" => &$this->defaultCacheLifetime, + "primary_key" => &$this->primaryKey, "search" => [ - "min_length" => $this->searchOptions["minLength"], - "mode" => $this->searchOptions["mode"], - "score_key" => $this->searchOptions["scoreKey"], - "algorithm" => $this->searchOptions["algorithm"] + "min_length" => &$this->searchOptions["minLength"], + "mode" => &$this->searchOptions["mode"], + "score_key" => &$this->searchOptions["scoreKey"], + "algorithm" => &$this->searchOptions["algorithm"] ], - "folder_permissions" => $this->folderPermissions, - "indexing" => $this->indexing, - "min_index_chars" => $this->minIndexChars, - "multi_words" => $this->multiWords, - "multi_words_separator" => $this->multiWordsSeparator, - "min_multi_words_chars" => $this->minMultiWordsChars, - "uniqueFields" => $this->uniqueFields, - "indexes" => $this->indexes, - "storePath" => $this->storePath, - "databasePath" => $this->databasePath, - "indexesPath" => $this->indexesPath, - "model" => $this->model + "folder_permissions" => &$this->folderPermissions, + "readIndex" => &$this->readIndex, + "indexing" => &$this->indexing, + "min_index_chars" => &$this->minIndexChars, + "multi_words" => &$this->multiWords, + "multi_words_separator" => &$this->multiWordsSeparator, + "min_multi_words_chars" => &$this->minMultiWordsChars, + "uniqueFields" => &$this->uniqueFields, + "indexes" => &$this->indexes, + "storePath" => &$this->storePath, + "databasePath" => &$this->databasePath, + "indexesPath" => &$this->indexesPath, + "model" => &$this->model ]; } @@ -1494,10 +1496,32 @@ protected function validateData(array $data) } if (count($criteria) > 0) { - $found = $this->findOneBy($criteria); + $found = $this->findBy($criteria); + + $duplicate = false; + + if ($found && count($found) > 0) { + foreach ($found as $foundArr) { + $match = false; + + foreach ($criteria as $criteriaArr) { + if (isset($foundArr[$criteriaArr[0]]) && $foundArr[$criteriaArr[0]] === $criteriaArr[2]) { + $match = true; + } else { + $match = false; + } + } - if ($found) { - throw new IOException("Duplicate entry found for field: $uniqueField. $uniqueField should be unique. Store: " . $this->storeName); + if ($match) { + $duplicate = $foundArr['id']; + + break; + } + } + } + + if ($duplicate) { + throw new IOException("Duplicate entry with ID: $duplicate found for field: $uniqueField. $uniqueField should be unique. Store: " . $this->storeName); } } } @@ -1651,6 +1675,24 @@ protected function normalizeData(array $data, $jsonToArray = false): array } } + if ($type === 'string') { + if (is_integer($data[$propertyKey]) || is_float($data[$propertyKey])) { + $data[$propertyKey] = (string) $data[$propertyKey]; + } + + if (is_bool($data[$propertyKey])) { + if ($data[$propertyKey] === true || + $data[$propertyKey] === 1 + ) { + $data[$propertyKey] = 'true'; + } else if ($data[$propertyKey] === false || + $data[$propertyKey] === 0 + ) { + $data[$propertyKey] = 'false'; + } + } + } + if ($type === 'boolean') { if (is_string($data[$propertyKey])) { if ($data[$propertyKey] === 'false' || @@ -1810,10 +1852,22 @@ public function getIndexing() return $this->indexing; } - public function setIndexing($indexing = true) + public function setIndexing($indexing) { $this->indexing = $indexing; return $this->getIndexing(); } + + public function getReadIndex() + { + return $this->readIndex; + } + + public function setReadIndex($index) + { + $this->readIndex = $index; + + return $this->getReadIndex(); + } } \ No newline at end of file diff --git a/system/Base/Providers/ErrorServiceProvider/ExceptionHandlers.php b/system/Base/Providers/ErrorServiceProvider/ExceptionHandlers.php index 863c97aef..34de6611b 100644 --- a/system/Base/Providers/ErrorServiceProvider/ExceptionHandlers.php +++ b/system/Base/Providers/ErrorServiceProvider/ExceptionHandlers.php @@ -66,11 +66,14 @@ public function handleValidationException($exception) return $this->response->redirect($exception->getPath()); } - public function handleCsrfTokenException() + public function handleIncorrectCSRFException($exception) { - $this->flash->now('warning', 'Session expired, please login again.'); + if ($this->request->getBestAccept() === 'application/json') { + + $this->addResponse($exception->getMessage(), 1); - return $this->response->redirect('/auth/login'); + return $this->sendJson(); + } } public function handleInvalidDataException($exception) diff --git a/system/Base/Providers/ErrorServiceProvider/Exceptions/IncorrectCSRF.php b/system/Base/Providers/ErrorServiceProvider/Exceptions/IncorrectCSRFException.php similarity index 61% rename from system/Base/Providers/ErrorServiceProvider/Exceptions/IncorrectCSRF.php rename to system/Base/Providers/ErrorServiceProvider/Exceptions/IncorrectCSRFException.php index 6f1096b5f..8f47aae51 100644 --- a/system/Base/Providers/ErrorServiceProvider/Exceptions/IncorrectCSRF.php +++ b/system/Base/Providers/ErrorServiceProvider/Exceptions/IncorrectCSRFException.php @@ -2,7 +2,7 @@ namespace System\Base\Providers\ErrorServiceProvider\Exceptions; -class IncorrectCSRF extends \Exception +class IncorrectCSRFException extends \Exception { } \ No newline at end of file diff --git a/system/Base/Providers/ErrorServiceProvider/Exceptions/IncorrectRequestType.php b/system/Base/Providers/ErrorServiceProvider/Exceptions/IncorrectRequestTypeException.php similarity index 58% rename from system/Base/Providers/ErrorServiceProvider/Exceptions/IncorrectRequestType.php rename to system/Base/Providers/ErrorServiceProvider/Exceptions/IncorrectRequestTypeException.php index aa10910e7..62de6d8c3 100644 --- a/system/Base/Providers/ErrorServiceProvider/Exceptions/IncorrectRequestType.php +++ b/system/Base/Providers/ErrorServiceProvider/Exceptions/IncorrectRequestTypeException.php @@ -2,7 +2,7 @@ namespace System\Base\Providers\ErrorServiceProvider\Exceptions; -class IncorrectRequestType extends \Exception +class IncorrectRequestTypeException extends \Exception { } \ No newline at end of file diff --git a/system/Base/Providers/ModulesServiceProvider/DbInstaller.php b/system/Base/Providers/ModulesServiceProvider/DbInstaller.php index 1e71c31d4..b17c38174 100644 --- a/system/Base/Providers/ModulesServiceProvider/DbInstaller.php +++ b/system/Base/Providers/ModulesServiceProvider/DbInstaller.php @@ -123,7 +123,7 @@ public function installDb($databases) $config = $this->ff->generateConfig($tableName, $tableClass['schema'], $tableClass['model'], $tableConfigParams); $schema = $this->ff->generateSchema($tableName, $tableClass['schema'], $tableClass['model']); - $this->ff->store($tableName, $config, $schema, $this->ff); + $this->ff->store($tableName, $config, $schema); if (method_exists($tableClass['schema'], 'indexes')) { array_push($storesToIndex, $tableName); diff --git a/system/Base/Providers/ModulesServiceProvider/Modules/Packages.php b/system/Base/Providers/ModulesServiceProvider/Modules/Packages.php index e0a1fd965..260b8d04f 100644 --- a/system/Base/Providers/ModulesServiceProvider/Modules/Packages.php +++ b/system/Base/Providers/ModulesServiceProvider/Modules/Packages.php @@ -171,6 +171,17 @@ public function getPackageByName($name) return false; } + public function getPackageByClass($class) + { + foreach($this->packages as $package) { + if (strtolower($package['class']) === strtolower($class)) { + return $package; + } + } + + return false; + } + public function getPackagesForCategory($category) { $packages = []; diff --git a/system/Base/Providers/ModulesServiceProvider/TaskCallInstaller.php b/system/Base/Providers/ModulesServiceProvider/TaskCallInstaller.php new file mode 100644 index 000000000..e044d1dfe --- /dev/null +++ b/system/Base/Providers/ModulesServiceProvider/TaskCallInstaller.php @@ -0,0 +1,79 @@ +localContent->fileExists($packageFile)) { + $installPackageJsonFile = $this->helper->decode($this->localContent->read($packageFile), true); + + $package = $this->modules->packages->getPackageByClass($installPackageJsonFile['class']); + + if ($package) { + $packageFolder = 'apps/' . implode('/', array_slice(explode('\\', get_class($packageClass)), 1, -2)) . '/TaskCalls/'; + + $callsArr = $this->basepackages->utils->scanDir($packageFolder); + + if (count($callsArr['files']) > 0) { + foreach ($callsArr['files'] as $key => $call) { + $call = ucfirst($call); + $call = str_replace('/', '\\', $call); + $call = str_replace('.php', '', $call); + + $callClass = new $call; + $callReflection = new \ReflectionClass($call); + + $dbCall = $this->basepackages->workers->calls->getByCallName($callReflection->getShortName()); + + if (!$dbCall) { + $dbCall = []; + $dbCall['name'] = $callReflection->getShortName(); + $dbCall['display_name'] = $callReflection->getShortName(); + $dbCall['class'] = $callReflection->getName(); + if ($callReflection->hasProperty('funcDisplayName')) { + $dbCall['display_name'] = $callReflection->getProperty('funcDisplayName')->getValue($callClass); + } + $dbCall['description'] = ''; + if ($callReflection->hasProperty('funcDescription')) { + $dbCall['description'] = $callReflection->getProperty('funcDescription')->getValue($callClass); + } + $dbCall['can_be_scheduled'] = true; + if ($callReflection->hasProperty('funcCanBeScheduled')) { + $dbCall['can_be_scheduled'] = $callReflection->getProperty('funcCanBeScheduled')->getValue($callClass); + } + $dbCall['can_be_run_on_demand'] = true; + if ($callReflection->hasProperty('funcCanBeRunOnDemand')) { + $dbCall['can_be_run_on_demand'] = $callReflection->getProperty('funcCanBeRunOnDemand')->getValue($callClass); + } + $dbCall['package_id'] = $package['id']; + + $this->basepackages->workers->calls->addCall($dbCall); + } + } + } + } + } + } catch (FilesystemException | UnableToCheckExistence | UnableToReadFile | \throwable $e) { + throw $e; + } + + return true; + } + + public function uninstallTaskCall($packageClass) + { + //Check for running jobs + //Uninstall Task associated with the call + //Uninstall Call + } +} \ No newline at end of file diff --git a/system/Base/Providers/ModulesServiceProvider/WidgetInstaller.php b/system/Base/Providers/ModulesServiceProvider/WidgetInstaller.php new file mode 100644 index 000000000..d05e2d238 --- /dev/null +++ b/system/Base/Providers/ModulesServiceProvider/WidgetInstaller.php @@ -0,0 +1 @@ +//Will be used to install Component Widgets via modules \ No newline at end of file diff --git a/system/Base/Providers/SecurityServiceProvider/PasswordGenerator/Generator/ComputerPasswordGenerator.php b/system/Base/Providers/SecurityServiceProvider/PasswordGenerator/Generator/ComputerPasswordGenerator.php index 8a6147e8c..ac014e505 100644 --- a/system/Base/Providers/SecurityServiceProvider/PasswordGenerator/Generator/ComputerPasswordGenerator.php +++ b/system/Base/Providers/SecurityServiceProvider/PasswordGenerator/Generator/ComputerPasswordGenerator.php @@ -95,13 +95,19 @@ protected function getCharactersAsPer($option, $characters, $per, $enabledOption $count = $this->getMinimumCount($option); } else if ($per === 'maximum') { $max = $this->getMaximumCount($option); + $passwordLength = \strlen($this->password); - if (!$max) { + if ($max) { + if ($max < $this->getLength('minimum')) { + $max = $this->getLength('minimum'); + } + } else { $max = $this->getLength('minimum'); } $numbersOfCharsNeeded = $max - $passwordLength; + $count = ceil($numbersOfCharsNeeded/$enabledOptionsCount); if ($count <= 0) { @@ -124,15 +130,20 @@ protected function getCharactersAsPer($option, $characters, $per, $enabledOption public function generatePassword() { $this->password = $this->getCharacters('minimum'); + $passwordLength = \strlen($this->password); + $expectedPasswordLength = $this->getLength('minimum'); + if ($passwordLength < $expectedPasswordLength) { $this->password .= $this->getCharacters('maximum'); + $passwordLength = \strlen($this->password); } if ($passwordLength > $expectedPasswordLength) { $substrlength = $expectedPasswordLength - $passwordLength; + $this->password = substr($this->password, 0, $substrlength); }