Skip to content

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:

bash
php artisan sharp:upgrade app/Sharp

Where 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(), or execute(): array methods it could not safely rewrite).

Updating Dependencies ​

If you depend on them, you should update the following dependencies in your composer.json file :

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)

php
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)

php
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:

php
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): CommandReloadReturn

Note 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.

(handled by sharp:upgrade)

php
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('') and assertReturnsLink('') 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:

php
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.

php
// 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:

php
\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:

php
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 associated CurrentSharpRequest class were removed. Use sharp()-⁠>context() instead (cf. Context).
  • The SharpAuthenticationCheckHandler interface was removed. Use the viewSharp Gate instead.
  • The withSharpCurrentBreadcrumb() method in SharpAssertions was removed. Use withSharpBreadcrumb() instead.
  • Removal of "multi-forms". Replace all SharpEntity::getMultiforms() implementations to SharpEntityList::configureEntityMap() instead (cf. Building entity list).
  • Smart handling of legacy fontaweome icons class has been removed. Tou must convert all fa- occurences to fas-*, far-*, fab-*.

Configuration ​

  • The legacy configuration handling based on the sharp.php config file was removed. You must now use a SharpAppServiceProvider with a SharpConfigBuilder.
  • SharpConfigBuilder::addEntity() has been removed in favor of SharpConfigBuilder::declareEntity().

Forms ​

  • The legacy $formValidatorClass property handling in SharpForm was removed. Implement the SharpForm::rules() and SharpForm::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:
php
\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. Use withField() or withListField() instead.
  • SharpFormDateField::setDisplayFormat() has been removed
  • SharpFormAutocompleteField was removed. Migrate to the following
    • SharpFormAutocompleteField::make('key', 'local') to SharpFormAutocompleteLocalField::make('key')
    • SharpFormAutocompleteField::make('key', 'remote') to SharpFormAutocompleteRemoteField::make('key')

Entity Lists ​

  • The setWidthOnSmallScreens() and setWidthOnSmallScreensFill() methods in EntityListField were removed as they are no longer used in the new front-end table UI.
  • The configureMultiformAttribute() method in SharpEntityList was removed. Use configureEntityMap() instead.

Show ​

  • The configureMultiformAttribute() method in SharpShow was removed. It's not used by sharp.

Filters ​

The following classes have been renamed / moved:

php
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; 

Released under the MIT License.