Skip to content

Commit 6bf9c26

Browse files
authored
chore: Merge pull request #271 from WebFiori/dev
Release-As: v3.0.0-beta.31
2 parents 3e82c23 + 3d719ea commit 6bf9c26

File tree

11 files changed

+191
-88
lines changed

11 files changed

+191
-88
lines changed

WebFiori/Framework/Access.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ public static function hasPrivilege(string $id, ?string $groupId = null): bool {
198198
* @param string $groupId The ID of the group. The ID must not contain
199199
* any of the following characters: ';','-',',' or a space. If the name contains
200200
* any of the given characters, the group will not be created.
201+
* @param string|null $parentGroupId Optional parent group ID for creating nested groups.
201202
*
202203
* @return bool If the group is created, the method will return true.
203204
* If not, the method will return false.
@@ -356,6 +357,14 @@ private function checkID(string $id, PrivilegesGroup $group): bool {
356357
return $bool;
357358
}
358359

360+
/**
361+
* Private helper that validates and creates a new privileges group.
362+
*
363+
* @param string $groupId The group ID to create.
364+
* @param string|null $parentGroupID Optional parent group ID for nested groups.
365+
*
366+
* @return bool True if group is created, false otherwise.
367+
*/
359368
private function createGroupHelper($groupId, ?string $parentGroupID = null): bool {
360369
$trimmedId = trim($groupId);
361370

@@ -715,6 +724,15 @@ private function isChildGroupHasPrivilege($prId, $groupId, $group): bool {
715724
return $retVal;
716725
}
717726

727+
/**
728+
* Private helper that validates an ID string.
729+
*
730+
* Checks that ID doesn't contain forbidden characters (';', ' ', '-', ',').
731+
*
732+
* @param string $id The ID string to validate.
733+
*
734+
* @return bool True if ID is valid, false otherwise.
735+
*/
718736
private function validateId($id): bool {
719737
$len = strlen($id);
720738

WebFiori/Framework/App.php

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,11 @@ public static function getConfig(): ConfigurationDriver {
271271
public static function getConfigDriver() : string {
272272
return self::$ConfigDriver;
273273
}
274+
/**
275+
* Calculates application root path by removing vendor framework path from current directory.
276+
*
277+
* @return string The application root path.
278+
*/
274279
private static function getRoot() {
275280
//Following lines of code assumes that the class exist on the folder:
276281
//\vendor\WebFiori\framework\WebFiori\Framework
@@ -367,7 +372,7 @@ public static function initiate(string $appFolder = 'App', string $publicFolder
367372
/**
368373
* Path to WebFiori's core library.
369374
*/
370-
define('WF_CORE_PATH', ROOT_PATH.DS.'vendor'.DS.'WebFiori'.DS.'framework'.DS.'WebFiori'.DS.'framework');
375+
define('WF_CORE_PATH', ROOT_PATH.DS.'vendor'.DS.'webfiori'.DS.'framework'.DS.'WebFiori'.DS.'Framework');
371376
}
372377
self::initAutoLoader();
373378
self::checkStandardLibs();
@@ -472,6 +477,11 @@ public static function start(): App {
472477

473478
return self::$LC;
474479
}
480+
/**
481+
* Helper for automatic class registration using reflection with configuration options.
482+
*
483+
* @param array $options Configuration array with dir, php-file, folder, class-name, params, callback, constructor-params.
484+
*/
475485
private static function autoRegisterHelper($options) {
476486
$dir = $options['dir'];
477487
$phpFile = $options['php-file'];
@@ -498,6 +508,11 @@ private static function autoRegisterHelper($options) {
498508
} catch (Error $ex) {
499509
}
500510
}
511+
/**
512+
* Safe function caller with CLI/web-aware exception handling.
513+
*
514+
* @param callable $func The function to call.
515+
*/
501516
private static function call($func) {
502517
try {
503518
call_user_func($func);
@@ -509,6 +524,9 @@ private static function call($func) {
509524
}
510525
}
511526
}
527+
/**
528+
* Validates and defines APP_DIR constant, checking for invalid characters.
529+
*/
512530
private function checkAppDir() {
513531

514532
if (!defined('APP_DIR')) {
@@ -616,6 +634,10 @@ private static function initAutoLoader() {
616634
*/
617635
if (!class_exists('WebFiori\Framework\Autoload\ClassLoader',false)) {
618636
$autoloader = WF_CORE_PATH.DIRECTORY_SEPARATOR.'Autoload'.DIRECTORY_SEPARATOR.'ClassLoader.php';
637+
638+
if (!file_exists($autoloader)) {
639+
throw new \Exception('Unable to locate the autoloader class.');
640+
}
619641
require_once $autoloader;
620642
}
621643
self::$AU = ClassLoader::get();
@@ -642,7 +664,7 @@ public static function initFrameworkVersionInfo() {
642664
*
643665
* @since 2.1
644666
*/
645-
define('WF_VERSION', '3.0.0-Beta.30');
667+
define('WF_VERSION', '3.0.0-beta.31');
646668
/**
647669
* A constant that tells the type of framework version.
648670
*
@@ -658,7 +680,7 @@ public static function initFrameworkVersionInfo() {
658680
*
659681
* @since 2.1
660682
*/
661-
define('WF_RELEASE_DATE', '2025-10-22');
683+
define('WF_RELEASE_DATE', '2025-10-28');
662684
}
663685

664686
/**
@@ -719,6 +741,9 @@ private function initScheduler() {
719741
TasksManager::registerTasks();
720742
}
721743
}
744+
/**
745+
* Defines THEMES_PATH constant pointing to the themes directory.
746+
*/
722747
private function initThemesPath() {
723748
if (!defined('THEMES_PATH')) {
724749
$themesDirName = 'Themes';

WebFiori/Framework/Autoload/ClassLoader.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ public function addClassMap(string $className, string $classWithNs, string $path
218218
* </li>
219219
* </ul>
220220
*
221+
* @param array $options Array of configuration options (define-root, search-folders, root, on-load-failure). *
221222
* @return ClassLoader
222223
*
223224
* @throws Exception
@@ -560,6 +561,12 @@ private function addSearchDirectory(string $dir, $incSubFolders = true, $appendR
560561
}
561562
}
562563
}
564+
/**
565+
* Private helper that recursively processes directories using a stack-based approach.
566+
*
567+
* @param string $cleanDir The directory path to process.
568+
* @param bool $appendRoot Whether to append root path to directory.
569+
*/
563570
private function addSearchDirectoryHelper($cleanDir, $appendRoot) {
564571
$dirsStack = [$cleanDir];
565572
$root = $this->getRoot();
@@ -576,6 +583,16 @@ private function addSearchDirectoryHelper($cleanDir, $appendRoot) {
576583
}
577584
}
578585
}
586+
/**
587+
* Private helper that scans subdirectories and adds them to the processing stack.
588+
*
589+
* @param string $xDir The current directory being processed.
590+
* @param string $fullPath The full path to the directory.
591+
* @param array $dirsStack The stack of directories to process.
592+
* @param bool $appendRoot Whether to append root path.
593+
*
594+
* @return array Updated directories stack.
595+
*/
579596
private function addSearchDirectoryHelper2($xDir, $fullPath, $dirsStack, $appendRoot) {
580597
$subDirs = scandir($fullPath);
581598

@@ -590,6 +607,12 @@ private function addSearchDirectoryHelper2($xDir, $fullPath, $dirsStack, $append
590607

591608
return $dirsStack;
592609
}
610+
/**
611+
* Private helper that attempts to create the cache directory if it doesn't exist.
612+
*
613+
* @param string $autoloadCachePath The path where cache should be created.
614+
* @param mixed $autoloadCache The cache data.
615+
*/
593616
private function attemptCreateCache($autoloadCachePath, $autoloadCache) {
594617
if (!file_exists($autoloadCachePath)) {
595618
mkdir($autoloadCachePath, 0777, true);

WebFiori/Framework/Cli/Commands/WHelpCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class WHelpCommand extends HelpCommand {
2020
public function exec() : int {
2121
$argV = $this->getOwner()->getArgsVector();
2222

23-
if (count($argV) == 0) {
23+
if (count(array_diff($argV, ['--ansi'])) == 0) {
2424
$this->printLogo();
2525
}
2626
$formattingOptions = [

WebFiori/Framework/Ini.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ class Ini {
3434
*
3535
*/
3636
private static $singleton;
37+
/**
38+
* Private constructor that initializes documentation formatting properties.
39+
*/
3740
private function __construct() {
3841
$this->docStart = '/**';
3942
$this->docEnd = ' **/';
@@ -57,11 +60,12 @@ public static function createAppDirs() {
5760
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Langs');
5861
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Apis');
5962
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Config');
60-
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto');
61-
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'.$DS.'uploads');
62-
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'.$DS.'logs');
63-
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'.$DS.'sessions');
63+
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Storage');
64+
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Storage'.$DS.'Uploads');
65+
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Storage'.$DS.'Logs');
66+
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Storage'.$DS.'Sessions');
6467
self::mkdir(ROOT_PATH.$DS.'public');
68+
self::mkdir(ROOT_PATH.$DS.'tests');
6569
}
6670

6771

@@ -151,6 +155,13 @@ public static function get(): Ini {
151155

152156
return self::$singleton;
153157
}
158+
/**
159+
* Attempts to create a directory if it does not exist.
160+
*
161+
* If directory creation fails, code execution stops and outputs JSON with error details.
162+
*
163+
* @param string $dir The directory path to create.
164+
*/
154165
public static function mkdir($dir) {
155166
self::$DIR_TO_CREATE = $dir;
156167
if (!is_dir($dir)) {

WebFiori/Framework/PrivilegesGroup.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,11 @@ private function hasPrivilegeHelper(PrivilegesGroup $group, Privilege $p) {
406406
return $hasPr;
407407
}
408408

409+
/**
410+
* Private helper that removes a child group by ID from the current group's children array.
411+
*
412+
* @param string $gId The ID of the child group to remove.
413+
*/
409414
private function removeChildGroupHelper($gId) {
410415
for ($x = 0 ; $x < count($this->childGroups()) ; $x++) {
411416
$xG = $this->childGroups[$x];

WebFiori/Framework/Scheduler/AbstractTask.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,11 @@ public function setTaskName(string $name) : bool {
10371037

10381038
return false;
10391039
}
1040+
/**
1041+
* Converts task to JSON with all task properties and time information.
1042+
*
1043+
* @return Json JSON object containing task data.
1044+
*/
10401045
public function toJSON() : Json {
10411046
$json = new Json([
10421047
'name' => $this->getTaskName(),
@@ -1330,6 +1335,13 @@ private function checkMonthHelper(string $monthField) {
13301335

13311336
return $monthAttrs;
13321337
}
1338+
/**
1339+
* Creates standard time attributes structure for scheduling.
1340+
*
1341+
* @param string $suffix The suffix for attribute names (e.g., 'hour', 'minute').
1342+
*
1343+
* @return array Standard attributes array with every, every-x, at-every-x, and at-range keys.
1344+
*/
13331345
private function createAttrs($suffix): array {
13341346
return [
13351347
// *
@@ -1388,6 +1400,13 @@ private function dayOfMonthHelper(string $dayOfMonthField) {
13881400
return $monthDaysAttrs;
13891401
}
13901402

1403+
/**
1404+
* Gets argument value from HTTP request parameters.
1405+
*
1406+
* @param string $name The argument name to retrieve.
1407+
*
1408+
* @return mixed|null The argument value or null if not found.
1409+
*/
13911410
private function getArgValFromRequest($name) {
13921411
if (Runner::isCLI()) {
13931412
return null;
@@ -1401,6 +1420,13 @@ private function getArgValFromRequest($name) {
14011420

14021421
return $retVal;
14031422
}
1423+
/**
1424+
* Gets argument value from CLI command.
1425+
*
1426+
* @param string $name The argument name to retrieve.
1427+
*
1428+
* @return mixed|null The argument value or null if not found.
1429+
*/
14041430
private function getArgValFromTerminal($name) {
14051431
$c = $this->getCommand();
14061432

@@ -1454,6 +1480,14 @@ private function getSubExprType(string $expr): string {
14541480

14551481
return $retVal;
14561482
}
1483+
/**
1484+
* Checks if current hour matches scheduling rules (exact or interval-based).
1485+
*
1486+
* @param array $hoursArr Array containing hour scheduling configuration.
1487+
* @param int $current The current hour to check.
1488+
*
1489+
* @return bool True if hour matches scheduling rules.
1490+
*/
14571491
private function isHourHelper($hoursArr, $current) {
14581492
$hours = $hoursArr['at-every-x-hour'];
14591493
$retVal = in_array($current, $hours);
@@ -1471,6 +1505,14 @@ private function isHourHelper($hoursArr, $current) {
14711505

14721506
return $retVal;
14731507
}
1508+
/**
1509+
* Checks if current minute matches scheduling rules (exact or interval-based).
1510+
*
1511+
* @param array $minuteArr Array containing minute scheduling configuration.
1512+
* @param int $current The current minute to check.
1513+
*
1514+
* @return bool True if minute matches scheduling rules.
1515+
*/
14741516
private function isMinuteHelper($minuteArr, $current) {
14751517
$minutes = $minuteArr['at-every-x-minute'];
14761518
$retVal = in_array($current, $minutes);

WebFiori/Framework/Scheduler/TasksManager.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,11 @@ public static function getMonth() : int {
350350
public static function getPassword() : string {
351351
return self::get()->getPasswordHelper();
352352
}
353+
/**
354+
* Returns all scheduled tasks as an array from the tasks queue.
355+
*
356+
* @return array Array of all scheduled tasks.
357+
*/
353358
public static function getTasks() : array {
354359
return self::get()->tasksQueue()->toArray();
355360
}
@@ -491,6 +496,12 @@ public static function initRoutes() {
491496
*
492497
* @since 1.0.8
493498
*/
499+
/**
500+
* Logs messages with optional CLI display formatting based on type.
501+
*
502+
* @param string $message The message to log.
503+
* @param string $type The message type (success, error, info, none).
504+
*/
494505
public static function log(string $message, string $type = 'none') {
495506
self::get()->logsArray[] = $message;
496507

@@ -896,6 +907,13 @@ private function getQueueHelper(): Queue {
896907
private function isLogEnabledHelper(): bool {
897908
return $this->isLogEnabled;
898909
}
910+
/**
911+
* Helper that writes task execution details to log file.
912+
*
913+
* @param bool $forced Whether the task was forced to execute.
914+
* @param AbstractTask $task The task that was executed.
915+
* @param File $file The log file to write to.
916+
*/
899917
private function logExecHelper($forced, $task, File $file) {
900918
if ($forced) {
901919
$file->setRawData('Task \''.$task->getTaskName().'\' was forced to executed at '.date(DATE_RFC1123).". Request source IP: ".Util::getClientIP()."\n");
@@ -911,6 +929,12 @@ private function logExecHelper($forced, $task, File $file) {
911929
$file->write();
912930
}
913931

932+
/**
933+
* Handles task execution logging by creating log file and calling helper.
934+
*
935+
* @param AbstractTask $task The task that was executed.
936+
* @param bool $forced Whether the task was forced to execute.
937+
*/
914938
private function logTaskExecution($task,$forced = false) {
915939
if ($this->isLogEnabled) {
916940
$logsPath = ROOT_PATH.DS.APP_DIR.DS.'sto'.DS.'logs';

0 commit comments

Comments
 (0)