Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions WebFiori/Framework/Access.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ public static function hasPrivilege(string $id, ?string $groupId = null): bool {
* @param string $groupId The ID of the group. The ID must not contain
* any of the following characters: ';','-',',' or a space. If the name contains
* any of the given characters, the group will not be created.
* @param string|null $parentGroupId Optional parent group ID for creating nested groups.
*
* @return bool If the group is created, the method will return true.
* If not, the method will return false.
Expand Down Expand Up @@ -356,6 +357,14 @@ private function checkID(string $id, PrivilegesGroup $group): bool {
return $bool;
}

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

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

/**
* Private helper that validates an ID string.
*
* Checks that ID doesn't contain forbidden characters (';', ' ', '-', ',').
*
* @param string $id The ID string to validate.
*
* @return bool True if ID is valid, false otherwise.
*/
private function validateId($id): bool {
$len = strlen($id);

Expand Down
31 changes: 28 additions & 3 deletions WebFiori/Framework/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ public static function getConfig(): ConfigurationDriver {
public static function getConfigDriver() : string {
return self::$ConfigDriver;
}
/**
* Calculates application root path by removing vendor framework path from current directory.
*
* @return string The application root path.
*/
private static function getRoot() {
//Following lines of code assumes that the class exist on the folder:
//\vendor\WebFiori\framework\WebFiori\Framework
Expand Down Expand Up @@ -367,7 +372,7 @@ public static function initiate(string $appFolder = 'App', string $publicFolder
/**
* Path to WebFiori's core library.
*/
define('WF_CORE_PATH', ROOT_PATH.DS.'vendor'.DS.'WebFiori'.DS.'framework'.DS.'WebFiori'.DS.'framework');
define('WF_CORE_PATH', ROOT_PATH.DS.'vendor'.DS.'webfiori'.DS.'framework'.DS.'WebFiori'.DS.'Framework');
}
self::initAutoLoader();
self::checkStandardLibs();
Expand Down Expand Up @@ -472,6 +477,11 @@ public static function start(): App {

return self::$LC;
}
/**
* Helper for automatic class registration using reflection with configuration options.
*
* @param array $options Configuration array with dir, php-file, folder, class-name, params, callback, constructor-params.
*/
private static function autoRegisterHelper($options) {
$dir = $options['dir'];
$phpFile = $options['php-file'];
Expand All @@ -498,6 +508,11 @@ private static function autoRegisterHelper($options) {
} catch (Error $ex) {
}
}
/**
* Safe function caller with CLI/web-aware exception handling.
*
* @param callable $func The function to call.
*/
private static function call($func) {
try {
call_user_func($func);
Expand All @@ -509,6 +524,9 @@ private static function call($func) {
}
}
}
/**
* Validates and defines APP_DIR constant, checking for invalid characters.
*/
private function checkAppDir() {

if (!defined('APP_DIR')) {
Expand Down Expand Up @@ -616,6 +634,10 @@ private static function initAutoLoader() {
*/
if (!class_exists('WebFiori\Framework\Autoload\ClassLoader',false)) {
$autoloader = WF_CORE_PATH.DIRECTORY_SEPARATOR.'Autoload'.DIRECTORY_SEPARATOR.'ClassLoader.php';

if (!file_exists($autoloader)) {
throw new \Exception('Unable to locate the autoloader class.');
}
require_once $autoloader;
}
self::$AU = ClassLoader::get();
Expand All @@ -642,7 +664,7 @@ public static function initFrameworkVersionInfo() {
*
* @since 2.1
*/
define('WF_VERSION', '3.0.0-Beta.30');
define('WF_VERSION', '3.0.0-beta.31');
/**
* A constant that tells the type of framework version.
*
Expand All @@ -658,7 +680,7 @@ public static function initFrameworkVersionInfo() {
*
* @since 2.1
*/
define('WF_RELEASE_DATE', '2025-10-22');
define('WF_RELEASE_DATE', '2025-10-28');
}

/**
Expand Down Expand Up @@ -719,6 +741,9 @@ private function initScheduler() {
TasksManager::registerTasks();
}
}
/**
* Defines THEMES_PATH constant pointing to the themes directory.
*/
private function initThemesPath() {
if (!defined('THEMES_PATH')) {
$themesDirName = 'Themes';
Expand Down
23 changes: 23 additions & 0 deletions WebFiori/Framework/Autoload/ClassLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ public function addClassMap(string $className, string $classWithNs, string $path
* </li>
* </ul>
*
* @param array $options Array of configuration options (define-root, search-folders, root, on-load-failure). *
* @return ClassLoader
*
* @throws Exception
Expand Down Expand Up @@ -560,6 +561,12 @@ private function addSearchDirectory(string $dir, $incSubFolders = true, $appendR
}
}
}
/**
* Private helper that recursively processes directories using a stack-based approach.
*
* @param string $cleanDir The directory path to process.
* @param bool $appendRoot Whether to append root path to directory.
*/
private function addSearchDirectoryHelper($cleanDir, $appendRoot) {
$dirsStack = [$cleanDir];
$root = $this->getRoot();
Expand All @@ -576,6 +583,16 @@ private function addSearchDirectoryHelper($cleanDir, $appendRoot) {
}
}
}
/**
* Private helper that scans subdirectories and adds them to the processing stack.
*
* @param string $xDir The current directory being processed.
* @param string $fullPath The full path to the directory.
* @param array $dirsStack The stack of directories to process.
* @param bool $appendRoot Whether to append root path.
*
* @return array Updated directories stack.
*/
private function addSearchDirectoryHelper2($xDir, $fullPath, $dirsStack, $appendRoot) {
$subDirs = scandir($fullPath);

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

return $dirsStack;
}
/**
* Private helper that attempts to create the cache directory if it doesn't exist.
*
* @param string $autoloadCachePath The path where cache should be created.
* @param mixed $autoloadCache The cache data.
*/
private function attemptCreateCache($autoloadCachePath, $autoloadCache) {
if (!file_exists($autoloadCachePath)) {
mkdir($autoloadCachePath, 0777, true);
Expand Down
2 changes: 1 addition & 1 deletion WebFiori/Framework/Cli/Commands/WHelpCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class WHelpCommand extends HelpCommand {
public function exec() : int {
$argV = $this->getOwner()->getArgsVector();

if (count($argV) == 0) {
if (count(array_diff($argV, ['--ansi'])) == 0) {
$this->printLogo();
}
$formattingOptions = [
Expand Down
19 changes: 15 additions & 4 deletions WebFiori/Framework/Ini.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class Ini {
*
*/
private static $singleton;
/**
* Private constructor that initializes documentation formatting properties.
*/
private function __construct() {
$this->docStart = '/**';
$this->docEnd = ' **/';
Expand All @@ -57,11 +60,12 @@ public static function createAppDirs() {
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Langs');
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Apis');
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Config');
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto');
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'.$DS.'uploads');
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'.$DS.'logs');
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'sto'.$DS.'sessions');
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Storage');
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Storage'.$DS.'Uploads');
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Storage'.$DS.'Logs');
self::mkdir(ROOT_PATH.$DS.APP_DIR.$DS.'Storage'.$DS.'Sessions');
self::mkdir(ROOT_PATH.$DS.'public');
self::mkdir(ROOT_PATH.$DS.'tests');
}


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

return self::$singleton;
}
/**
* Attempts to create a directory if it does not exist.
*
* If directory creation fails, code execution stops and outputs JSON with error details.
*
* @param string $dir The directory path to create.
*/
public static function mkdir($dir) {
self::$DIR_TO_CREATE = $dir;
if (!is_dir($dir)) {
Expand Down
5 changes: 5 additions & 0 deletions WebFiori/Framework/PrivilegesGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,11 @@ private function hasPrivilegeHelper(PrivilegesGroup $group, Privilege $p) {
return $hasPr;
}

/**
* Private helper that removes a child group by ID from the current group's children array.
*
* @param string $gId The ID of the child group to remove.
*/
private function removeChildGroupHelper($gId) {
for ($x = 0 ; $x < count($this->childGroups()) ; $x++) {
$xG = $this->childGroups[$x];
Expand Down
42 changes: 42 additions & 0 deletions WebFiori/Framework/Scheduler/AbstractTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,11 @@ public function setTaskName(string $name) : bool {

return false;
}
/**
* Converts task to JSON with all task properties and time information.
*
* @return Json JSON object containing task data.
*/
public function toJSON() : Json {
$json = new Json([
'name' => $this->getTaskName(),
Expand Down Expand Up @@ -1330,6 +1335,13 @@ private function checkMonthHelper(string $monthField) {

return $monthAttrs;
}
/**
* Creates standard time attributes structure for scheduling.
*
* @param string $suffix The suffix for attribute names (e.g., 'hour', 'minute').
*
* @return array Standard attributes array with every, every-x, at-every-x, and at-range keys.
*/
private function createAttrs($suffix): array {
return [
// *
Expand Down Expand Up @@ -1388,6 +1400,13 @@ private function dayOfMonthHelper(string $dayOfMonthField) {
return $monthDaysAttrs;
}

/**
* Gets argument value from HTTP request parameters.
*
* @param string $name The argument name to retrieve.
*
* @return mixed|null The argument value or null if not found.
*/
private function getArgValFromRequest($name) {
if (Runner::isCLI()) {
return null;
Expand All @@ -1401,6 +1420,13 @@ private function getArgValFromRequest($name) {

return $retVal;
}
/**
* Gets argument value from CLI command.
*
* @param string $name The argument name to retrieve.
*
* @return mixed|null The argument value or null if not found.
*/
private function getArgValFromTerminal($name) {
$c = $this->getCommand();

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

return $retVal;
}
/**
* Checks if current hour matches scheduling rules (exact or interval-based).
*
* @param array $hoursArr Array containing hour scheduling configuration.
* @param int $current The current hour to check.
*
* @return bool True if hour matches scheduling rules.
*/
private function isHourHelper($hoursArr, $current) {
$hours = $hoursArr['at-every-x-hour'];
$retVal = in_array($current, $hours);
Expand All @@ -1471,6 +1505,14 @@ private function isHourHelper($hoursArr, $current) {

return $retVal;
}
/**
* Checks if current minute matches scheduling rules (exact or interval-based).
*
* @param array $minuteArr Array containing minute scheduling configuration.
* @param int $current The current minute to check.
*
* @return bool True if minute matches scheduling rules.
*/
private function isMinuteHelper($minuteArr, $current) {
$minutes = $minuteArr['at-every-x-minute'];
$retVal = in_array($current, $minutes);
Expand Down
24 changes: 24 additions & 0 deletions WebFiori/Framework/Scheduler/TasksManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,11 @@ public static function getMonth() : int {
public static function getPassword() : string {
return self::get()->getPasswordHelper();
}
/**
* Returns all scheduled tasks as an array from the tasks queue.
*
* @return array Array of all scheduled tasks.
*/
public static function getTasks() : array {
return self::get()->tasksQueue()->toArray();
}
Expand Down Expand Up @@ -491,6 +496,12 @@ public static function initRoutes() {
*
* @since 1.0.8
*/
/**
* Logs messages with optional CLI display formatting based on type.
*
* @param string $message The message to log.
* @param string $type The message type (success, error, info, none).
*/
public static function log(string $message, string $type = 'none') {
self::get()->logsArray[] = $message;

Expand Down Expand Up @@ -896,6 +907,13 @@ private function getQueueHelper(): Queue {
private function isLogEnabledHelper(): bool {
return $this->isLogEnabled;
}
/**
* Helper that writes task execution details to log file.
*
* @param bool $forced Whether the task was forced to execute.
* @param AbstractTask $task The task that was executed.
* @param File $file The log file to write to.
*/
private function logExecHelper($forced, $task, File $file) {
if ($forced) {
$file->setRawData('Task \''.$task->getTaskName().'\' was forced to executed at '.date(DATE_RFC1123).". Request source IP: ".Util::getClientIP()."\n");
Expand All @@ -911,6 +929,12 @@ private function logExecHelper($forced, $task, File $file) {
$file->write();
}

/**
* Handles task execution logging by creating log file and calling helper.
*
* @param AbstractTask $task The task that was executed.
* @param bool $forced Whether the task was forced to execute.
*/
private function logTaskExecution($task,$forced = false) {
if ($this->isLogEnabled) {
$logsPath = ROOT_PATH.DS.APP_DIR.DS.'sto'.DS.'logs';
Expand Down
Loading
Loading