2021-11-26 21:11:20 +01:00
|
|
|
<?php
|
|
|
|
|
|
2025-03-12 20:55:47 +01:00
|
|
|
/*
|
|
|
|
|
FusionPBX
|
|
|
|
|
Version: MPL 1.1
|
|
|
|
|
|
|
|
|
|
The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
|
1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
|
the License. You may obtain a copy of the License at
|
|
|
|
|
http://www.mozilla.org/MPL/
|
|
|
|
|
|
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
|
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
|
for the specific language governing rights and limitations under the
|
|
|
|
|
License.
|
|
|
|
|
|
|
|
|
|
The Original Code is FusionPBX
|
|
|
|
|
|
|
|
|
|
The Initial Developer of the Original Code is
|
|
|
|
|
Mark J Crane <markjcrane@fusionpbx.com>
|
|
|
|
|
Portions created by the Initial Developer are Copyright (C) 2008-2024
|
|
|
|
|
the Initial Developer. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
Contributor(s):
|
|
|
|
|
Mark J Crane <markjcrane@fusionpbx.com>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Auto Loader class
|
|
|
|
|
* Searches for project files when a class is required. Debugging mode can be set using:
|
|
|
|
|
* - export DEBUG=1
|
|
|
|
|
* OR
|
|
|
|
|
* - debug=true is appended to the url
|
|
|
|
|
*/
|
2021-11-26 21:11:20 +01:00
|
|
|
class auto_loader {
|
|
|
|
|
|
2025-03-15 16:13:36 +01:00
|
|
|
const CLASSES_KEY = 'autoloader_classes';
|
|
|
|
|
const CLASSES_FILE = 'autoloader_cache.php';
|
|
|
|
|
const INTERFACES_KEY = "autoloader_interfaces";
|
|
|
|
|
const INTERFACES_FILE = "autoloader_interface_cache.php";
|
2025-02-13 22:48:40 +01:00
|
|
|
|
|
|
|
|
private $classes;
|
|
|
|
|
|
2025-02-26 01:21:41 +01:00
|
|
|
/**
|
|
|
|
|
* Tracks the APCu extension for caching to RAM drive across requests
|
|
|
|
|
* @var bool
|
|
|
|
|
*/
|
|
|
|
|
private $apcu_enabled;
|
|
|
|
|
|
2025-03-12 20:55:47 +01:00
|
|
|
/**
|
2025-03-15 16:13:36 +01:00
|
|
|
* Cache path and file name for classes
|
2025-03-12 20:55:47 +01:00
|
|
|
* @var string
|
|
|
|
|
*/
|
2025-03-15 16:13:36 +01:00
|
|
|
private static $classes_file = null;
|
2025-03-12 20:55:47 +01:00
|
|
|
|
2025-03-15 16:13:36 +01:00
|
|
|
/**
|
|
|
|
|
* Maps interfaces to classes
|
|
|
|
|
* @var array
|
|
|
|
|
*/
|
|
|
|
|
private $interfaces;
|
|
|
|
|
|
2025-03-17 17:01:11 +01:00
|
|
|
/**
|
|
|
|
|
* @var array
|
|
|
|
|
*/
|
|
|
|
|
private $traits;
|
|
|
|
|
|
2025-03-15 16:13:36 +01:00
|
|
|
/**
|
|
|
|
|
* Cache path and file name for interfaces
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
|
|
|
|
private static $interfaces_file = null;
|
|
|
|
|
|
2025-03-17 17:01:11 +01:00
|
|
|
public function __construct($disable_cache = false) {
|
2025-02-26 01:21:41 +01:00
|
|
|
|
|
|
|
|
//set if we can use RAM cache
|
|
|
|
|
$this->apcu_enabled = function_exists('apcu_enabled') && apcu_enabled();
|
|
|
|
|
|
2025-03-17 17:01:11 +01:00
|
|
|
//set classes cache location
|
|
|
|
|
if (empty(self::$classes_file)) {
|
|
|
|
|
self::$classes_file = sys_get_temp_dir() . DIRECTORY_SEPARATOR . self::CLASSES_FILE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//set interface cache location
|
|
|
|
|
if (empty(self::$interfaces_file)) {
|
|
|
|
|
self::$interfaces_file = sys_get_temp_dir() . DIRECTORY_SEPARATOR . self::INTERFACES_FILE;
|
|
|
|
|
}
|
2025-03-12 20:55:47 +01:00
|
|
|
|
2025-02-13 22:48:40 +01:00
|
|
|
//classes must be loaded before this object is registered
|
2025-03-17 17:01:11 +01:00
|
|
|
if ($disable_cache || !$this->load_cache()) {
|
2025-02-15 18:44:46 +01:00
|
|
|
//cache miss so load them
|
2025-03-15 16:13:36 +01:00
|
|
|
$this->reload_classes();
|
2025-02-15 18:44:46 +01:00
|
|
|
//update the cache after loading classes array
|
|
|
|
|
$this->update_cache();
|
2025-02-13 22:48:40 +01:00
|
|
|
}
|
|
|
|
|
//register this object to load any unknown classes
|
2021-11-26 21:11:20 +01:00
|
|
|
spl_autoload_register(array($this, 'loader'));
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-17 17:01:11 +01:00
|
|
|
/**
|
|
|
|
|
* The loader is set to private because only the PHP engine should be calling this method
|
|
|
|
|
* @param string $class_name The class name that needs to be loaded
|
|
|
|
|
* @return bool True if the class is loaded or false when the class is not found
|
|
|
|
|
* @access private
|
|
|
|
|
*/
|
|
|
|
|
private function loader($class_name): bool {
|
|
|
|
|
|
|
|
|
|
//sanitize the class name
|
|
|
|
|
$class_name = preg_replace('[^a-zA-Z0-9_]', '', $class_name);
|
|
|
|
|
|
|
|
|
|
//find the path using the class_name as the key in the classes array
|
|
|
|
|
if (isset($this->classes[$class_name])) {
|
|
|
|
|
//include the class or interface
|
|
|
|
|
include_once $this->classes[$class_name];
|
|
|
|
|
|
|
|
|
|
//return boolean
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Smarty has it's own autoloader so reject the request
|
|
|
|
|
if ($class_name === 'Smarty_Autoloader') {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//cache miss
|
|
|
|
|
self::log(LOG_WARNING, "class '$class_name' not found in cache");
|
|
|
|
|
|
|
|
|
|
//set project path using magic dir constant
|
|
|
|
|
$project_path = dirname(__DIR__, 2);
|
|
|
|
|
|
|
|
|
|
//build the search path array
|
|
|
|
|
$search_path[] = glob($project_path . "/resources/interfaces/" . $class_name . ".php");
|
|
|
|
|
$search_path[] = glob($project_path . "/resources/traits/" . $class_name . ".php");
|
|
|
|
|
$search_path[] = glob($project_path . "/resources/classes/" . $class_name . ".php");
|
|
|
|
|
$search_path[] = glob($project_path . "/*/*/resources/interfaces/" . $class_name . ".php");
|
|
|
|
|
$search_path[] = glob($project_path . "/*/*/resources/traits/" . $class_name . ".php");
|
|
|
|
|
$search_path[] = glob($project_path . "/*/*/resources/classes/" . $class_name . ".php");
|
|
|
|
|
|
|
|
|
|
//collapse all entries to only the matched entry
|
|
|
|
|
$matches = array_filter($search_path);
|
|
|
|
|
if (!empty($matches)) {
|
|
|
|
|
$path = array_pop($matches)[0];
|
|
|
|
|
|
|
|
|
|
//include the class, interface, or trait
|
|
|
|
|
include_once $path;
|
|
|
|
|
|
|
|
|
|
//inject the class in to the array
|
|
|
|
|
$this->classes[$class_name] = $path;
|
|
|
|
|
|
|
|
|
|
//update the cache with new classes
|
|
|
|
|
$this->update_cache();
|
|
|
|
|
|
|
|
|
|
//return boolean
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//send to syslog when debugging
|
|
|
|
|
self::log(LOG_ERR, "class '$class_name' not found name");
|
|
|
|
|
|
|
|
|
|
//return boolean
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-15 16:13:36 +01:00
|
|
|
/**
|
|
|
|
|
* Update the auto loader
|
|
|
|
|
*/
|
|
|
|
|
public function update() {
|
2025-03-17 17:01:11 +01:00
|
|
|
self::clear_cache();
|
2025-03-15 16:13:36 +01:00
|
|
|
$this->reload_classes();
|
|
|
|
|
$this->update_cache();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function update_cache(): bool {
|
2025-02-26 01:21:41 +01:00
|
|
|
//guard against writing an empty file
|
2025-02-28 05:09:31 +01:00
|
|
|
if (empty($this->classes)) {
|
2025-02-26 01:21:41 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//update RAM cache when available
|
|
|
|
|
if ($this->apcu_enabled) {
|
2025-03-15 16:13:36 +01:00
|
|
|
$classes_cached = apcu_store(self::CLASSES_KEY, $this->classes);
|
|
|
|
|
$interfaces_cached = apcu_store(self::INTERFACES_KEY, $this->interfaces);
|
2025-03-12 20:55:47 +01:00
|
|
|
//do not save to drive when we are using apcu
|
2025-03-17 17:01:11 +01:00
|
|
|
if ($classes_cached && $interfaces_cached)
|
|
|
|
|
return true;
|
2025-02-26 01:21:41 +01:00
|
|
|
}
|
|
|
|
|
|
2025-03-15 16:13:36 +01:00
|
|
|
//export the classes array using PHP engine
|
|
|
|
|
$classes_array = var_export($this->classes, true);
|
|
|
|
|
|
|
|
|
|
//put the array in a form that it can be loaded directly to an array
|
|
|
|
|
$class_result = file_put_contents(self::$classes_file, "<?php\n return " . $classes_array . ";\n");
|
|
|
|
|
if ($class_result === false) {
|
|
|
|
|
//file failed to save - send error to syslog when debugging
|
|
|
|
|
$error_array = error_get_last();
|
|
|
|
|
self::log(LOG_WARNING, $error_array['message'] ?? '');
|
2024-03-21 17:33:05 +01:00
|
|
|
}
|
2025-02-13 22:48:40 +01:00
|
|
|
|
2025-03-15 16:13:36 +01:00
|
|
|
//export the interfaces array using PHP engine
|
|
|
|
|
$interfaces_array = var_export($this->interfaces, true);
|
2025-02-13 22:48:40 +01:00
|
|
|
|
2025-02-26 01:21:41 +01:00
|
|
|
//put the array in a form that it can be loaded directly to an array
|
2025-03-15 16:13:36 +01:00
|
|
|
$interface_result = file_put_contents(self::$interfaces_file, "<?php\n return " . $interfaces_array . ";\n");
|
|
|
|
|
if ($interface_result === false) {
|
|
|
|
|
//file failed to save - send error to syslog when debugging
|
|
|
|
|
$error_array = error_get_last();
|
|
|
|
|
self::log(LOG_WARNING, $error_array['message'] ?? '');
|
2024-03-21 17:33:05 +01:00
|
|
|
}
|
2025-03-12 20:55:47 +01:00
|
|
|
|
2025-03-15 16:13:36 +01:00
|
|
|
$result = ($class_result && $interface_result);
|
2025-02-26 01:21:41 +01:00
|
|
|
|
2025-03-15 16:13:36 +01:00
|
|
|
return $result;
|
2025-02-13 22:48:40 +01:00
|
|
|
}
|
|
|
|
|
|
2025-03-15 16:13:36 +01:00
|
|
|
public function load_cache(): bool {
|
2025-02-13 22:48:40 +01:00
|
|
|
$this->classes = [];
|
2025-03-15 16:13:36 +01:00
|
|
|
$this->interfaces = [];
|
2025-03-17 17:01:11 +01:00
|
|
|
$this->traits = [];
|
2025-02-26 01:21:41 +01:00
|
|
|
|
|
|
|
|
//use apcu when available
|
2025-03-15 16:13:36 +01:00
|
|
|
if ($this->apcu_enabled && apcu_exists(self::CLASSES_KEY)) {
|
|
|
|
|
$this->classes = apcu_fetch(self::CLASSES_KEY, $classes_cached);
|
|
|
|
|
$this->interfaces = apcu_fetch(self::INTERFACES_KEY, $interfaces_cached);
|
|
|
|
|
//don't use files when we are using apcu caching
|
2025-03-17 17:01:11 +01:00
|
|
|
if ($classes_cached && $interfaces_cached)
|
|
|
|
|
return true;
|
2025-02-26 01:21:41 +01:00
|
|
|
}
|
|
|
|
|
|
2025-03-15 16:13:36 +01:00
|
|
|
//use PHP engine to parse it
|
|
|
|
|
if (file_exists(self::$classes_file)) {
|
|
|
|
|
$this->classes = include self::$classes_file;
|
2025-02-13 22:48:40 +01:00
|
|
|
}
|
2025-03-12 20:55:47 +01:00
|
|
|
|
2025-03-15 16:13:36 +01:00
|
|
|
//do the same for interface to class mappings
|
|
|
|
|
if (file_exists(self::$interfaces_file)) {
|
|
|
|
|
$this->interfaces = include self::$interfaces_file;
|
2025-02-13 22:48:40 +01:00
|
|
|
}
|
2025-03-12 20:55:47 +01:00
|
|
|
|
|
|
|
|
//catch edge case of first time using apcu cache
|
|
|
|
|
if ($this->apcu_enabled) {
|
2025-03-15 16:13:36 +01:00
|
|
|
apcu_store(self::CLASSES_KEY, $this->classes);
|
|
|
|
|
apcu_store(self::INTERFACES_KEY, $this->interfaces);
|
2025-02-13 22:48:40 +01:00
|
|
|
}
|
2025-03-12 20:55:47 +01:00
|
|
|
|
|
|
|
|
//return true when we have classes and false if the array is still empty
|
2025-03-15 16:13:36 +01:00
|
|
|
return (!empty($this->classes) && !empty($this->interfaces));
|
2025-02-13 22:48:40 +01:00
|
|
|
}
|
|
|
|
|
|
2025-03-15 16:13:36 +01:00
|
|
|
public function reload_classes() {
|
2025-02-13 22:48:40 +01:00
|
|
|
//set project path using magic dir constant
|
2025-03-15 16:13:36 +01:00
|
|
|
$project_path = dirname(__DIR__, 2);
|
2025-02-13 22:48:40 +01:00
|
|
|
|
2025-03-12 20:55:47 +01:00
|
|
|
//build the array of all locations for classes in specific order
|
|
|
|
|
$search_path = [
|
|
|
|
|
$project_path . '/resources/interfaces/*.php',
|
|
|
|
|
$project_path . '/resources/traits/*.php',
|
|
|
|
|
$project_path . '/resources/classes/*.php',
|
|
|
|
|
$project_path . '/*/*/resources/interfaces/*.php',
|
|
|
|
|
$project_path . '/*/*/resources/traits/*.php',
|
|
|
|
|
$project_path . '/*/*/resources/classes/*.php',
|
|
|
|
|
$project_path . '/core/authentication/resources/classes/plugins/*.php',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
//get all php files for each path
|
|
|
|
|
$files = [];
|
|
|
|
|
foreach ($search_path as $path) {
|
|
|
|
|
$files = array_merge($files, glob($path));
|
|
|
|
|
}
|
2025-02-13 22:48:40 +01:00
|
|
|
|
|
|
|
|
//reset the current array
|
2025-03-15 16:13:36 +01:00
|
|
|
$class_list = [];
|
2025-02-13 22:48:40 +01:00
|
|
|
|
|
|
|
|
//store the class name (key) and the path (value)
|
2025-03-12 20:55:47 +01:00
|
|
|
foreach ($files as $file) {
|
2025-03-17 17:01:11 +01:00
|
|
|
$file_content = file_get_contents($file);
|
2025-03-12 20:55:47 +01:00
|
|
|
|
2025-03-17 17:01:11 +01:00
|
|
|
// Remove block comments
|
|
|
|
|
$file_content = preg_replace('/\/\*.*?\*\//s', '', $file_content);
|
|
|
|
|
// Remove single-line comments
|
|
|
|
|
$file_content = preg_replace('/(\/\/|#).*$/m', '', $file_content);
|
2025-03-12 20:55:47 +01:00
|
|
|
|
2025-03-17 17:01:11 +01:00
|
|
|
// Detect the namespace
|
|
|
|
|
$namespace = '';
|
|
|
|
|
if (preg_match('/\bnamespace\s+([^;{]+)[;{]/', $file_content, $namespace_match)) {
|
|
|
|
|
$namespace = trim($namespace_match[1]) . '\\';
|
2025-03-12 20:55:47 +01:00
|
|
|
}
|
2025-02-13 23:05:27 +01:00
|
|
|
|
2025-03-17 17:01:11 +01:00
|
|
|
// Regex to capture class, interface, or trait declarations
|
|
|
|
|
// It optionally captures an "implements" clause
|
|
|
|
|
// Note: This regex is a simplified version and may need adjustments for edge cases
|
|
|
|
|
$pattern = '/\b(class|interface|trait)\s+(\w+)(?:\s+extends\s+\w+)?(?:\s+implements\s+([^\\{]+))?/';
|
|
|
|
|
|
|
|
|
|
if (preg_match_all($pattern, $file_content, $matches, PREG_SET_ORDER)) {
|
|
|
|
|
foreach ($matches as $match) {
|
|
|
|
|
|
|
|
|
|
// "class", "interface", or "trait"
|
|
|
|
|
$type = $match[1];
|
|
|
|
|
|
|
|
|
|
// The class/interface/trait name
|
2025-03-26 20:11:37 +01:00
|
|
|
$name = trim($match[2]);
|
2025-03-17 17:01:11 +01:00
|
|
|
|
|
|
|
|
// Combine the namespace and name
|
|
|
|
|
$full_name = $namespace . $name;
|
|
|
|
|
|
|
|
|
|
// Store the class/interface/trait with its file overwriting any existing declaration.
|
|
|
|
|
$this->classes[$full_name] = $file;
|
|
|
|
|
|
|
|
|
|
// If it's a class that implements interfaces, process the implements clause.
|
|
|
|
|
if ($type === 'class' && isset($match[3]) && trim($match[3]) !== '') {
|
|
|
|
|
// Split the interface list by commas.
|
|
|
|
|
$interface_list = explode(',', $match[3]);
|
|
|
|
|
foreach ($interface_list as $interface) {
|
2025-03-26 20:11:37 +01:00
|
|
|
$interface_name = trim($interface);
|
2025-03-17 17:01:11 +01:00
|
|
|
// Check that it is declared as an array so we can record the classes
|
|
|
|
|
if (empty($this->interfaces[$interface_name]))
|
|
|
|
|
$this->interfaces[$interface_name] = [];
|
|
|
|
|
// Record the classes that implement interface sorting by namspace and class name
|
|
|
|
|
$this->interfaces[$interface_name][] = $full_name;
|
|
|
|
|
}
|
2025-03-15 16:13:36 +01:00
|
|
|
}
|
2025-03-17 17:01:11 +01:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// When the file is in the classes|interfaces|traits folder then
|
|
|
|
|
// we must assume it is a valid class as IonCube will encode the
|
|
|
|
|
// class name. So, we use the file name as the class name in the
|
|
|
|
|
// global namespace and set it, checking first to ensure the
|
|
|
|
|
// basename does not override an already declared class file in
|
|
|
|
|
// order to mimic previous behaviour.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
// use the basename as the class name
|
|
|
|
|
$class_name = basename($file, '.php');
|
|
|
|
|
if (!isset($this->classes[$class_name])) {
|
|
|
|
|
$this->classes[$class_name] = $file;
|
2025-03-15 16:13:36 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-12 20:55:47 +01:00
|
|
|
/**
|
|
|
|
|
* Returns a list of classes loaded by the auto_loader. If no classes have been loaded an empty array is returned.
|
|
|
|
|
* @return array List of classes loaded by the auto_loader or empty array
|
|
|
|
|
*/
|
|
|
|
|
public function get_class_list(): array {
|
|
|
|
|
if (!empty($this->classes)) {
|
|
|
|
|
return $this->classes;
|
2025-02-20 19:24:39 +01:00
|
|
|
}
|
2025-03-12 20:55:47 +01:00
|
|
|
return [];
|
2025-02-20 19:24:39 +01:00
|
|
|
}
|
2025-02-26 01:21:41 +01:00
|
|
|
|
2025-03-15 16:13:36 +01:00
|
|
|
/**
|
|
|
|
|
* Returns a list of classes implementing the interface
|
|
|
|
|
* @param string $interface_name
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
|
|
|
|
public function get_interface_list(string $interface_name): array {
|
|
|
|
|
//make sure we can return values
|
|
|
|
|
if (empty($this->classes) || empty($this->interfaces)) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
//check if we have an interface with that name
|
|
|
|
|
if (!empty($this->interfaces[$interface_name])) {
|
|
|
|
|
//return the list of classes associated with that interface
|
|
|
|
|
return $this->interfaces[$interface_name];
|
|
|
|
|
}
|
|
|
|
|
//interface is not implemented by any classes
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function get_interfaces(): array {
|
|
|
|
|
if (!empty($this->interfaces)) {
|
|
|
|
|
return $this->interfaces;
|
|
|
|
|
}
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-17 17:01:11 +01:00
|
|
|
public static function clear_cache() {
|
2025-03-12 20:55:47 +01:00
|
|
|
|
|
|
|
|
//check for apcu cache
|
2025-02-26 01:21:41 +01:00
|
|
|
if (function_exists('apcu_enabled') && apcu_enabled()) {
|
2025-03-15 16:13:36 +01:00
|
|
|
apcu_delete(self::CLASSES_KEY);
|
|
|
|
|
apcu_delete(self::INTERFACES_KEY);
|
2025-02-26 01:21:41 +01:00
|
|
|
}
|
2025-03-12 20:55:47 +01:00
|
|
|
|
|
|
|
|
//set default file
|
2025-03-15 16:13:36 +01:00
|
|
|
if (empty(self::$classes_file)) {
|
|
|
|
|
self::$classes_file = sys_get_temp_dir() . DIRECTORY_SEPARATOR . self::CLASSES_FILE;
|
2025-03-12 20:55:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//set file to clear
|
2025-03-17 17:01:11 +01:00
|
|
|
$classes_file = self::$classes_file;
|
2025-03-15 16:13:36 +01:00
|
|
|
|
|
|
|
|
//remove the file when it exists
|
|
|
|
|
if (file_exists($classes_file)) {
|
|
|
|
|
@unlink($classes_file);
|
|
|
|
|
$error_array = error_get_last();
|
|
|
|
|
//send to syslog when debugging with either environment variable or debug in the url
|
|
|
|
|
self::log(LOG_WARNING, $error_array['message'] ?? '');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (empty(self::$interfaces_file)) {
|
|
|
|
|
self::$interfaces_file = sys_get_temp_dir() . DIRECTORY_SEPARATOR . self::INTERFACES_FILE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//set interfaces file to clear
|
2025-03-17 17:01:11 +01:00
|
|
|
$interfaces_file = self::$interfaces_file;
|
2025-03-12 20:55:47 +01:00
|
|
|
|
|
|
|
|
//remove the file when it exists
|
2025-03-15 16:13:36 +01:00
|
|
|
if (file_exists($interfaces_file)) {
|
|
|
|
|
@unlink($interfaces_file);
|
2025-03-12 20:55:47 +01:00
|
|
|
$error_array = error_get_last();
|
|
|
|
|
//send to syslog when debugging with either environment variable or debug in the url
|
|
|
|
|
self::log(LOG_WARNING, $error_array['message'] ?? '');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static function log(int $level, string $message): void {
|
|
|
|
|
if (filter_var($_REQUEST['debug'] ?? false, FILTER_VALIDATE_BOOL) || filter_var(getenv('DEBUG') ?? false, FILTER_VALIDATE_BOOL)) {
|
|
|
|
|
openlog("PHP", LOG_PID | LOG_PERROR, LOG_LOCAL0);
|
|
|
|
|
syslog($level, "[auto_loader] " . $message);
|
|
|
|
|
closelog();
|
|
|
|
|
}
|
2025-02-26 01:21:41 +01:00
|
|
|
}
|
2021-11-26 21:11:20 +01:00
|
|
|
}
|