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