Skip to content

Commit e114e1b

Browse files
committed
update comments, add getBoundCentralStoragePath()
we use FilesystemTenancyBootstrapper::getBoundCentralStoragePath() in LogTenancyBootstrapper to simplify the logic for extracting a path inside the central storage directory we could use this method in more places, such as DeleteTenantStorage: $centralStoragePath = tenancy()->central(fn () => storage_path()); $tenantStoragePath = tenancy()->run($this->tenant, fn () => storage_path()); however for consistency (we're getting both the central and tenant paths there) we're keeping it simple as it is now using the newly added method would also introduce more coupling to FilesystemTenancyBootstrapper - its specific implementation. this isn't a big issue in LogTenancyBootstrapper which already has several dependencies on the FS bootstrapper, and we do use app(static::class) in the added method so extending the bootstrapper should work
1 parent a6ce0e2 commit e114e1b

2 files changed

Lines changed: 28 additions & 16 deletions

File tree

src/Bootstrappers/FilesystemTenancyBootstrapper.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,4 +255,10 @@ public function scopeSessions(string|false $suffix): void
255255
$sessionManager->getDrivers()['file']->setHandler($handler);
256256
}
257257
}
258+
259+
/** Get the central storage path from the bound singleton instance of this class. */
260+
public static function getBoundCentralStoragePath(): string
261+
{
262+
return app(static::class)->originalStoragePath;
263+
}
258264
}

src/Bootstrappers/LogTenancyBootstrapper.php

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
* Laravel's 'single' and 'daily' channels by default. To customize it,
2222
* see the property's docblock.
2323
*
24-
* For this to work correctly:
24+
* For the storage path channels to be scoped correctly:
2525
* - this bootstrapper must run *after* FilesystemTenancyBootstrapper,
2626
* since FilesystemTenancyBootstrapper adjusts storage_path() for the tenant
2727
* - storage path suffixing has to be enabled (= config('tenancy.filesystem.suffix_storage_path')
@@ -38,10 +38,10 @@ class LogTenancyBootstrapper implements TenancyBootstrapper
3838
protected array $configuredChannels = [];
3939

4040
/**
41-
* Logging channels whose path is built using storage_path() (e.g. Laravel's single and daily).
41+
* Logging channels whose path is built using storage_path() (e.g. Laravel's 'single' and 'daily').
4242
*
4343
* Channels included here will be configured to use tenant-specific storage paths
44-
* generated using storage_path() in the tenant context. Overrides in the $channelOverrides
44+
* created using storage_path() in the tenant context. Overrides in the $channelOverrides
4545
* property take precedence over $storagePathChannels when a channel is included in both.
4646
*
4747
* Requires FilesystemTenancyBootstrapper to run before this bootstrapper,
@@ -63,9 +63,10 @@ class LogTenancyBootstrapper implements TenancyBootstrapper
6363
*
6464
* Examples:
6565
* - Array mapping: ['slack' => ['url' => 'webhookUrl']]
66-
* - this maps $tenant->webhookUrl to slack.url (if $tenant->webhookUrl is not null; otherwise the override is ignored)
66+
* - this maps $tenant->webhookUrl to slack.url (if $tenant->webhookUrl is null, the override is ignored)
6767
* - Closure: ['slack' => fn (Tenant $tenant, array $channel) => array_merge($channel, ['url' => $tenant->slackUrl])]
68-
* - this merges ['url' => $tenant->slackUrl] into the channel's config.
68+
* - this manually merges ['url' => $tenant->slackUrl] into the channel's config
69+
* - null is not ignored, the closure controls the override fully
6970
*
7071
* So the channel overrides can be arrays and closures that return arrays.
7172
*/
@@ -112,13 +113,13 @@ public function revert(): void
112113
* - any 'stack' channel that includes one of the above as a member
113114
*
114115
* Stack channels are included because once a stack has been used, it keeps logging
115-
* to wherever its members pointed at that moment. So a stack used in the central
116+
* to wherever its members pointed to at that moment. So a stack used in the central
116117
* context would keep writing to the central logs, even after tenancy is initialized
117118
* and its member channels are configured for the tenant.
118119
* Forgetting the stack forces it to be re-resolved with its members' updated (tenant)
119120
* config.
120121
*
121-
* Only stacks one level deep are handled.
122+
* Importantly, stacks are only inspected one level deep - they are not traversed recursively.
122123
*/
123124
protected function getChannels(): array
124125
{
@@ -145,9 +146,7 @@ protected function getChannels(): array
145146
/**
146147
* Configure channels for the tenant context.
147148
*
148-
* Only the channels that are in the $storagePathChannels array
149-
* or have custom overrides in the $channelOverrides property
150-
* will be configured (overrides take precedence over storage path channels).
149+
* This handles both $storagePathChannels and $channelOverrides.
151150
*/
152151
protected function configureChannels(array $channels, Tenant $tenant): void
153152
{
@@ -158,7 +157,7 @@ protected function configureChannels(array $channels, Tenant $tenant): void
158157
// Set storage path channels to use a tenant-specific directory.
159158
// The tenant log will be located at e.g. "storage/tenant{$tenantKey}/logs/laravel.log".
160159
$originalChannelPath = $this->config->get("logging.channels.{$channel}.path");
161-
$centralStoragePath = Str::before(storage_path(), $this->config->get('tenancy.filesystem.suffix_base') . $tenant->getTenantKey());
160+
$centralStoragePath = FilesystemTenancyBootstrapper::getBoundCentralStoragePath();
162161

163162
// The tenant log will inherit the segment that follows the storage path from the central channel path config.
164163
// For example, if a channel's path is configured to storage_path('logs/foo.log') (storage/logs/foo.log),
@@ -168,16 +167,24 @@ protected function configureChannels(array $channels, Tenant $tenant): void
168167
}
169168
}
170169

170+
/**
171+
* Update channel configurations per $channelOverrides.
172+
*
173+
* For overrides set in array format, update individual keys of the channel.
174+
* - This ignores cases where the value of the respective tenant attribute is null.
175+
* For overrides set as closures, replace the entire channel with the returned config override.
176+
* - This does not ignore cases where parts of the config may be null - the closure fully controls the override.
177+
*/
171178
protected function overrideChannelConfig(string $channel, array|Closure $override, Tenant $tenant): void
172179
{
173180
if (is_array($override)) {
174181
// Map tenant attributes to channel config keys.
175-
// If the tenant attribute is null,
176-
// the override is ignored and the channel config key's value remains unchanged.
177182
foreach ($override as $configKey => $tenantAttributeName) {
178183
/** @var Tenant&Model $tenant */
179184
$tenantAttribute = data_get($tenant, $tenantAttributeName);
180185

186+
// If the tenant attribute is null, the override is ignored
187+
// and the channel config key's value remains unchanged.
181188
if ($tenantAttribute !== null) {
182189
$this->config->set("logging.channels.{$channel}.{$configKey}", $tenantAttribute);
183190
}
@@ -196,9 +203,8 @@ protected function overrideChannelConfig(string $channel, array|Closure $overrid
196203
}
197204

198205
/**
199-
* Forget all passed channels from the log manager so that
200-
* they can be re-resolved with the updated (tenant-specific)
201-
* config on the next logging attempt.
206+
* Forget all passed channels from the log manager so that they can be
207+
* re-resolved with the updated config on the next logging attempt.
202208
*/
203209
protected function forgetChannels(array $channels): void
204210
{

0 commit comments

Comments
 (0)