Upgrading from 9.x to 10.x
The upgrade command
Sharp 10 comes with an upgrade command that replaces and notifies for deprecated and removed code. You can run it with:
php artisan sharp:upgrade app/SharpWhere app/Sharp is the base path of your sharp code. Use the --dry-run option to list the files that would be updated without writing them.
The command handles most of the changes described below:
- it rewrites moved classes and namespaces, renamed methods, Command return types and the
info()/link()boolean arguments; - it reports the files where it detected removed code that must be migrated by hand (like
currentSharpRequest(), orexecute(): arraymethods it could not safely rewrite).
Updating Dependencies
If you depend on them, you should update the following dependencies in your composer.json file :
inertiajs/inertia-laravelto^3.0(cf. https://inertiajs.com/docs/v3/getting-started/upgrade-guide)
Commands
Commands have moved out of the EntityList namespace
Commands are used everywhere in Sharp (Entity Lists, Show Pages, Dashboards), so they now live in their own namespace. The ReorderHandler interface, which is not a command, has moved to the EntityList namespace. (handled by sharp:upgrade)
use Code16\Sharp\EntityList\Commands\EntityCommand;
use Code16\Sharp\Commands\EntityCommand;
use Code16\Sharp\EntityList\Commands\Wizards\InstanceWizardCommand;
use Code16\Sharp\Commands\Wizards\InstanceWizardCommand;
use Code16\Sharp\EntityList\Commands\ReorderHandler;
use Code16\Sharp\EntityList\ReorderHandler; This applies to all classes of Code16\Sharp\EntityList\Commands (Command, EntityCommand, InstanceCommand, SingleInstanceCommand, EntityState, SingleEntityState and the Wizards classes), except Code16\Sharp\EntityList\Commands\QuickCreate\QuickCreationCommand, which is specific to Entity Lists and stays where it is. Code16\Sharp\Dashboard\Commands\DashboardCommand is unchanged as well.
Commands must return a CommandReturn
Command execution methods now return a typed Code16\Sharp\Commands\Returns\CommandReturn object instead of an array. Since the $this->info(), $this->reload(), $this->refresh()... helpers are unchanged, you only need to update the return types. (handled by sharp:upgrade)
use Code16\Sharp\Commands\Returns\CommandReturn;
class MyCommand extends InstanceCommand
{
public function execute(mixed $instanceId, array $data = []): array
public function execute(mixed $instanceId, array $data = []): CommandReturn
{
return $this->reload();
}
}This applies to execute(), executeSingle(), and the Wizard executeFirstStep() / executeStep() / executeStepXXX() methods. Entity States have more specific return types:
use Code16\Sharp\Commands\Returns\CommandRefreshReturn;
use Code16\Sharp\Commands\Returns\CommandReloadReturn;
// EntityState
protected function updateState($instanceId, string $stateId): ?array
protected function updateState($instanceId, string $stateId): CommandReloadReturn|CommandRefreshReturn|null
// SingleEntityState
protected function updateSingleState(string $stateId): array
protected function updateSingleState(string $stateId): CommandReloadReturnNote that updateSingleState() can no longer return null: it must return $this->reload().
WARNING
sharp:upgrade only rewrites classes that directly extend a Sharp Command class. If your Commands extend your own abstract class, the command will report the remaining execute(): array methods, which you must update by hand.
info and link boolean arguments are replaced by fluent modifiers
(handled by sharp:upgrade)
return $this->info('Invitation sent!', reload: true);
return $this->info('Invitation sent!')->withReload();
return $this->link('https://example.org', openInNewTab: true);
return $this->link('https://example.org')->inNewTab(); Both modifiers accept an optional boolean, for conditional cases: ->withReload($shouldReload).
Testing assertions
A few Command testing assertions were improved (cf. Testing), with two small behavior changes:
assertReturnsInfo('')andassertReturnsLink('')now assert an empty message / link; to assert any value, omit the parameter.- Response methods called on testing objects now return their value:
->json('message')returns the message instead of the testing object.
Uploads
Existing uploads must be signed
For security reasons, when an existing upload is sent back by an Upload field (unchanged, or with a transformation), Sharp now checks that its disk and path are the ones it rendered in the form. To do that, it adds a path_signature attribute to upload values (based on your APP_KEY, APP_PREVIOUS_KEYS is supported), which the front sends back with the rest of the value. If the signature is missing or does not match, the update fails with a validation error.
This is transparent when using Sharp forms and its built-in uploads, but it impacts any code that posts existing upload values by hand, typically your tests:
use Code16\Sharp\Utils\Uploads\UploadPathSignature;
$this->sharpForm(Post::class, 1)
->edit()
->update([
// picture is already on the Post
'picture' => [
'path' => 'data/test/image.jpg',
'disk' => 'local',
'path_signature' => UploadPathSignature::make(disk: 'local', path: 'data/test/image.jpg'),
],
]);Note that new uploads ('uploaded' => true) are not impacted.
Disabling the signature check in tests
If you have a lot of tests posting upload values by hand and can't sign them all right away, you can disable the check in your tests only, with the disableUploadPathSigning() config method. path_signature is then neither sent nor checked.
// tests/TestCase.php (or in a Pest `beforeEach`)
protected function setUp(): void
{
parent::setUp();
sharp()->config()->disableUploadPathSigning();
}DANGER
Do not disable the signature check in your service provider or in production. It would allow any user who can update an entity with an Upload field to store an arbitrary disk and path, and then read the matching file through the generated thumbnail or download URLs.
Deprecated methods
Forms
Upload setImageCompactThumbnail() has no impact and can be removed:
\Code16\Sharp\Form\Fields\SharpFormUploadField::make('upload')
->setImageCompactThumbnail() Testing
The legacy testing API is deprecated and will be removed in 11.x. Please refer to (cf. Testing). Here are replacement examples:
uses(\Code16\Sharp\Utils\Testing\SharpAssertions::class)
it('test', function () {
$this->callSharpEntityCommandFromList(PersonEntity::class, MyCommand::class, ['attr' => 'some_value'])
$this->sharpList(PersonEntity::class)->entityCommand(MyCommand::class)->post(['attr' => 'some_value'])
$this->callSharpInstanceCommandFromList(PersonEntity::class, 1, MyCommand::class, ['attr' => 'some_value'])
$this->sharpList(PersonEntity::class)->instanceCommand(MyCommand::class, 1)->post(['attr' => 'some_value'])
$this->callSharpInstanceCommandFromShow(PersonEntity::class, 1, MyCommand::class, ['attr' => 'some_value'])
$this->sharpShow(PersonEntity::class, 1)->instanceCommand(MyCommand::class)->post(['attr' => 'some_value'])
$this->getSharpShow(PersonEntity::class, 1)
$this->sharpShow(PersonEntity::class, 1)->get()
$this->getSharpForm(PersonEntity::class, 1)
$this->sharpForm(PersonEntity::class, 1)->get()
$this->getSingleSharpForm(PersonEntity::class)
$this->sharpForm(PersonEntity::class)->get()
$this->updateSharpForm(PersonEntity::class, 1, [])
$this->sharpForm(PersonEntity::class, 1)->update([])
$this->storeSharpForm(PersonEntity::class, 1, [])
$this->sharpForm(PersonEntity::class, 1)->store([])
$this->updateSingleSharpForm(PersonEntity::class, [])
$this->sharpForm(PersonEntity::class)->update([])
$this->withSharpBreadcrumb(function (\Code16\Sharp\Utils\Links\BreadcrumbBuilder $builder) {
$builder->appendEntityList(PersonEntity::class)->appendShowPage(PersonEntity::class, 1)
})->getSharpForm(PersonEntity::class, 1)
$this->sharpList(PersonEntity::class)->sharpShow(PersonEntity::class, 1)->sharpForm(PersonEntity::class)->get()
})Removed classes and methods
Several features and methods that were deprecated in Sharp 9.0 have been removed to clean up the codebase.
General
- The
currentSharpRequest()helper and its associatedCurrentSharpRequestclass were removed. Usesharp()->context()instead (cf. Context). - The
SharpAuthenticationCheckHandlerinterface was removed. Use theviewSharpGate instead. - The
withSharpCurrentBreadcrumb()method inSharpAssertionswas removed. UsewithSharpBreadcrumb()instead. - Removal of "multi-forms". Replace all
SharpEntity::getMultiforms()implementations toSharpEntityList::configureEntityMap()instead (cf. Building entity list). - Smart handling of legacy fontaweome icons class has been removed. Tou must convert all
fa-occurences tofas-*,far-*,fab-*.
Configuration
- The legacy configuration handling based on the
sharp.phpconfig file was removed. You must now use aSharpAppServiceProviderwith aSharpConfigBuilder. SharpConfigBuilder::addEntity()has been removed in favor ofSharpConfigBuilder::declareEntity().
Forms
- The legacy
$formValidatorClassproperty handling inSharpFormwas removed. Implement theSharpForm::rules()andSharpForm::messages()methods instead (cf. Building form). Along with this removal, the following classes have been removed:\Code16\Sharp\Form\Validator\SharpFormRequest\Code16\Sharp\Form\Validator\SharpValidator\Code16\Sharp\Http\Middleware\Api\BindSharpValidationResolver(remove this from config)
- In
SharpFormUploadField, the following deprecated methods were removed:
\Code16\Sharp\Form\Fields\SharpFormUploadField::make('upload')
->setCropRatio()
->setImageCropRatio()
->shouldOptimizeImage()
->setImageOptimize()
->setTransformable()
->setImageTransformable()
->setFileFilterImages()
->setImageOnly()
->setFileFilter()
->setAllowedExtensions() - The
FormLayoutColum::withSingleField()&ShowLayoutColum::withSingleField()method was removed. UsewithField()orwithListField()instead. SharpFormDateField::setDisplayFormat()has been removedSharpFormAutocompleteFieldwas removed. Migrate to the followingSharpFormAutocompleteField::make('key', 'local')toSharpFormAutocompleteLocalField::make('key')SharpFormAutocompleteField::make('key', 'remote')toSharpFormAutocompleteRemoteField::make('key')
Entity Lists
- The
setWidthOnSmallScreens()andsetWidthOnSmallScreensFill()methods inEntityListFieldwere removed as they are no longer used in the new front-end table UI. - The
configureMultiformAttribute()method inSharpEntityListwas removed. UseconfigureEntityMap()instead.
Show
- The
configureMultiformAttribute()method inSharpShowwas removed. It's not used by sharp.
Filters
The following classes have been renamed / moved:
use \Code16\Sharp\EntityList\Filters\EntityListCheckFilter;
use \Code16\Sharp\Utils\Filters\CheckFilter;
use \Code16\Sharp\Filters\CheckFilter;
use \Code16\Sharp\EntityList\Filters\EntityListDateRangeFilter;
use \Code16\Sharp\Utils\Filters\DateRangeFilter;
use \Code16\Sharp\Filters\DateRangeFilter;
use \Code16\Sharp\EntityList\Filters\EntityListDateRangeRequiredFilter;
use \Code16\Sharp\Utils\Filters\DateRangeRequiredFilter;
use \Code16\Sharp\Filters\DateRangeRequiredFilter;
use \Code16\Sharp\EntityList\Filters\EntityListSelectFilter;
use \Code16\Sharp\Utils\Filters\SelectFilter;
use \Code16\Sharp\Filters\SelectFilter;
use \Code16\Sharp\EntityList\Filters\EntityListSelectMultipleFilter;
use \Code16\Sharp\Utils\Filters\SelectMultipleFilter;
use \Code16\Sharp\Filters\SelectMultipleFilter;
use \Code16\Sharp\EntityList\Filters\EntityListSelectRequiredFilter;
use \Code16\Sharp\Utils\Filters\SelectRequiredFilter;
use \Code16\Sharp\Filters\SelectRequiredFilter;