Also, use parameterAllowlist() instead of the static property (so that we can e.g. override it later in SQLiteDatabaseManager, since overriding the static property doesn't work).
DB manager methods validate the parameters they use in SQL statements using validateParameter() (excluding parameters passed via bindings in SELECT statements).
At the moment, `where()` cannot be used correctly while using
`withoutPending()`. For example, if we have a single non-pending tenant
in our DB (with ID 'foo'), queries like
`Tenant::withoutPending()->where('id', 'nonexistent')->first()`will
incorrectly return the non-pending tenant ('foo').
This is because `withoutPending()` does
`$builder->whereNull('data->pending_since')->orWhereNull('data')`. These
two aren't grouped, so `withoutPending()->where('id', 'nonexistent')`
basically translates to "WHERE data->pending_since IS NULL **OR (data IS
NULL AND id = 'nonexistent')**". So the query will include all tenants
whose `pending_since` is null (= all non-pending tenants).
Grouping `->whereNull('data->pending_since')->orWhereNull('data')` in a
closure passed to a separate `where()` fixes this issue.
phpstan started failing with '... implements generic interface
Illuminate\Database\Eloquent\Scope but does not specify its types:
TModel'. We solve this by adding an implements docblock to the scopes
implementing that interface. They're fairly generic - we just use the
Model type itself in the code - so we use Model for the type parameter.
- Update ci.yml and composer.json
- Wrap single database tenancy trait scopes in whenBooted()
- Update SessionSeparationTest to use laravel-cache- prefix in L13
and laravel_cache_ in <=L12. Our own prefix remains tenant_%tenant%_
(as configured in tenancy.cache.prefix). We could update this to be
tenant-%tenant%- from now on for consistency with Laravel's prefixes
(changed in https://github.com/laravel/framework/pull/56172) but I'm
not sure yet. _ seems to read a bit better but perhaps consistency
is more important. We may change this later and it can be adjusted
in userland easily (since it's just a config option).
This pull request adds improved PHPDoc type annotations to several
Eloquent relationship methods, enhancing static analysis and developer
experience. These changes clarify the expected return types for
relationships, making the codebase easier to understand and work with.
Relationship method type annotations:
* Added a detailed return type annotation to the `tenant` method in the
`BelongsToTenant` trait, specifying the related model and the current
class.
* Added a detailed return type annotation to the `domains` method in the
`HasDomains` trait, specifying the related model and the current class.
* Added a detailed return type annotation to the `tenants` method in the
`ResourceSyncing` class, specifying the related model and the current
class.
This method lets the user specify default values for custom
non-nullable columns. The primary use case is when the tenants table
has a column like 'slug' and createPending() is called with no
value for 'slug'. This would produce an exception due to the column
having no default value.
Here, getPendingAttributes() can set an initial dummy slug (like a
randomly generated string) before it's overwritten during a pull.
getPendingAttributes() accepts an $attributes array which corresponds
to the attributes passed to createPending(). The array returned from
getPendingAttributes() is ultimately merged with $attributes, so
the user doesn't need to use the $attributes value in
getPendingAttributes(), however it serves to provide more context when
the pending attributes might be dependent on $attributes and therefore
derived from the $attributes actually being used.
Also fixed the `finally` branch in createPending() as it was
potentially referencing the $tenant variable before it was initialized.
Notable changes:
- CreateUserWithRLSPolicies: Clarify why we're creating a custom
DatabaseConfing instance
- HasDatabase: Clarify why we're ignoring tenancy_db_connection
- DatabaseConfig: General refactor, clarify the role of the host conn
- SQLiteDatabaseManager: Handle trailing DIRECTORY_SEPARATOR
in static::$path
- DisallowSqliteAttach: Don't throw any exceptions, just silently fail
since the class isn't 100% portable
- Clean up todos that are no longer relevant
- Clean up dead code or comments in some database managers
- [BC BREAK] Make pullPendingFromPool() $firstOrCreate arg
default to false (pullPending() is now a direct alias for
pullPendingFromPool() with default $firstOrCreate=true)
- Resolve race conditions in pullPendingFromPool()
- Make createPending() set pending_since regardless of exceptions
- Make pullPending() accept $attributes
- Fire PullingPendingTenant from within a DB transaction
- Clarify --count arg description for CreatePendingTenants command
- Add docblock to PullingPendingTenant with a notice
* cleanup, resolve todos, add immediate todos
* Improve path_identification_middleware docblock
* rename leave() method in tests
* wip fix hardcoded values making assumptions about the parameters used in routing
* defaultParameterNames
* fix CreatesDatabaseUsers return values
* $tenant -> tenant()
* resolve more todos
* make comment block a complete block
* Correct useTenantRoutesInFortify(), delete unused import
* test fixes
* remove todos
* remove JobPipeline todo
* simplify comment example
* remove todo
* fix VERSION_PREFIX in queue.yml
---------
Co-authored-by: lukinovec <lukinovec@gmail.com>
* Add option to update attributes of pending tenants while pulling them
* Fix failing toEqualCanonicalizing tests
* Fix code style (php-cs-fixer)
* fix code errors
* lock phpcsfixer to 3.62.0 due to a bug in 3.63.1
---------
Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
Co-authored-by: Samuel Štancl <samuel@archte.ch>
* resolver refactor
* Fix code style (php-cs-fixer)
* make tenant column used in PathTenantResolver configurable, fix phpstan errors, minor improvements
* support binding route fields, write tests for customizable tenant columns
* Invalidate cache for all possible columns in path resolver
* implement proper cache separation logic for different columns used by PathTenantResolver
* improve return type
---------
Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
* Add &Model to docblock
* Fix code style (php-cs-fixer)
* Only delete synced resource if the central resource shouldSync
* Add central resource detached event and listener
* Add SyncedTenant interface
* Use the event & listener in the test file
* Add getGlobalIdentifierKey(Name) to TenantMorphPivot
* Refactor TriggerSyncingEvents
* Fix code style (php-cs-fixer)
* Test queueing the detaching listener
* Move finding the central resource into the event, naming changes
* Fix code style (php-cs-fixer)
* Simplify listener code
* Refactor detaching logic
* Create tenant resource after attaching central to tenant, test queueing related listener
* Delete dd()
* Fix code style (php-cs-fixer)
* Move triggerAttachEvent from SyncMaster
* Update attach event-related code
* Move findResource from SyncedTenant to the pivot trait
* Add annotation
* Update annotation
* Simplify getAttributesForCreation in CreateTenantResourceFromSyncMaster
* Update naming
* Add tenant trait for attaching/detaching resources
* Update test names
* Move creation attribute parsing method to trait
* Rename variable
* Fix code style (php-cs-fixer)
* Delete complete to-do
* Delete event comment
* Rename event property
* Find tenant resource in detach listener
* Use global ID key of tenant resource in cascade deletes listener
* Use global ID key name of the central resource while creating/deleting tenant resources
* Add getSyncedCreationAttributes example in the annotation
* Fix inconsistencies in SyncedTenant methods
* Improve annotation
* Don't return the query in `$scopeGetModelQuery`
Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>
* Fix code style (php-cs-fixer)
* Update scoping getModel query
* Only use detach event instead of using both detach and delete events, refactor code
* Test that detaching tenant from a central resource doesn't affect other tenants
* Delete extra imports
* Fix code style (php-cs-fixer)
* Add PivotWithRelation, test attaching/detaching resources without polymorphic relations
* Refactor TriggerSyncingEvents to work with non-polymorphic relations too
* Fix code style (php-cs-fixer)
* Rename synced resource changed event, fix tests
* Enforce passing Tenant&Model to attach/detach events
* Prevent firing saved event automatically in CreateTenantResource
* Improve TriggerSyncingEvents trait
* Delete unused import
* Make TriggerSyncingEvents methods non-static, improve annotations
* Pass saved model to event
* Move attach/detach queueing tests to ResourceSyncingTest, pass models instead of IDs to attach/detach
* Move events to ResourceSyncing\Events
* Fix code style (php-cs-fixer)
* Use SerializesModels in queueable listeners instead of events
* Delete redundant $shouldQueue setting
* Rename listener, test cascade deletes from both sides of many-to-many
* Move creation attributes-related code to a separate test file, improve comments (wip)
* Improve comments, fix variable name capitalization
* Delete tracing comma
* Extract duplicate code into a trait
* Don't accept nullable tenant in SyncMasterDeleted
* Fix annotation
* Fix code style (php-cs-fixer)
* Update annotation
* Fix PHPStan error
* Fix annotation
* Update comments and test naming
* Move triggerDeleteEvent to CascadeDeletes interface
* Rename test file
* Import TenantPivot in Tenant class (tests/Etc)
* Add central resource not available in pivot exception
* Rename SaveSyncedResource to UpdateOrCreateSyncedResource
* Add new events and listeners to TSP stub
* Improve comments and naming
* Only keep SerializesModels in classes that utilize it
* Use tenant->run()
* Import events in stub
* Move RS listeners to separate namespace, use `Event/`Listener/` in stub for consistency
* Fix code style (php-cs-fixer)
* Fix namespace changes
* Use cursor instead of get
* Update src/ResourceSyncing/ParsesCreationAttributes.php
Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>
* Update naming, structure (discussed on Discord)
* Update uses in in test file
* remove double ;;
* Add comments
* Test if static properties work fine with queueable listeners
* Update $shouldQuery test
* Update creation attributes
* Work on updating the tests
* Make synced attributes configurable using static properties
* Update resource syncing tests
* Get rid of mixed attribute classes
* Get rid of TenantUserWIthCreationAttributes
* Fix imports
* Get rid of the conditionally synced classes, improve tests
* Simplify resource creation tests (only test the more complex cases instead of each case - if the complex case works, the simpler cases work too)
* Clean up ResourceSyncingTest (mostly duplicate tests that were already in AutomaticResourceCreationTest)
* Simplify class naming in polymorhpic tests
* Move automatic resource creation tests to ResourceSyncingTest
* Test that the sync event doesn't get triggered excessively
* Only trigger the sync event if the synced attributes were changed or if the resource was recently created
* Update synced attribute instead of unsynced in test
* Fix sync event test
* Update static property redefining test
* Use getGlobalIdentifierKeyName() instead of hardcoding the key name
* Delete static properties from the ResourceSyncing trait
* Reuse user classes in polymorphic tests
* Update tests/ResourceSyncingTest.php
Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>
* Use the default tenants() method in central user, override the default in ResourceSyncingTest
* Use BelongsToMany as tenants() return type
* Fix code style (php-cs-fixer)
* Delete extra static property from trait
* Delete duplicate events/listeners from TSP stub
* Delete weird expectation, use $model->trashed()
* Change ResourceUser to TenantUser
* Add defaults for getGlobalIdentifierKey(Name)
* Use singular tenant in DeleteResourceInTenants name
* Rename getSyncedCreationAttributes to getCreationAttributes
* Fix comma position in comment
* minor fixes in traits and interfaces
* Fix code style (php-cs-fixer)
* Correct comment
* Use $tenant->run()
* Update scopeGetModelQuery annotation
* Use static property for testing shouldSync
* Improve test
* Get rid of datasets
* Add trashed assertions
* Always merge synced attributes with the creation attributes during parsing
* Update creation attributes in test's beforeEach
* Use only the necessary creation attributes (no need to include the synced attributes because they get merged automatically)
* Rename ResourceTenant to MorphTenant
* Add TriggerSyncingEvents docblock
Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>
* Add force deletes test
* Fix code style (php-cs-fixer)
* Delete pivot if it can't access the resource class
* Make parseCreationAttributes more readable
* Comment out setting $scopeGetModelQuery in the stub
* Add @var annotations to bootTriggerSyncingEvents
* Fix attach()/detach() exception test
* Interrupt creation of broken pivots instead of deleting the pivots at a later point
* Add more comments
* Update CreateTenantResource comment
* Assert that forceDelete() doesn't affect other tenant resources
* Rename test
* Correct with() array formatting
* Expand test with soft deletes
* Merge SyncedResourceSaved tests
* Improve naming, comments and minor details in the assertions
* Move test
* Fix failing test
* Delete duplicate test
* Minor test improvement
* Delete duplicate test
* Improve old test
* Minor test improvement
* Improve event test
* Improve tests (naming, code, comments)
* Delete extra test, add comments to the larger test
* Refactor central -> tenant attach() test
* Apply changes from central -> tenant attach() test on tenant -> central test
* Fix assertions in central -> tenant
* Correct comment and assertion
* Refactor tenant -> central attach() test
* Fix inconsistency
* Delete unused import
* Add comments
* Update polymorphic test names
* Rename polymorphic tests
* Update listener test name
* Delete redundant tenant ID assignments
* Improve test names
* Move polymorphic tests to ResourceSyncingTest
* Mention alternative solutions in CentralResourceNotAvailableInPivotException
* Add comments
* Update test comments
* minor changes to tests + review comments
* Delete extra tests, update comments
* Remove unneeded part of test
* Fix comment
* Improve comments
* Add test for companies() realationship accessibility
* Update test name
* Complete to-do, add comment
* Improve naming and comments (resolve some priority reviews)
* Move test
* Comment, resolve to-dos
* Add low-level pivot assertions
* Restore trashed resources if the central resource got restored, try improving tests
* Fix code style (php-cs-fixer)
* Dekete redundnat unsynced comments
* Add to-do, test WIP
* Fix restoring logic
* Update todo
* Add todo to fix phpdoc
* Fix code style (php-cs-fixer)
* PHPStan error fix wip
* Fix PHPStan error
* Add regression test
* Delete unused trait
* Add and test restoring WIP
* Fix code style (php-cs-fixer)
* Add to-do
* Delete comment from test
* Focus on restoring in the restore test
* Improve maming
* Fix stub
* Delete redundant part of test
* Delete incorrect test leftover
* Add triggerRestoredEvent
* Fix restore test
* Correct tests and restore(() logic
* Fix code style (php-cs-fixer)
* Check if SoftDeletes are used before firing SyncMasterRestored
* Fix comment
* Revert restore action changes (phpstan errors)
* Delete CascadeDeletes interface
* Remove CascadeDeletes from most of the tests
* Fix code style (php-cs-fixer)
* Rename tests
* Fix restoring + tests WIP
* Fix restoring
* Fix restoring tests
* Fix code style (php-cs-fixer)
* Test that detaching force deletes the tenant resources
* Implement cacscade force deleting
* Delete redundant changes
* Fix typo
* Fix SyncMaster
* Improve test
* Add force deleting logic back and fix tests
* Improve comment
* Delete extra assertion
* Improve restoring test
* Simplify assertion
* Delete redundant query scoping from test
* Test restore listener queueing
* use strict in_array() checks
* fix phpstan errors
---------
Co-authored-by: lukinovec <lukinovec@gmail.com>
Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
* wip
* Fix code style (php-cs-fixer)
* adjust tests
* Update ResourceSyncingPolymorphicTest.php
* Update SyncMaster.php
* correct method name
* Update ResourceSyncingPolymorphicTest.php
* use BelongsToMany return type
* separate pivot model for each approach
* ability to publish migrations
* remove unsed import
* use resource migrations from asset
* anonymous migration for `tenant_resources` table
* rename file
* rename classes
* trait
* add back using statement
* revert to unset change
* use unset approach
* use unset approach
* Assert `tenants` are accessible
* Update ResourceSyncingUsingPolymorphicTest.php
* improve `tenants` assertions
* improve assertions
* remove `getResourceTenantModelName` method and use config
* use `BelongsToMany` for `tenants` method return type
* Fix code style (php-cs-fixer)
* revert type
* use correct key
* test right resources are accessible from the tenant
* Update tests/ResourceSyncingUsingPolymorphicTest.php
---------
Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
Co-authored-by: Samuel Štancl <samuel@archte.ch>
* wip
* add test
* readability
* remove group
* DisabledSync -> ConditionalSync; test both cases with dataset
Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>
* Add readied tenants
Add config for readied tenants
Add `create` and `clear` command
Add Readied scope and static functions
Add tests
* Fix initialize function name
* Add readied events
* Fix readied column cast
* Laravel 6 compatible
* Add readied scope tests
* Rename config from include_in_scope to include_in_queries
* Change terminology to pending
* Update CreatePendingTenants.php
* Laravel 6 compatible
* Update CreatePendingTenants.php
* runForMultiple can scope pending tenants
* Fix issues
* Code and comment style improvements
* Change 'tenant' to 'tenants' in command signature
* Fix code style (php-cs-fixer)
* Rename variables in CreatePendingTenants
* Remove withPending from runForMultiple
* Update tenants option trait
* Update command that use tenants
* Fix code style (php-cs-fixer)
* Improve getTenants condition
* Update config comments
* Minor config comment corrections
* Grammar fix
* Update comments and naming
* Correct comments
* Improve writing
* Remove pending tenant clearing time constraints
* Allow using only one time constraint for clearing the pending tenants
* phpunit to pest
* Fix code style (php-cs-fixer)
* Fix code style (php-cs-fixer)
* [4.x] Optionally delete storage after tenant deletion (#938)
* Add test for deleting storage after tenant deletion
* Save `storage_path()` in a variable after initializing tenant in test
Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>
* Add DeleteTenantStorage listener
* Update test name
* Remove storage deletion config key
* Remove tenant storage deletion events
* Move tenant storage deletion to the DeletingTenant event
Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>
* [4.x] Finish incomplete and missing tests (#947)
* complete test sqlite manager customize path
* complete test seed command works
* complete uniqe exists test
* Update SingleDatabaseTenancyTest.php
* refactor the ternary into if condition
* custom path
* simplify if condition
* random dir name
* Update SingleDatabaseTenancyTest.php
* Update CommandsTest.php
* prefix random DB name with custom_
Co-authored-by: Samuel Štancl <samuel@archte.ch>
* [4.x] Add batch tenancy queue bootstrapper (#874)
* exclude master from CI
* Add batch tenancy queue bootstrapper
* add test case
* skip tests for old versions
* variable docblocks
* use Laravel's connection getter and setter
* convert test to pest
* bottom space
* singleton regis in TestCase
* Update src/Bootstrappers/BatchTenancyBootstrapper.php
Co-authored-by: Samuel Štancl <samuel@archte.ch>
* convert batch class resolution to property level
* enabled BatchTenancyBootstrapper by default
* typehint DatabaseBatchRepository
* refactore name
* DI DB manager
* typehint
* Update config.php
* use initialize() twice without end()ing tenancy to assert that previousConnection logic works correctly
Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>
Co-authored-by: Abrar Ahmad <abrar.dev99@gmail.com>
Co-authored-by: Samuel Štancl <samuel@archte.ch>
* [4.x] Storage::url() support (modified #689) (#909)
* This adds support for tenancy aware Storage::url() method
* Trigger CI build
* Fixed Link command for Laravel v6, added StorageLink Events, more StorageLink tests, added RemoveStorageSymlinks Job, added Storage Jobs to TenancyServiceProvider stub, renamed misleading config example.
* Fix typo
* Fix code style (php-cs-fixer)
* Update config comments
* Format code in Link command, make writing more concise
* Change "symLinks" to "symlinks"
* Refactor Link command
* Fix test name typo
* Test fetching files using the public URL
* Extract Link command logic into actions
* Fix code style (php-cs-fixer)
* Check if closure is null in CreateStorageSymlinksAction
* Stop using command terminology in CreateStorageSymlinksAction
* Separate the Storage::url() test cases
* Update url_override comments
* Remove afterLink closures, add types, move actions, add usage explanation to the symlink trait
* Fix code style (php-cs-fixer)
* Update public storage URL test
* Fix issue with using str()
* Improve url_override comment, add todos
* add todo comment
* fix docblock style
* Add link command tests back
* Add types to $tenants in the action handle() methods
* Fix typo, update variable name formatting
* Add tests for the symlink actions
* Change possibleTenantSymlinks not to prefix the paths twice while tenancy is initialized
* Fix code style (php-cs-fixer)
* Stop testing storage directory existence in symlink test
* Don't specify full namespace for Tenant model annotation
* Don't specify full namespace in ActionTest
* Remove "change to DI" todo
* Remove possibleTenantSymlinks return annotation
* Remove symlink-related jobs, instantiate and use actions
* Revert "Remove symlink-related jobs, instantiate and use actions"
This reverts commit 547440c887.
* Add a comment line about the possible tenant symlinks
* Correct storagePath and publicPath variables
* Revert "Correct storagePath and publicPath variables"
This reverts commit e3aa8e2086.
* add a todo
Co-authored-by: Martin Vlcek <martin@dontfreakout.eu>
Co-authored-by: lukinovec <lukinovec@gmail.com>
Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
* Use HasTenantOptions in Link
* Correct the tenant order in Run command
* Fix code style (php-cs-fixer)
* Fix formatting issue
* Add missing imports
* Fix code style (php-cs-fixer)
* Use HasTenantOptions instead of the old trait name in Up/Down commands
* Fix test name typo
* Remove redundant passing of $withPending to runForMultiple in TenantCollection's runForEach
* Make `with-pending` default to `config('tenancy.pending.include_in_queries')` in HasTenantOptions
* Make `createPending()` return the created tenant
* Fix code style (php-cs-fixer)
* Remove tenant ordering
* Fix code style (php-cs-fixer)
* Remove duplicate tenancy bootstrappers config setting
* Add and use getWithPendingOption method
* Fix code style (php-cs-fixer)
* Add optionNotPassedValue property
* Test using --with-pending and the include_in_queries config value
* Make with-pending VALUE_NONE
* use plural in test names
* fix test names
* add pullPendingTenantFromPool
* Add docblock type
* Import commands
* Fix code style (php-cs-fixer)
* Move pending tenant tests to a more appropriate file
* Delete queuetest from gitignore
* Delete queuetest file
* Add queuetest to gitignore
* Rename pullPendingTenant to pullPending and don't pass bool to that method
* Add a test that checks if pulling a pending tenant removes it from the pool
* bump stancl/virtualcolumn to ^1.3
* Update pending tenant pulling test
* Dynamically get columns for pending queries
* Dynamically get virtual column name in ClearPendingTenants
* Fix ClearPendingTenants bug
* Make test name more accurate
* Update test name
* add a todo
* Update include in queries test name
* Remove `Tenant::query()->delete()` from pending tenant check test
* Rename the pending tenant check test name
* Update HasPending.php
* fix all() call
* code style
* all() -> get()
* Remove redundant `Tenant::all()` call
Co-authored-by: j.stein <joristein@gmail.com>
Co-authored-by: lukinovec <lukinovec@gmail.com>
Co-authored-by: PHP CS Fixer <phpcsfixer@example.com>
Co-authored-by: Abrar Ahmad <abrar.dev99@gmail.com>
Co-authored-by: Riley19280 <rileyaven88@gmail.com>
Co-authored-by: Martin Vlcek <martin@dontfreakout.eu>
* Add bring up from maintenance function
* Add up and down tenant maintenance commands
* Rename commands signatures
* Update TenancyServiceProvider.php
* Complying to Laravel maintenance code and parameters
* Update MaintenanceModeTest.php
* Add maintenance mode via commands test
* Update CheckTenantForMaintenanceMode.php
* Update MaintenanceModeTest.php
* Cookie bypass only for > Laravel 8
* minor formatting change, trigger CI
* clean
* Update MaintenanceModeTest.php
* Add comments for using the 'tenants' option in runForMultiple
* improve code
* php-cs-fixer
* fix php cs fixer config
* improve test logic
* remove version check since v4 will be L9+
Co-authored-by: Samuel Štancl <samuel@archte.ch>
Co-authored-by: lukinovec <lukinovec@gmail.com>
Co-authored-by: Samuel Štancl <samuel.stancl@gmail.com>