Working state snapshot with debug settings and pending changes
Fix manifest helper delegator missing return statements 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
11
.env.dist
11
.env.dist
@@ -5,6 +5,7 @@ APP_DEBUG=true
|
|||||||
APP_URL=http://localhost
|
APP_URL=http://localhost
|
||||||
|
|
||||||
# RSX Application Mode: development, debug, or production
|
# RSX Application Mode: development, debug, or production
|
||||||
|
RSX_MODE=development
|
||||||
|
|
||||||
LOG_CHANNEL=stack
|
LOG_CHANNEL=stack
|
||||||
LOG_DEPRECATIONS_CHANNEL=null
|
LOG_DEPRECATIONS_CHANNEL=null
|
||||||
@@ -40,10 +41,15 @@ MAIL_FROM_NAME="${APP_NAME}"
|
|||||||
|
|
||||||
# Debug Settings
|
# Debug Settings
|
||||||
# SHOW_CONSOLE_DEBUG_CLI: Enable console_debug() output in CLI mode
|
# SHOW_CONSOLE_DEBUG_CLI: Enable console_debug() output in CLI mode
|
||||||
SHOW_CONSOLE_DEBUG_CLI=false
|
SHOW_CONSOLE_DEBUG_CLI=true
|
||||||
|
|
||||||
# SHOW_CONSOLE_DEBUG_HTTP: Enable console_debug() output in HTTP mode (browser console)
|
# SHOW_CONSOLE_DEBUG_HTTP: Enable console_debug() output in HTTP mode (browser console)
|
||||||
SHOW_CONSOLE_DEBUG_HTTP=false
|
SHOW_CONSOLE_DEBUG_HTTP=true
|
||||||
|
|
||||||
|
# Console Debug Configuration
|
||||||
|
CONSOLE_DEBUG_ENABLED=false
|
||||||
|
CONSOLE_DEBUG_FILTER_MODE=all
|
||||||
|
CONSOLE_DEBUG_BENCHMARK=true
|
||||||
|
|
||||||
# FORCE_REBUILD_EVERY_REQUEST: Clear build cache on each request (development only)
|
# FORCE_REBUILD_EVERY_REQUEST: Clear build cache on each request (development only)
|
||||||
|
|
||||||
@@ -56,4 +62,3 @@ GATEKEEPER_SUBTITLE="This is a restricted development preview site. Please enter
|
|||||||
SSR_FPC_ENABLED=true
|
SSR_FPC_ENABLED=true
|
||||||
LOG_BROWSER_ERRORS=false
|
LOG_BROWSER_ERRORS=false
|
||||||
AJAX_DISABLE_BATCHING=false
|
AJAX_DISABLE_BATCHING=false
|
||||||
RSX_MODE=development
|
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -59,3 +59,6 @@ __pycache__
|
|||||||
docs.dev/*/node_modules/
|
docs.dev/*/node_modules/
|
||||||
docs.dev/ace_reference/vendor/
|
docs.dev/ace_reference/vendor/
|
||||||
.rspade_last_commit_for_publish
|
.rspade_last_commit_for_publish
|
||||||
|
|
||||||
|
# VS Code workspace file (user-specific)
|
||||||
|
rspade.code-workspace
|
||||||
|
|||||||
146
app/RSpade/CodeQuality/Rules/Scss/DataSidSelector_CodeQualityRule.php
Executable file
146
app/RSpade/CodeQuality/Rules/Scss/DataSidSelector_CodeQualityRule.php
Executable file
@@ -0,0 +1,146 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\RSpade\CodeQuality\Rules\Scss;
|
||||||
|
|
||||||
|
use App\RSpade\CodeQuality\Rules\CodeQualityRule_Abstract;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DataSidSelectorRule - Prohibits targeting [data-sid] in SCSS/CSS selectors
|
||||||
|
*
|
||||||
|
* PHILOSOPHY: $sid attributes are internal implementation details of jqhtml components.
|
||||||
|
* They exist for programmatic DOM access via this.$sid('name'), not for styling.
|
||||||
|
* Styling should use semantic BEM child classes instead.
|
||||||
|
*/
|
||||||
|
class DataSidSelector_CodeQualityRule extends CodeQualityRule_Abstract
|
||||||
|
{
|
||||||
|
public function get_id(): string
|
||||||
|
{
|
||||||
|
return 'SCSS-SID-01';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_name(): string
|
||||||
|
{
|
||||||
|
return 'No data-sid CSS Selectors';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_description(): string
|
||||||
|
{
|
||||||
|
return 'Prohibits targeting [data-sid] attributes in CSS selectors. Use BEM child classes instead.';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_file_patterns(): array
|
||||||
|
{
|
||||||
|
return ['*.scss', '*.css'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_default_severity(): string
|
||||||
|
{
|
||||||
|
return 'critical';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run at manifest-time for immediate feedback
|
||||||
|
*/
|
||||||
|
public function is_called_during_manifest_scan(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check SCSS/CSS files for [data-sid] selectors
|
||||||
|
*/
|
||||||
|
public function check(string $file_path, string $contents, array $metadata = []): void
|
||||||
|
{
|
||||||
|
// Skip vendor and node_modules
|
||||||
|
if (str_contains($file_path, '/vendor/') || str_contains($file_path, '/node_modules/')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip minified files
|
||||||
|
if (str_ends_with($file_path, '.min.css') || str_ends_with($file_path, '.min.scss')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$lines = explode("\n", $contents);
|
||||||
|
|
||||||
|
foreach ($lines as $line_num => $line) {
|
||||||
|
$actual_line_number = $line_num + 1;
|
||||||
|
$trimmed = trim($line);
|
||||||
|
|
||||||
|
// Skip comments
|
||||||
|
if (str_starts_with($trimmed, '//') || str_starts_with($trimmed, '/*')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for exception comment on same line or previous line
|
||||||
|
if (str_contains($line, '@' . $this->get_id() . '-EXCEPTION')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($line_num > 0 && str_contains($lines[$line_num - 1], '@' . $this->get_id() . '-EXCEPTION')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for [data-sid= pattern (with or without quotes)
|
||||||
|
if (preg_match('/\[data-sid\s*[=~\|\^\$\*]/', $line, $matches)) {
|
||||||
|
// Extract the selector context for better error message
|
||||||
|
$code_snippet = trim($line);
|
||||||
|
if (strlen($code_snippet) > 80) {
|
||||||
|
$code_snippet = substr($code_snippet, 0, 77) . '...';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to extract the sid name for the suggestion
|
||||||
|
$sid_name = '';
|
||||||
|
if (preg_match('/\[data-sid\s*=\s*["\']?([^"\'\]]+)/', $line, $sid_match)) {
|
||||||
|
$sid_name = $sid_match[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
$suggestion = $this->get_suggestion($sid_name);
|
||||||
|
|
||||||
|
$this->add_violation(
|
||||||
|
$file_path,
|
||||||
|
$actual_line_number,
|
||||||
|
"Targeting [data-sid] in CSS is PROHIBITED",
|
||||||
|
$code_snippet,
|
||||||
|
$suggestion,
|
||||||
|
'critical'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the fix suggestion with example
|
||||||
|
*/
|
||||||
|
private function get_suggestion(string $sid_name): string
|
||||||
|
{
|
||||||
|
$example_class = $sid_name ? "__$sid_name" : '__element_name';
|
||||||
|
|
||||||
|
return <<<SUGGESTION
|
||||||
|
\$sid attributes are internal implementation details of jqhtml components.
|
||||||
|
They exist for programmatic DOM access (this.\$sid('name')), NOT for styling.
|
||||||
|
|
||||||
|
WHY THIS IS WRONG:
|
||||||
|
- \$sid is an internal identifier, not a semantic class name
|
||||||
|
- Component internals may change without notice
|
||||||
|
- Breaks encapsulation - styles reach into component implementation
|
||||||
|
|
||||||
|
SOLUTION: Use BEM child classes instead.
|
||||||
|
|
||||||
|
Before (WRONG):
|
||||||
|
[data-sid="$sid_name"] {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
After (CORRECT):
|
||||||
|
&$example_class {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
Then in the jqhtml template, add the class to the element:
|
||||||
|
<button \$sid="$sid_name" class="Component_Name$example_class">
|
||||||
|
|
||||||
|
BEM child classes are semantic, documented, and part of the component's public API.
|
||||||
|
\$sid attributes are internal implementation that should never leak into CSS.
|
||||||
|
SUGGESTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -535,7 +535,8 @@ class BundleCompiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle class name includes (could be Asset Bundles with CDN assets)
|
// Handle class name includes (could be Asset Bundles with CDN assets)
|
||||||
if (is_string($include) && Manifest::php_find_class($include)) {
|
// Check manifest data directly since php_find_class throws if not found
|
||||||
|
if (is_string($include) && isset(Manifest::$data['data']['php_classes'][$include])) {
|
||||||
if (Manifest::php_is_subclass_of($include, 'Rsx_Asset_Bundle_Abstract')) {
|
if (Manifest::php_is_subclass_of($include, 'Rsx_Asset_Bundle_Abstract')) {
|
||||||
$asset_def = $include::define();
|
$asset_def = $include::define();
|
||||||
if (!empty($asset_def['cdn_assets'])) {
|
if (!empty($asset_def['cdn_assets'])) {
|
||||||
|
|||||||
@@ -189,9 +189,9 @@ class Manifest
|
|||||||
|
|
||||||
public static $_manifest_compile_lock;
|
public static $_manifest_compile_lock;
|
||||||
|
|
||||||
public static $_get_rsx_files_cache;
|
public static $_get_rsx_files_cache = null;
|
||||||
|
|
||||||
public static bool $_has_changed_cache;
|
public static array $_has_changed_cache = [];
|
||||||
|
|
||||||
public static bool $_has_manifest_ready = false;
|
public static bool $_has_manifest_ready = false;
|
||||||
|
|
||||||
@@ -1209,7 +1209,7 @@ class Manifest
|
|||||||
// move to lower soon
|
// move to lower soon
|
||||||
public static function _validate_cached_data()
|
public static function _validate_cached_data()
|
||||||
{
|
{
|
||||||
_Manifest_Cache_Helper::_validate_cached_data();
|
return _Manifest_Cache_Helper::_validate_cached_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1258,7 +1258,7 @@ class Manifest
|
|||||||
*/
|
*/
|
||||||
public static function _collate_files_by_classes()
|
public static function _collate_files_by_classes()
|
||||||
{
|
{
|
||||||
_Manifest_Builder_Helper::_collate_files_by_classes();
|
return _Manifest_Builder_Helper::_collate_files_by_classes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1281,7 +1281,7 @@ class Manifest
|
|||||||
*/
|
*/
|
||||||
public static function _build_event_handler_index()
|
public static function _build_event_handler_index()
|
||||||
{
|
{
|
||||||
_Manifest_Builder_Helper::_build_event_handler_index();
|
return _Manifest_Builder_Helper::_build_event_handler_index();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1295,7 +1295,7 @@ class Manifest
|
|||||||
*/
|
*/
|
||||||
public static function _build_classless_php_files_index()
|
public static function _build_classless_php_files_index()
|
||||||
{
|
{
|
||||||
_Manifest_Builder_Helper::_build_classless_php_files_index();
|
return _Manifest_Builder_Helper::_build_classless_php_files_index();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -153,8 +153,6 @@ class _Manifest_Cache_Helper
|
|||||||
// If cache exists, check if anything changed
|
// If cache exists, check if anything changed
|
||||||
$files = Manifest::_get_rsx_files();
|
$files = Manifest::_get_rsx_files();
|
||||||
|
|
||||||
$any_changes = false;
|
|
||||||
|
|
||||||
// Check for changed files
|
// Check for changed files
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
if (Manifest::_has_changed($file)) {
|
if (Manifest::_has_changed($file)) {
|
||||||
@@ -163,7 +161,6 @@ class _Manifest_Cache_Helper
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check for deleted files
|
// Check for deleted files
|
||||||
if (!$any_changes) {
|
|
||||||
$existing_files = array_flip($files);
|
$existing_files = array_flip($files);
|
||||||
|
|
||||||
foreach (array_keys(Manifest::$data['data']['files']) as $cached_file) {
|
foreach (array_keys(Manifest::$data['data']['files']) as $cached_file) {
|
||||||
@@ -173,15 +170,14 @@ class _Manifest_Cache_Helper
|
|||||||
}
|
}
|
||||||
if (!isset($existing_files[$cached_file])) {
|
if (!isset($existing_files[$cached_file])) {
|
||||||
// Only show the message once per page load
|
// Only show the message once per page load
|
||||||
if (!self::$__shown_rescan_message) {
|
if (!Manifest::$__shown_rescan_message) {
|
||||||
console_debug('MANIFEST', '* Deleted file ' . $cached_file . ' is triggering manifest rescan *');
|
console_debug('MANIFEST', '* Deleted file ' . $cached_file . ' is triggering manifest rescan *');
|
||||||
self::$__shown_rescan_message = true;
|
Manifest::$__shown_rescan_message = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,17 +16,15 @@ use App\RSpade\Core\Manifest\Manifest;
|
|||||||
*/
|
*/
|
||||||
class _Manifest_Scanner_Helper
|
class _Manifest_Scanner_Helper
|
||||||
{
|
{
|
||||||
protected static $_get_rsx_files_cache;
|
// Static properties are defined on Manifest class and accessed via Manifest::$property
|
||||||
protected static $_has_changed_cache = [];
|
|
||||||
protected static $__shown_rescan_message = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all files in configured scan directories (returns relative paths)
|
* Get all files in configured scan directories (returns relative paths)
|
||||||
*/
|
*/
|
||||||
public static function _get_rsx_files(): array
|
public static function _get_rsx_files(): array
|
||||||
{
|
{
|
||||||
if (!empty(self::$_get_rsx_files_cache)) {
|
if (!empty(Manifest::$_get_rsx_files_cache)) {
|
||||||
return self::$_get_rsx_files_cache;
|
return Manifest::$_get_rsx_files_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
$base_path = base_path();
|
$base_path = base_path();
|
||||||
@@ -128,7 +126,7 @@ class _Manifest_Scanner_Helper
|
|||||||
$files = array_unique($files);
|
$files = array_unique($files);
|
||||||
sort($files);
|
sort($files);
|
||||||
|
|
||||||
self::$_get_rsx_files_cache = $files;
|
Manifest::$_get_rsx_files_cache = $files;
|
||||||
|
|
||||||
return $files;
|
return $files;
|
||||||
}
|
}
|
||||||
@@ -138,17 +136,17 @@ class _Manifest_Scanner_Helper
|
|||||||
*/
|
*/
|
||||||
public static function _has_changed(string $file): bool
|
public static function _has_changed(string $file): bool
|
||||||
{
|
{
|
||||||
if (isset(self::$_has_changed_cache[$file])) {
|
if (isset(Manifest::$_has_changed_cache[$file])) {
|
||||||
return self::$_has_changed_cache[$file];
|
return Manifest::$_has_changed_cache[$file];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset(Manifest::$data['data']['files'][$file])) {
|
if (!isset(Manifest::$data['data']['files'][$file])) {
|
||||||
// Only show the message once per page load
|
// Only show the message once per page load
|
||||||
if (!self::$__shown_rescan_message) {
|
if (!Manifest::$__shown_rescan_message) {
|
||||||
console_debug('MANIFEST', '* New file ' . $file . ' is triggering manifest rescan *');
|
console_debug('MANIFEST', '* New file ' . $file . ' is triggering manifest rescan *');
|
||||||
self::$__shown_rescan_message = true;
|
Manifest::$__shown_rescan_message = true;
|
||||||
}
|
}
|
||||||
$_has_changed_cache[$file] = true;
|
Manifest::$_has_changed_cache[$file] = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -159,11 +157,11 @@ class _Manifest_Scanner_Helper
|
|||||||
// Make sure file exists
|
// Make sure file exists
|
||||||
if (!file_exists($absolute_path)) {
|
if (!file_exists($absolute_path)) {
|
||||||
// Only show the message once per page load
|
// Only show the message once per page load
|
||||||
if (!self::$__shown_rescan_message) {
|
if (!Manifest::$__shown_rescan_message) {
|
||||||
console_debug('MANIFEST', '* File ' . $file . ' appears to be deleted in ' . $absolute_path . ', triggering manifest rescan *');
|
console_debug('MANIFEST', '* File ' . $file . ' appears to be deleted in ' . $absolute_path . ', triggering manifest rescan *');
|
||||||
self::$__shown_rescan_message = true;
|
Manifest::$__shown_rescan_message = true;
|
||||||
}
|
}
|
||||||
$_has_changed_cache[$file] = true;
|
Manifest::$_has_changed_cache[$file] = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -173,11 +171,11 @@ class _Manifest_Scanner_Helper
|
|||||||
// Stage 1: Size check
|
// Stage 1: Size check
|
||||||
if ($old['size'] != $current_size) {
|
if ($old['size'] != $current_size) {
|
||||||
// Only show the message once per page load
|
// Only show the message once per page load
|
||||||
if (!self::$__shown_rescan_message) {
|
if (!Manifest::$__shown_rescan_message) {
|
||||||
console_debug('MANIFEST', '* File ' . $file . ' has changed size, triggering manifest rescan *');
|
console_debug('MANIFEST', '* File ' . $file . ' has changed size, triggering manifest rescan *');
|
||||||
self::$__shown_rescan_message = true;
|
Manifest::$__shown_rescan_message = true;
|
||||||
}
|
}
|
||||||
$_has_changed_cache[$file] = true;
|
Manifest::$_has_changed_cache[$file] = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -186,16 +184,16 @@ class _Manifest_Scanner_Helper
|
|||||||
$current_mtime = filemtime($absolute_path);
|
$current_mtime = filemtime($absolute_path);
|
||||||
if ($old['mtime'] != $current_mtime) {
|
if ($old['mtime'] != $current_mtime) {
|
||||||
// Only show the message once per page load
|
// Only show the message once per page load
|
||||||
if (!self::$__shown_rescan_message) {
|
if (!Manifest::$__shown_rescan_message) {
|
||||||
console_debug('MANIFEST', '* File ' . $file . ' has changed mtime, triggering manifest rescan *');
|
console_debug('MANIFEST', '* File ' . $file . ' has changed mtime, triggering manifest rescan *');
|
||||||
self::$__shown_rescan_message = true;
|
Manifest::$__shown_rescan_message = true;
|
||||||
}
|
}
|
||||||
$_has_changed_cache[$file] = true;
|
Manifest::$_has_changed_cache[$file] = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$_has_changed_cache[$file] = false;
|
Manifest::$_has_changed_cache[$file] = false;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ class Rsx_Framework_Provider extends ServiceProvider
|
|||||||
*/
|
*/
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
|
// Sanity check: .env symlink configuration
|
||||||
|
// The system/.env must be a symlink to ../.env for proper configuration sharing
|
||||||
|
$this->check_env_symlink();
|
||||||
|
|
||||||
// Merge framework config defaults
|
// Merge framework config defaults
|
||||||
$package_config = base_path('config/rsx.php');
|
$package_config = base_path('config/rsx.php');
|
||||||
$this->mergeConfigFrom($package_config, 'rsx');
|
$this->mergeConfigFrom($package_config, 'rsx');
|
||||||
@@ -506,4 +510,74 @@ class Rsx_Framework_Provider extends ServiceProvider
|
|||||||
|
|
||||||
rmdir($dir);
|
rmdir($dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that .env is properly symlinked
|
||||||
|
*
|
||||||
|
* The system/.env file must be a symlink to ../.env for proper configuration sharing.
|
||||||
|
* This ensures both the project root and Laravel see the same .env file.
|
||||||
|
*/
|
||||||
|
private function check_env_symlink(): void
|
||||||
|
{
|
||||||
|
// Only check if we're in the standard /var/www/html/system location
|
||||||
|
if (base_path() !== '/var/www/html/system') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$project_env = '/var/www/html/.env';
|
||||||
|
$system_env = '/var/www/html/system/.env';
|
||||||
|
|
||||||
|
// Both files must exist for this check to apply
|
||||||
|
if (!file_exists($project_env) || !file_exists($system_env)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// system/.env must be a symlink
|
||||||
|
if (!is_link($system_env)) {
|
||||||
|
$this->fatal_env_symlink_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The symlink must point to ../.env (relative path)
|
||||||
|
$link_target = readlink($system_env);
|
||||||
|
if ($link_target !== '../.env') {
|
||||||
|
$this->fatal_env_symlink_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display fatal error for .env symlink misconfiguration
|
||||||
|
*/
|
||||||
|
private function fatal_env_symlink_error(): void
|
||||||
|
{
|
||||||
|
$message = <<<'ERROR'
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
FATAL ERROR: .env Symlink Misconfiguration
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
The file /var/www/html/system/.env must be a symlink to ../.env
|
||||||
|
|
||||||
|
This ensures both the project root and the Laravel framework share the same
|
||||||
|
environment configuration. Without this symlink, configuration changes in one
|
||||||
|
location won't be reflected in the other.
|
||||||
|
|
||||||
|
TO FIX THIS ISSUE:
|
||||||
|
|
||||||
|
cd /var/www/html/system
|
||||||
|
rm .env
|
||||||
|
ln -s ../.env .env
|
||||||
|
|
||||||
|
After creating the symlink, your .env setup should look like:
|
||||||
|
|
||||||
|
/var/www/html/.env (the actual .env file)
|
||||||
|
/var/www/html/system/.env -> ../.env (symlink)
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
|
||||||
|
ERROR;
|
||||||
|
|
||||||
|
// Use echo + die for maximum visibility (before any error handlers are set up)
|
||||||
|
echo $message;
|
||||||
|
die(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user