Coder Social home page Coder Social logo

wn-builder-plugin's Introduction

Builder plugin

A user-friendly, visual plugin scaffolding tool that makes it trivial to get a new plugin running in Winter CMS. This plugin takes away the leg-work in setting up the necessary structure for a plugin by providing several simple tools that manage all facets of your plugin's definitions and files.

Installation

You can install the plugin using Composer. As this is a development plugin, it should be defined as a "dev" dependency.

composer require --dev winter/wn-builder-plugin

Features

With the Builder plugin, you can:

  • Create and update your plugin's database schema, with automatic migration generation.
  • Define models for your database tables.
  • Create and manage controllers.
  • Define your plugin's Backend navigation items and available permissions.
  • Design and create your forms and lists.
  • Manage your plugin's versions and migrations.
  • Use simple, universal Builder components on your CMS templates to display full lists and single records.

The Builder plugin works gracefully with your own work tools and methodologies, being both comprehensive and yet careful with its own scope of plugin modifications - allowing you to work on more complex plugin functionality in your own development environment without interference from the Builder plugin.

Builder is a visual development tool. It shortens plugin development time by automating common development tasks and makes programming fun again. With Builder you can create a fully functional plugin scaffold in a matter of minutes.

Builder makes the learning curve less steep by providing a visual interface that naturally incorporates Winter's design patterns and documentation. Here’s an example, instead of looking into the documentation for a list of supported form controls and their features, you can just open the Form Builder, find a suitable control in the Control Palette, add the control to the form and explore its properties with the visual inspector.

Builder implements a Rapid Application Development process that automates the boring activities without sacrificing complete control. With this tool you can spend more time implementing the plugin's business logic in your favorite code editor rather than dealing with the more mundane tasks, like building forms or managing plugin versions.

Plugins created with the help of Builder are no different to plugins that you would usually create by hand. That means that you can continue to use your usual “hands on” workflow for updating your servers, managing the code versions and sharing work with your teammates.

Video tutorial

Check out https://vimeo.com/154415433 for a video tutorial showing how to use the plugin to build a simple library plugin.

What you can do with Builder

This tool includes multiple features that cover almost all aspects of creating a plugin.

  • Initializing a new plugin - this creates the plugin directory along with any necessary files.
  • Creating and editing plugin database tables. All schema changes are saved as regular migration files, so you can easily update the plugin on other servers using your regular workflow.
  • Creating model classes.
  • Creating backend forms with the visual Form Builder.
  • Creating backend lists.
  • Managing a list of user permissions provided by the plugin.
  • Creating plugin backend navigation - in the form of main menu items and sidebar items.
  • Creating backend controllers and configuring their behaviors with a visual tool.
  • Managing plugin versions and updates.
  • Managing plugin localization files.
  • A set of universal components - used for displaying data from the plugin on the front-end in form of lists and single record details.

Put simply, you can create a multilingual plugin, that installs database tables, has backend lists and forms protected with user permissions, and adds CMS pages for displaying data managed with the plugin. After learning how Builder works, this process takes just a few minutes.

Builder is a productivity tool, it doesn't completely replace coding by hand and doesn't include a code editor for editing PHP files (the only exception is the version management interface). Builder never overwrites or deletes plugin PHP files, so you can rest assured knowing that the code you write never gets touched by Builder. However, Builder can create new PHP files, like models and controllers.

Most of the visual editors in Builder work with YAML configuration files, which are a native concept in Winter CMS. For example, after creating a model class in Builder, you can choose to add a form to the model. This operation creates a YAML file in the model's directory.

There are currently some limitations when using Builder. Some of them are missing features which will be added later. Others are ideas intentionally omitted to keep the things simple. As mentioned above, Builder doesn't want to replace coding, while at the same time, it doesn't go too far with visual programming either. The limitations are explained and described in the corresponding sections of the plugin documentation. Those limitations don't mean you can't create any plugin you want - the good old approach to writing the code manually is always applicable for plugins developed with Builder. Builder’s aim is to be a modest, yet powerful tool that is used to accelerate your development cycle.

Getting started

Before you create your first plugin with Builder you should configure it. Open the Settings page in the Winter CMS backend and find Builder in the side menu. Enter your author name and namespace. The author name and namespace are required fields and should not change if you wish to publish your plugins on Winter CMS Marketplace.

If you already have a Marketplace account, use your existing author name and namespace.

Initializing a new plugin

On the Builder page in Winter CMS backend click the small arrow icon in the sidebar to expose the plugin list. After clicking the "Create plugin" button, enter the plugin name and namespace. The default author name and namespace can be pre-filled from the plugin settings. Select the plugin icon, enter the description text and plugin homepage URL (optional).

Please note that you cannot change the namespaces after you create the plugin.

When Builder initializes a plugin, it creates the following files and directories in Winter's plugins directory:

 📂 myauthor              /* Author name */
 ┗ 📂 myplugin            /* Plugin name */
   ┣ 📂 lang              /* Localization files */
   ┃ ┗ 📂 en              /* Specific locale folder */
   ┃   ┗ 📜 lang.php      /* Translations */
   ┣ 📂 updates           /* Database migrations */
   ┃ ┗ 📜 version.yaml    /* Changelog */
   ┣ 📜 Plugin.php        /* Plugin registration class */
   ┗ 📜 plugin.yaml       /* Basic plugin information in YAML format in order to edit with Builder */

The file plugin.yaml contains the basic plugin information - name, description, permissions and backend navigation. This file is managed by the Builder user interface.

The initial contents of the lang.php localization file is the plugin name and description. The localization file is created in the default locale of your Winter installation.

When a new plugin is created, it's automatically selected as the current plugin that Builder works with. You can select another plugin in the plugin list if you need.

Managing plugin database tables

Tables are managed on the Database tab of Builder. You can create tables, update their structure and delete tables with the visual interface.

Click Add button to open the Create Table tab. Builder automatically generates prefixes for plugin tables. The prefixes are compliant with the Developer Guidelines for database tables.

Every time when you save changes in a table, Builder shows a popup window with the automatically generated migration PHP code. You can't edit the code in the popup, but you can inspect it or copy to the clipboard. After reviewing the migration, click Save & Apply button. Builder executes the migration immediately and saves the migration file to the plugin's updates directory. Afterwards you can find all plugin migrations on the Versions tab of Builder.

Note: Although Builder generates migration files automatically, it can't prevent the data loss in some cases when you significantly change the table structure. In some cases it's possible - for example, when you alter length of a string column. Always check the migration PHP code generated by Builder before applying the migration and consider possible consequences of running the migration in a production database.

Currently Builder doesn't allow you to manage table indexes with the visual user interface. Unique column management is not supported yet as well. Please use the Version Management feature to manually create migration files.

Please note that the enum data type is not currently supported by the Builder due to limitations in the underlying Doctrine classes.

Managing models

You can edit models on the Models tab of Builder. Click the Add button, enter the model class name and select a database table from the drop-down list.

The model class name should not contain the namespace. Some examples: Post, Product, Category.

Please note that you cannot delete model files with builder because it would contradict the idea of not deleting or overwriting PHP files with the visual tool. If you need to delete a model, remove its files manually.

Managing backend forms

In Winter CMS forms belong to models. For every model you can create as many backend forms as you need, but in most cases there is a single form per model.

Note: when you create a form, it's not displayed in Winter CMS backend until you create a backend controller which uses the form. Read about controllers below.

On the Models tab in Builder find a model you want to create a form for. Expand the model if needed, hover the Forms section and click the plus sign.

Forms in Winter CMS are defined with YAML files. The default form file name is fields.yaml. In the Form Builder, click a placeholder and select a control from the popup list. After that you can click the control and edit it parameters in Inspector.

Almost all form controls have these common properties:

  • Field name - a model field name. It's an autocomplete field in Inspector, which allows you to select column names from the underlying database table. Currently relations are not displayed in the autocomplete hints, this will be implemented later. You can enter any model property manually.
  • Label - The control label. You can enter a static text string to the field, or create a new localization string by clicking the plus sign in the input field. Almost all editors in Builder support this feature.
  • Comment - the comment text - fixed text or localization string key.
  • Span - position of the control on the form - left, right, full or automatic placement.

Most of the properties have descriptive names or have a description in Inspector. If you need more information about control properties please refer to the Documentation.

You can drag controls in the Form Builder to rearrange them or to move them to/from form tabs.

Note: a form tab should have at least one control, otherwise it will be ignored when Form Builder saves the YAML file.

Note: some form controls, for example the file upload control, require a relation to be created in the model class manually. The relation name should be entered in the Field name property. Please read the Forms Documentation for details about specific form controls.

Managing backend lists

Similarly to forms, backend lists in Winter CMS belong to models.

Note: when you create a list, it's not displayed in Winter CMS backend until you create a backend controller which uses the list. Read about controllers below.

On the Models tab in Builder find a model you want to create a list for. Expand the model if needed, hover the Lists section and click the plus sign.

Lists in Winter CMS are defined with YAML files. The default list file name is columns.yaml. The grid in the list editor contains list column definitions. Column property names are self descriptive, although some of them require some explanations. Refer to the Lists documentation for details about each property.

For the Label property you can either enter a static string or create a new localization string.

The Field property column has an autocompletion feature attached. It allows you to select columns from the database table that is bound to the model. At the moment it doesn't show relation properties, but you can still type them in manually.

Managing plugin permissions

Plugin permissions define what features and backend plugin pages a user can access. You can manage permissions on the Permissions tab in Builder. For each permission you should specify a unique permission code, permission tab title and permission label. The tab title and label are displayed in the user management interface on the System page in October backend.

For the tab title and label you can either enter a static string or create a new localization string.

Later, when you create controllers and menu items, you can select what permissions users should have in order to access or see those objects.

Managing backend menus

The plugin navigation is managed on the Backend Menus tab of the Builder. The user interface allows to create top level menu items and sidebar items.

To create a menu item click the placeholder rectangle and then click the new item to open Inspector. In the inspector you can enter the item label, select icon and assign user permissions. The code property is required for referring menu items from the controllers code (for marking menu items active).

Note: when you create menu items for backend pages which don't exist yet in the plugin, it makes sense to leave the URL property empty until you create the plugin controllers. This property supports autocompletion, so you can just select your controller URLs from the drop-down list.

Managing backend controllers, forms and lists

Backend pages in Winter CMS are provided with backend controllers. Usually backend pages contain lists and forms for managing plugin records, although you can create any custom controller.

Please refer to the backend forms, lists and reorder controller documentation pages for more information about controller behaviors. Currently only List, Form and Reorder Controller behaviors can be configured with the Builder. If your controller contains other behaviors they won't be removed by the Builder, you just won't be able to edit them with the visual interface.

Builder also allows you to create empty controller classes which don't implement any behaviors and customize them manually.

Note: Some behaviors require specific model features to be implemented. For example, the Reorder Controller behavior requires the model to implement Sortable or NestedTree traits. Always refer to the specific behavior documentation for the implementation details.

To create a controller, click the Add button list on the Controllers tab. Enter the controller class name, for example Posts.

If the controller is going to provide backend lists or forms, select a base model in the drop-down list and select behaviors you want to add. You can also select a top and sidebar menu items that should be active on the controller pages. If needed, choose permissions that users must have to access the controller pages.

Please note that the settings you enter in the Create Controller popup cannot be changed with Builder. However you can update them manually by editing controller classes.

After creating a controller you can configure its behaviors. Click the controller in list and then click a behavior you want to configure. When Builder creates a controller it tries to apply default configuration to the behaviors, however you might want to change it. Inspector lists displays all supported behavior properties. URL properties (like the list records URLs) are autocomplete fields and populated with URLs of the existing plugin controllers.

Managing plugin versions

Please read the Version History documentation page to understand how versioning works in Winter CMS.

Basically there are 3 types of version updates:

  1. Updates which change the database structure - migrations. Builder can generate migration files automatically when you make changes in the DB schema on the Database tab.
  2. Seeding updates, which populate the database contents.
  3. Version updates, which do not update anything in the database but are often used for releasing code changes.

Plugin versions are managed on the Versions tab of the Builder. This tab displays a list of existing plugin versions their status. Applied versions have a green checkbox marker. Pending versions have a grey clock marker.

You can create a new version with clicking the Add button and selecting the update time. The user interface automatically generates scaffold PHP code for the "Migration" and "Seeder" updates. The "Increase the version number" updates won’t contain any PHP code.

For every version you should specify the new version number and description. Builder generates the version number automatically by increasing the last digit in the existing version. You might want to change it if you're releasing a major version update and want to change the first or second digit.

When a version file is saved, Builder doesn't apply it immediately. You should click the "Apply version" button in the toolbar in order to apply the version and execute the update code (if applicable). You can also rollback already applied version updates, change their code and apply again. This allows you to edit database schema updates generated by Builder if you don't like the default code.

Note that your migration files should provide correct rollback code in the down method in order to use the rollback feature.

When you rollback a version, it automatically rolls back all newer versions. When you apply a version, it automatically applies all pending older versions. Please remember that when a user logs into the backend, October automatically applies all pending updates. Never edit versions on a production server or on a server with multiple backend users - it could cause unpredictable consequences.

Migrations that contain multiple scripts are not supported. They can't be created or edited with Builder.

Managing localization

Localization files are managed on the Localization tab of the Builder. When a new plugin is initialized, a single language file is created. This file is created in the default system locale specified in Winter CMS configuration scripts.

You can create as many language files as you want. Builder UI always displays strings in the Winter CMS locale, so you might want to update your configuration files to see your plugin in another language.

Please note that although localization files in Winter CMS are PHP scripts, they are translated to YAML to simplify the editing in the Builder user interface. When language files are saved, they are translated back to PHP again.

Builder tries to keep the user interface synchronized with your default language file. This means that when you save the language file, Builder automatically updates all localized strings in all editors. In some cases you might need to close and open Inspector in order to re-initialize the autocomplete fields.

In many cases you can create new localization strings on-the-fly from the Builder editors - the Form Builder, Menu Builder, etc. The localization input field has the plus icon on the right side. Clicking the plus icon opens a popup window that allows you to enter the localization string key and value. The string key can contain dots to mark the localization file sections. For example - if you add a string with the key plugin.posts.category and value "Enter a category name", Builder will create the following structure in the language file:

plugin:
    posts:
        category: Enter a category name

If you create a new localization string from the Inspector or other editor while you have the default language file tab open in the Builder, it will try to update the tab contents or merge the updated file contents from the server. It's a good idea to keep the default localization file always saved in the Builder to avoid possible content conflicts when you edit localization from another place.

Protip: In YAML a single quote is escaped with two single quotes (https://yaml.org/spec/1.2.2).

Displaying plugin records on the front-end pages

Builder provides universal CMS components that you can use for displaying records from your plugins on the front-end website pages. The components provide only basic functionality, for example they don't support a record search feature.

Please read the CMS documentation to learn more about the CMS components concept.

Record list component

The Record list component outputs a list of records provided by a plugin's model. The component supports the following optional features: pagination, links to the record details page, using a model scope for the list filtering. The list can be sorted by any column, but the sorting cannot be changed by website visitors - it's set in the component configuration.

Add this component to a CMS page by dragging it to the page code from the component list and click it to configure its properties:

  • Model class - select a model class you want to use to fetch data from the database.
  • Scope - optional, select the model scope method used to filter the results
  • Scope Value - optional, the value to provide to the selected scope method. URL parameters can be provided in the form of {{ :nameOfParam }}
  • Display column - select the model column to display in the list. It's an autocomplete field that displays columns from the underlying database table. You can enter any value in this field. The value is used in the default component partial, you can customize the component by providing custom markup instead of the default partial.
  • Details page - a drop-down list of CMS pages you want to create links to.
  • Details key column - select a column you want to use as a record identifier in the record links. You can link your records by the primary identifier (id), slug column or any other - it depends on the your database structure.
  • URL parameter name - enter the details page URL parameter name, which takes the record identifier. For example, if the record details page has a URL like "/blog/post/:slug", the URL parameter would be "slug".
  • Records per page - enter a number to enable pagination for the records.
  • Page number - specify the fixed page number or use the external parameter editor to enter a name of the URL parameter which holds the page number. For example - if your record list page URL was "/record-list-test/:page?", the Page number property value would be ":page".
  • Sorting - select a database column name to use for sorting the list.
  • Direction - select whether the sorting should be ascending or descending.

After configuring the component save and preview the page. Most likely you will want to customize the default component markup to output more details about each record.

Record details component

The Record details component loads a model from the database and outputs its details on a page. If the requested record cannot be found, the component outputs the "record not found" message.

Add this component to a CMS page by dragging it to the page code from the component list and click it to configure its properties:

  • Model class - select a model class you want to use to fetch data from the database.
  • Identifier value - specify a fixed value or use the external parameter editor to enter a name of the URL parameter. If the details page had the URL like "/blog/post/:slug", the identifier value would be ":slug".
  • Key column - specify a name of the database table column to use for looking up the record. This is an autocomplete field that displays columns from the underlying database table.
  • Display column - enter a name of the database table column to display on the details page. The value is used in the default component partial, you can customize the component by providing custom markup instead of the default partial.
  • Not found message - a message to display if the record is not found. Used in the default partial.

After configuring the component save and preview the page. You will likely want to customize the default component markup to output more details from the loaded model.

Notes about the autocompletion

Builder updates the Inspector autocompletion fields every time when the underlying data is updated. For example, the “Field name” property of the Form Builder controls is populated with the database table column names. If you update the table structure with Builder, the autocompletion cache updates automatically. However you may need to reopen Inspector so that it can update its editors.

If you edit your plugin files or database structure with an external editor, Builder won’t be able to pick up those changes automatically. You might want to reload the Builder page after you add a database column with an external tool in order to refresh the autocompletion features.

Editing other plugins

Although Builder allows you to edit plugins created by other authors, remember that you do it at your own risk. Plugins could be updated by their authors, which will eliminate your changes or break the plugin. In many cases, if you make updates to plugins developed by another author, you lose any technical support provided by the author.

Adding support for a custom FormWidget

To add a custom widget to the Builder plugin, you must first register a backend form widget for your plugin.

Once it is registered, define a list of properties within your plugin in the Plugin registration class boot() method and register the custom control. For example:

public function boot()
{
    $properties = [
        'max_value' => [
            'title' => 'The maximum allowed',
            'type' => 'builderLocalization',
            'validation' => [
                'required' => [
                    'message' => 'Maxium value is required'
                ]
            ]
        ],
         'mode' => [
            'title' => 'The plugin mode',
            'type' => 'dropdown',
                'options' => [
                    'single' => 'Single',
                    'multiple' => 'Multiple',
                ],
            'ignoreIfEmpty' => true,
        ]
    ];

    Event::listen('pages.builder.registerControls', function($controlLibrary) {
        $controlLibrary->registerControl(
            'yourwidgetname',
            'My Widget',
            'Widget description',
            ControlLibrary::GROUP_WIDGETS,
            'icon-file-image-o',
            $controlLibrary->getStandardProperties([], $properties),
            'Acme\Blog\Classes\ControlDesignTimeProvider'
        );
    });
}

Note: See the getStandardProperties() method in the winter/builder/classes/ControlLibrary.php file for more examples.

Now, we need the ControlDesignTimeProvider class referenced above. Save the following as classes/ControlDesignTimeProvider.php within your plugin's directory (replacing 'yourwidgetname' with what you used in your Plugin registration class boot() method).

<?php namespace Acme\Blog\Classes;

use Winter\Builder\Widgets\DefaultControlDesignTimeProvider;

class ControlDesignTimeProvider extends DefaultControlDesignTimeProvider
{
    public function __construct()
    {
        $this->defaultControlsTypes[] = 'yourwidgetname';
    }
}

Then save the following as class/controldesigntimeprovider/_control-yourwidgetname.htm within your plugin's directory, and customize it how you like. Again, yourwidgetname in the file name must match:

<div class="builder-blueprint-control-text">
    <?= e(trans('acme.blog::lang.mywidget.placeholder')) ?>
</div>

You should now be able to add and configure your custom widget within the Builder plugin just like any other plugin.

wn-builder-plugin's People

Contributors

acasar avatar air-petr avatar alekseybobkov avatar ariponce avatar arvislacis avatar bennothommo avatar blackxel avatar butterz21217 avatar daftspunk avatar datune avatar gergo85 avatar gpasztor87 avatar hammenws avatar host138 avatar iafilin avatar ideepblue avatar luketowers avatar magiczne avatar mjauvin avatar moisessepulveda avatar multiwebinc avatar pgarnek avatar plehatron avatar pvullioud avatar sms-system avatar theservat avatar tleish avatar tobias-kuendig avatar vojtasvoboda avatar webvpf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

wn-builder-plugin's Issues

the models are not displayed

Winter version: Detected a modified version of Winter CMS build 1.1.2
PHP: 8.0.3

Step to reproduce

  • create new plugin
  • create new model(s)
  • the models are not displayed under the models tabs but the file exists under the folder Models

Automatically populate $jsonable field in the model for certain field types

Winter CMS Build

1.1

PHP Version

7.4

Database engine

MySQL/MariaDB

Plugins installed

Winter.Builder,Rainlab.User

Issue description

Within the builder plugin i have created a DB with a column called "settingsO" as "Text" with a length of 65535.
Then in my models for this DB, i went to Forms -> fields.yaml and created a "Checkbox List" with three options.

It does not matter if i choose one, two or all options from within my form in the backend, i always get this error:
"Unexpected type of array when attempting to save attribute "settingsO", try adding it to the $jsonable property." on line 781 of /htdocs/vendor/winter/storm/src/Database/Model.php

Steps to replicate

  1. Create a DB with some tables, one saying something like "mySettings".
  2. Create a Model for said DB.
  3. Add a Form
  4. Add the widget "Checkbox List" to that form and save.
  5. Go to your form in the backend and try to add a new entry.

Workaround

No response

Add database fields error key with not en locale

image

Hi, locale ru ~dev-main

Winter\Builder\Behaviors\IndexModelFormOperations:221

$fieldTypes = array_merge(array_keys($controls['Standard']), array_keys($controls['Widgets']));

Standard and Widgets keys apparently taken from lang file

image

I'm not sure but this might work

$standardKey = \Illuminate\Support\Facades\Lang::get('winter.builder::lang.form.control_group_standard');
$widgetKey = \Illuminate\Support\Facades\Lang::get('winter.builder::lang.form.control_group_widgets');
$fieldTypes = array_merge(array_keys($controls[$standardKey]), array_keys($controls[$widgetKey]));

Error adding permissions

Step to reproduce
Go to permission tabs
Add permission like

conference.event.create | base33.conference::lang.conference.events.event | base33.conference::lang.conference.events.event_create

before save, translations are added in the lang.php file

<?php return [
    'plugin' => [
        'name' => 'Conference',
        'description' => 'Events management plugin',
    ],
    'conference' => [
        'events' => [
            'event' => 'Event',
            'event_create' => 'Create',
        ],
    ],
];

while saving I get this error
Screenshot 2022-03-16 at 20 28 05

and is impossible to save permission

Refresh the database view after migration

When a migration is applied or rolled back in the backend, the list of tables in the Database tab is not updated in real time. A manual refresh needs to be performed to view any changes. I suggest automatically refreshing the view any time a migration is applied or rolled back.

Field search not working

v2.0.6, SQLite.
For one field of type Text in columns.yaml, I set the search capability. As a result, the search is performed on two letters in the second word.

After deleting a column, the table is deleted

Winter 1.2.1, Builder 2.0.6, MySQL 5.7.27, PHP 8.2

I have created a boolean column. Added records using this column. Then he deleted the boolean column, but at the same time the table in which there was a boolean column was deleted.

What else can I do to confirm the mistake and help others fix it?

Error creating dropdown in fields.yaml

When creating fields.yaml
if the field il of type DROPDOWN
when saving, I get this error

Screenshot 2022-03-20 at 16 11 19

stack trace

[2022-03-20 15:11:57] development.ERROR: ErrorException: Undefined array key "multiple" in /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/classes/ModelFormModel.php:103
Stack trace:
#0 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php(231): Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(2, 'Undefined array...', '/Users/francesc...', 103)
#1 /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/classes/ModelFormModel.php(103): Illuminate\Foundation\Bootstrap\HandleExceptions->Illuminate\Foundation\Bootstrap\{closure}(2, 'Undefined array...', '/Users/francesc...', 103)
#2 /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/classes/ModelFormModel.php(57): Winter\Builder\Classes\ModelFormModel->scanJsonableFields(Array, Array)
#3 /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/behaviors/IndexModelFormOperations.php(71): Winter\Builder\Classes\ModelFormModel->getJsonableFields()
#4 [internal function]: Winter\Builder\Behaviors\IndexModelFormOperations->onModelFormSave()
#5 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Extension/ExtendableTrait.php(432): call_user_func_array(Array, Array)
#6 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(184): Backend\Classes\Controller->extendableCall('onModelFormSave', Array)
#7 [internal function]: Backend\Classes\Controller->__call('onModelFormSave', Array)
#8 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(629): call_user_func_array(Array, Array)
#9 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(479): Backend\Classes\Controller->runAjaxHandler('onModelFormSave')
#10 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(277): Backend\Classes\Controller->execAjaxHandlers()
#11 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/BackendController.php(171): Backend\Classes\Controller->run('index', Array)
#12 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): Backend\Classes\BackendController->run('winter/builder')
#13 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/BackendController.php(119): Illuminate\Routing\Controller->callAction('run', Array)
#14 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(45): Backend\Classes\BackendController->callAction('run', Array)
#15 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Route.php(261): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(Backend\Classes\BackendController), 'run')
#16 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Route.php(204): Illuminate\Routing\Route->runController()
#17 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(725): Illuminate\Routing\Route->run()
#18 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\Routing\Router->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#19 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/BackendController.php(68): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#20 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(162): Backend\Classes\BackendController->Backend\Classes\{closure}(Object(Illuminate\Http\Request), Object(Closure))
#21 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(50): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#22 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Routing\Middleware\SubstituteBindings->handle(Object(Illuminate\Http\Request), Object(Closure))
#23 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#24 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#25 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#26 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\Session\Middleware\StartSession->handleStatefulRequest(Object(Illuminate\Http\Request), Object(Illuminate\Session\Store), Object(Closure))
#27 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#28 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#29 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#30 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#31 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
#32 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#33 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(727): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#34 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(702): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#35 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(666): Illuminate\Routing\Router->runRoute(Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route))
#36 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Router/CoreRouter.php(20): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#37 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(167): Winter\Storm\Router\CoreRouter->dispatch(Object(Illuminate\Http\Request))
#38 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}(Object(Illuminate\Http\Request))
#39 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#40 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Foundation/Http/Middleware/CheckForMaintenanceMode.php(25): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle(Object(Illuminate\Http\Request), Object(Closure))
#41 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
#42 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Foundation/Http/Middleware/CheckForTrustedProxies.php(56): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#43 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Foundation\Http\Middleware\CheckForTrustedProxies->handle(Object(Illuminate\Http\Request), Object(Closure))
#44 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Http/Middleware/TrustHosts.php(46): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#45 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Http\Middleware\TrustHosts->handle(Object(Illuminate\Http\Request), Object(Closure))
#46 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#47 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(142): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#48 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(111): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#49 /Users/francesco/Dev/sites/wn-conference/index.php(43): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#50 /Users/francesco/.composer/vendor/laravel/valet/server.php(234): require('/Users/francesc...')
#51 {main}  

``` 

Infinite Scroll request

Please add Infinite scroll option for "Builder records list" component. Pagination is good but Infinite scroll is more user friendly and will increase the time user spend on webpage.

Editing plugin details removes the 'replaces' key from plugin.yaml

If I have the following plugin.yaml file:

# plugin.yaml

plugin:
    name: 'acme.blog::lang.plugin.name'
    description: 'Plugin Description'
    author: 'Author Name'
    icon: wn-icon-chain
    homepage: 'https://example.com'
    replaces:
        Acme.Blog: '<3.0.0'

And I edit the plugin details by clicking on the plugin gear icon and save the changes, the replaces definition is removed from the yaml and results in the following:

# plugin.yaml

plugin:
    name: 'acme.blog::lang.plugin.name'
    description: 'Plugin Description'
    author: 'Author Name'
    icon: wn-icon-chain
    homepage: 'https://example.com'

Cant access to builer page

Hello,

I have installed the module on wintercms version 1.2.1 and php 8.1.17.

I removed cms module from "loadModules" and i set 'backendUri' => '' in config/cms.php,.

When I click on the "builder" menu, I have this error

"We searched and searched but the requested URL just couldn't be found. Perhaps you were looking for something else?

http://127.0.0.1:8000/winter/builder"

Thanks

Error when searching trough database tables

I get this error when using the search table in the database view
now is it impossible to exit from this error

[2022-04-09 21:46:28] development.ERROR: TypeError: mb_strtolower(): Argument #1 ($string) must be of type string, array given in /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Support/Str.php:443
Stack trace:
#0 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Support/Str.php(443): mb_strtolower(Array, 'UTF-8')
#1 /Users/francesco/Dev/sites/wn-conference/modules/backend/Traits/SearchableWidget.php(36): Illuminate\Support\Str::lower(Array)
#2 /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/widgets/DatabaseTableList.php(93): Winter\Builder\Widgets\DatabaseTableList->textMatchesSearch(Array, Array)
#3 /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/widgets/DatabaseTableList.php(117): Winter\Builder\Widgets\DatabaseTableList->getData(Object(Winter\Builder\Classes\PluginVector))
#4 /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/widgets/DatabaseTableList.php(39): Winter\Builder\Widgets\DatabaseTableList->getRenderData()
#5 /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/controllers/index/_sidepanel.htm(11): Winter\Builder\Widgets\DatabaseTableList->render()
#6 /Users/francesco/Dev/sites/wn-conference/modules/system/Traits/ViewMaker.php(246): include('/Users/francesc...')
#7 /Users/francesco/Dev/sites/wn-conference/modules/system/Traits/ViewMaker.php(96): Backend\Classes\Controller->makeFileContents('/Users/francesc...', Array)
#8 /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/controllers/index/index.htm(5): Backend\Classes\Controller->makePartial('_sidepanel.htm')
#9 /Users/francesco/Dev/sites/wn-conference/modules/system/Traits/ViewMaker.php(246): include('/Users/francesc...')
#10 /Users/francesco/Dev/sites/wn-conference/modules/system/Traits/ViewMaker.php(108): Backend\Classes\Controller->makeFileContents('/Users/francesc...')
#11 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(420): Backend\Classes\Controller->makeView('index')
#12 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(297): Backend\Classes\Controller->execPageAction('index', Array)
#13 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/BackendController.php(171): Backend\Classes\Controller->run('index', Array)
#14 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): Backend\Classes\BackendController->run('winter/builder')
#15 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/BackendController.php(119): Illuminate\Routing\Controller->callAction('run', Array)
#16 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(45): Backend\Classes\BackendController->callAction('run', Array)
#17 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Route.php(261): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(Backend\Classes\BackendController), 'run')
#18 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Route.php(204): Illuminate\Routing\Route->runController()
#19 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(725): Illuminate\Routing\Route->run()
#20 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\Routing\Router->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#21 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/BackendController.php(68): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#22 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(162): Backend\Classes\BackendController->Backend\Classes\{closure}(Object(Illuminate\Http\Request), Object(Closure))
#23 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(50): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#24 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Routing\Middleware\SubstituteBindings->handle(Object(Illuminate\Http\Request), Object(Closure))
#25 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#26 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#27 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#28 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\Session\Middleware\StartSession->handleStatefulRequest(Object(Illuminate\Http\Request), Object(Illuminate\Session\Store), Object(Closure))
#29 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#30 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#31 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#32 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#33 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
#34 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#35 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(727): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#36 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(702): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#37 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(666): Illuminate\Routing\Router->runRoute(Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route))
#38 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Router/CoreRouter.php(20): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#39 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(167): Winter\Storm\Router\CoreRouter->dispatch(Object(Illuminate\Http\Request))
#40 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}(Object(Illuminate\Http\Request))
#41 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#42 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Foundation/Http/Middleware/CheckForMaintenanceMode.php(25): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle(Object(Illuminate\Http\Request), Object(Closure))
#43 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
#44 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Foundation/Http/Middleware/CheckForTrustedProxies.php(56): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#45 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Foundation\Http\Middleware\CheckForTrustedProxies->handle(Object(Illuminate\Http\Request), Object(Closure))
#46 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Http/Middleware/TrustHosts.php(46): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#47 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Http\Middleware\TrustHosts->handle(Object(Illuminate\Http\Request), Object(Closure))
#48 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#49 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(142): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#50 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(111): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#51 /Users/francesco/Dev/sites/wn-conference/index.php(43): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#52 /Users/francesco/.composer/vendor/laravel/valet/server.php(234): require('/Users/francesc...')
#53 {main}  

Error when creating fields.yaml

In the backend
try to add fields.yaml and I get this error
Screenshot 2022-03-16 at 19 58 49

Step to reproduce

  • create 2 tables
  • add 1 model, add fields with the new function 'add fields from database' (good function!)
  • try to save and get the error

the fields.yaml is correctly created with this content

fields:
    title:
        label: Title
        span: auto
        type: text
    slug:
        label: Slug
        span: auto
        type: text
    slogan:
        label: Slogan
        span: auto
        type: textarea
    teaser:
        label: Teaser
        span: auto
        type: textarea
    socialtags:
        label: Socialtags
        span: auto
        type: textarea
    dates:
        label: Dates
        span: auto
        type: textarea

Stack trace

[2022-03-16 18:59:38] development.ERROR: TypeError: Winter\Builder\Behaviors\IndexModelFormOperations::updateJsonable(): Argument #1 ($model) must be of type array, null given, called in /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/behaviors/IndexModelFormOperations.php on line 78 and defined in /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/behaviors/IndexModelFormOperations.php:296
Stack trace:
#0 /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/behaviors/IndexModelFormOperations.php(78): Winter\Builder\Behaviors\IndexModelFormOperations->updateJsonable(NULL, Array, Array)
#1 [internal function]: Winter\Builder\Behaviors\IndexModelFormOperations->onModelFormSave()
#2 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Extension/ExtendableTrait.php(432): call_user_func_array(Array, Array)
#3 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(184): Backend\Classes\Controller->extendableCall('onModelFormSave', Array)
#4 [internal function]: Backend\Classes\Controller->__call('onModelFormSave', Array)
#5 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(629): call_user_func_array(Array, Array)
#6 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(479): Backend\Classes\Controller->runAjaxHandler('onModelFormSave')
#7 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(277): Backend\Classes\Controller->execAjaxHandlers()
#8 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/BackendController.php(171): Backend\Classes\Controller->run('index', Array)
#9 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): Backend\Classes\BackendController->run('winter/builder')
#10 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/BackendController.php(119): Illuminate\Routing\Controller->callAction('run', Array)
#11 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(45): Backend\Classes\BackendController->callAction('run', Array)
#12 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Route.php(261): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(Backend\Classes\BackendController), 'run')
#13 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Route.php(204): Illuminate\Routing\Route->runController()
#14 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(725): Illuminate\Routing\Route->run()
#15 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\Routing\Router->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#16 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/BackendController.php(68): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#17 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(162): Backend\Classes\BackendController->Backend\Classes\{closure}(Object(Illuminate\Http\Request), Object(Closure))
#18 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(50): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#19 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Routing\Middleware\SubstituteBindings->handle(Object(Illuminate\Http\Request), Object(Closure))
#20 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#21 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#22 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#23 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\Session\Middleware\StartSession->handleStatefulRequest(Object(Illuminate\Http\Request), Object(Illuminate\Session\Store), Object(Closure))
#24 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#25 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#26 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#27 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#28 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
#29 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#30 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(727): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#31 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(702): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#32 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(666): Illuminate\Routing\Router->runRoute(Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route))
#33 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Router/CoreRouter.php(20): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#34 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(167): Winter\Storm\Router\CoreRouter->dispatch(Object(Illuminate\Http\Request))
#35 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}(Object(Illuminate\Http\Request))
#36 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#37 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Foundation/Http/Middleware/CheckForMaintenanceMode.php(25): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle(Object(Illuminate\Http\Request), Object(Closure))
#38 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
#39 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Foundation/Http/Middleware/CheckForTrustedProxies.php(56): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#40 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Foundation\Http\Middleware\CheckForTrustedProxies->handle(Object(Illuminate\Http\Request), Object(Closure))
#41 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Http/Middleware/TrustHosts.php(46): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#42 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Http\Middleware\TrustHosts->handle(Object(Illuminate\Http\Request), Object(Closure))
#43 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#44 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(142): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#45 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(111): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#46 /Users/francesco/Dev/sites/wn-conference/index.php(43): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#47 /Users/francesco/.composer/vendor/laravel/valet/server.php(234): require('/Users/francesc...')
#48 {main}  
```  

mb_strtolower(): Argument #1 ($string) must be of type string, array given

Summary:

On creating the first new table in a custom plugin, an unhandled error occured.

Installed build and plugins:

Winter CMS Build: 1.2.0
Plugins Installed: Demo, Builder

Reproduce steps:

-create a new plugin and call it 'Menus'
-create a new table 'menus_list'

Expected behavior:
-Save the table
-Go back to Builder page

Actual behavior:

Unhandled Error

mb_strtolower(): Argument #1 ($string) must be of type string, array given
../vendor/laravel/framework/src/Illuminate/Support/Str.php line 474

P.S: I'm new to the CMS so I might be doing something wrong but it was a straight forward thing. Create Plugin->Add new Table->Error

Missing oc-icon-css3 and oc-icon-html5 icons in the dropdown lists

CSS3 and HTML5 icons are not shown next to text value in the dropdown lists:

For example, plugin configuration pop-up:
2021-07-04_11-05
Back-end menu item configuration:
2021-07-04_11-06

Cause of issue can be found at:

This two lines doesn't contain proper second parameter in array, for example, should be 'oc-icon-css3' and 'oc-icon-html5' instead of plain '|'.

If needed then I can create super-simple pull request or maintainers could easily fix this too but maybe there is another cause/reason why these icons are missing?

Navigation menu exception when resetting menu item order

2021-07-04_11-36

Steps to reproduce:

  1. In Builder under your plugin go to the "Backend Menu" configuration section;
  2. Add new or edit existing main menu and set the Order to valid value, for example, 100;
  3. Reset/clear value specified in step 2 to empty value;
  4. Reload page and the most of back-end is not accessible anymore (view exception image).

Cause of this is that when clearing Order value in step 3 then in plugin.yaml file it's stored as order: '' which then throws exception because of https://github.com/wintercms/winter/blob/develop/modules/backend/classes/NavigationManager.php#L121 - because there is no type conversation to int value.

Possible solutions:

  1. Builder menu editor should not save order: '' back into plugin.yaml when parameter value is empty...
  2. https://github.com/wintercms/winter/blob/develop/modules/backend/classes/NavigationManager.php#L121 and similar lines should use type conversation to int value, for example, return (int) $a->order - (int) $b->order;.

Error creating balloons in fields.yaml

When creating fields.yaml
if the field il of type BALLONS
when saving, I get this error (but the yaml is created)
Screenshot 2022-03-20 at 16 19 19

[2022-03-20 15:20:17] development.ERROR: TypeError: Winter\Builder\Behaviors\IndexModelFormOperations::updateJsonable(): Argument #1 ($model) must be of type array, null given, called in /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/behaviors/IndexModelFormOperations.php on line 78 and defined in /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/behaviors/IndexModelFormOperations.php:296
Stack trace:
#0 /Users/francesco/Dev/sites/wn-conference/plugins/winter/builder/behaviors/IndexModelFormOperations.php(78): Winter\Builder\Behaviors\IndexModelFormOperations->updateJsonable(NULL, Array, Array)
#1 [internal function]: Winter\Builder\Behaviors\IndexModelFormOperations->onModelFormSave()
#2 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Extension/ExtendableTrait.php(432): call_user_func_array(Array, Array)
#3 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(184): Backend\Classes\Controller->extendableCall('onModelFormSave', Array)
#4 [internal function]: Backend\Classes\Controller->__call('onModelFormSave', Array)
#5 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(629): call_user_func_array(Array, Array)
#6 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(479): Backend\Classes\Controller->runAjaxHandler('onModelFormSave')
#7 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/Controller.php(277): Backend\Classes\Controller->execAjaxHandlers()
#8 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/BackendController.php(171): Backend\Classes\Controller->run('index', Array)
#9 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): Backend\Classes\BackendController->run('winter/builder')
#10 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/BackendController.php(119): Illuminate\Routing\Controller->callAction('run', Array)
#11 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(45): Backend\Classes\BackendController->callAction('run', Array)
#12 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Route.php(261): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(Backend\Classes\BackendController), 'run')
#13 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Route.php(204): Illuminate\Routing\Route->runController()
#14 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(725): Illuminate\Routing\Route->run()
#15 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\Routing\Router->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#16 /Users/francesco/Dev/sites/wn-conference/modules/backend/Classes/BackendController.php(68): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#17 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(162): Backend\Classes\BackendController->Backend\Classes\{closure}(Object(Illuminate\Http\Request), Object(Closure))
#18 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(50): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#19 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Routing\Middleware\SubstituteBindings->handle(Object(Illuminate\Http\Request), Object(Closure))
#20 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#21 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#22 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#23 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\Session\Middleware\StartSession->handleStatefulRequest(Object(Illuminate\Http\Request), Object(Illuminate\Session\Store), Object(Closure))
#24 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#25 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#26 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#27 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#28 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
#29 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#30 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(727): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#31 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(702): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#32 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Routing/Router.php(666): Illuminate\Routing\Router->runRoute(Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route))
#33 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Router/CoreRouter.php(20): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#34 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(167): Winter\Storm\Router\CoreRouter->dispatch(Object(Illuminate\Http\Request))
#35 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}(Object(Illuminate\Http\Request))
#36 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#37 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Foundation/Http/Middleware/CheckForMaintenanceMode.php(25): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle(Object(Illuminate\Http\Request), Object(Closure))
#38 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
#39 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Foundation/Http/Middleware/CheckForTrustedProxies.php(56): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#40 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Foundation\Http\Middleware\CheckForTrustedProxies->handle(Object(Illuminate\Http\Request), Object(Closure))
#41 /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm/src/Http/Middleware/TrustHosts.php(46): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#42 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Http\Middleware\TrustHosts->handle(Object(Illuminate\Http\Request), Object(Closure))
#43 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#44 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(142): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#45 /Users/francesco/Dev/sites/wn-conference/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(111): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#46 /Users/francesco/Dev/sites/wn-conference/index.php(43): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#47 /Users/francesco/.composer/vendor/laravel/valet/server.php(234): require('/Users/francesc...')
#48 {main}  

($model) must be of type array, null given

After save form from builder. This error.

"Winter\Builder\Behaviors\IndexModelFormOperations::updateJsonable(): Argument #1 ($model) must be of type array, null given, called in /application/plugins/winter/builder/behaviors/IndexModelFormOperations.php on line 78" on line 296 of /application/plugins/winter/builder/behaviors/IndexModelFormOperations.php

IndexModelFormOperations::updateJsonable
image
first param only array

image

image

getJsonable from Winter\Builder\Classes\ModelModel return null from ModelFileParser

Version file %s is not found when try to access migration in subdir

If create migration file with artisan command ./artisan create:migration plugin.code --name "SomeMigration" --table some_table -u then created migration in subdir with dirname as version number.
On the builder plugin if try to open this migration from the list - catching appliaction error about unable to find migration file

Array to String conversion on line 240

PHP 8.0.16 (cli) (built: Mar  3 2022 06:25:06) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.16, Copyright (c) Zend Technologies
with Zend OPcache v8.0.16, Copyright (c), by Zend Technologies
mysql  Ver 8.0.28 for macos12.2 on arm64 (Homebrew)
php artisan winter:version
*** Detecting Winter CMS build...
*** Detected a modified version of Winter CMS build 1.1.8.
Composer version 2.2.8
Composer show winter/storm

name     : winter/storm
descrip. : Winter CMS Storm Library
keywords : cms, storm, winter
versions : * dev-wip/1.2
type     : library
license  : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
homepage : https://wintercms.com
source   : [git] https://github.com/wintercms/storm.git c76f1facb74706d02f3499aceeaf8e7018115bfc
dist     : [zip] https://api.github.com/repos/wintercms/storm/zipball/c76f1facb74706d02f3499aceeaf8e7018115bfc c76f1facb74706d02f3499aceeaf8e7018115bfc
path     : /Users/francesco/Dev/sites/wn-conference/vendor/winter/storm
names    : winter/storm, october/rain

support
source : https://github.com/wintercms/storm/tree/wip/1.2

autoload
files
psr-4
Winter\Storm\ => src/

requires
assetic/framework ~3.0
doctrine/dbal ^2.6
erusev/parsedown-extra ~0.7
ext-ctype *
ext-curl *
ext-dom *
ext-fileinfo *
ext-gd *
ext-json *
ext-libxml *
ext-mbstring *
ext-openssl *
ext-pdo *
ext-zip *
laravel/framework ~9.0
laravel/tinker ^2.7
league/csv ~9.1
nesbot/carbon ^2.0
php ^8.0.2
scssphp/scssphp ~1.0
symfony/yaml ^6.0
twig/twig ~3.0
wikimedia/less.php ~3.0
wikimedia/minify ~2.2

requires (dev)
dms/phpunit-arraysubset-asserts ^0.1.0|^0.2.1
meyfa/phpunit-assert-gd ^2.0.0|^3.0.0
mockery/mockery ^1.4.4
php-parallel-lint/php-parallel-lint ^1.0
phpunit/phpunit ^9.5.8
squizlabs/php_codesniffer 3.*

suggests
ext-PDO_ODBC Required to use databases accessed through ODBC drivers
ext-pdo_dblib Required to use MS SQL Server databases
ext-pdo_mysql Required to use MySQL databases
ext-pdo_pgsql Required to use PostgreSQL databases
ext-pdo_sqlite Required to use SQLite databases

replaces
october/rain self.version

Step to reporduce

#INSTALLATION

  • composer create-project wintercms/winter example.com "dev-wip/1.2"
  • php artisan winter:env (and db config)
  • php artisan winter up
  • composer require --dev winter/wn-builder-plugin

In the Builder plugin

  • Create 2 tables
  • In the Models page click ADD
    and then get the error

Screenshot 2022-03-15 at 23 11 36

Blueprint type before $table, uncomment migration code block, replace create, drop to table and curly brace position

Migration generated without Blueprint type of $table and commented migration code block - why?
Better - place migration code block without comments and with true typing

Replace:

<?php namespace {namespace};

use Schema;
use Winter\Storm\Database\Updates\Migration;

class {className} extends Migration
{
    public function up()
    {
        // Schema::create('{tableNamePrefix}_table', function($table)
        // {
        // });
    }

    public function down()
    {
        // Schema::drop('{tableNamePrefix}_table');
    }
}

To:

<?php namespace {namespace};

use Schema;
use Winter\Storm\Database\Schema\Blueprint;
use Winter\Storm\Database\Updates\Migration;

class {className} extends Migration
{
    public function up()
    {
        Schema::table('{tableNamePrefix}_table', function (Blueprint $table) {

        });
    }

    public function down()
    {
        Schema::table('{tableNamePrefix}_table', function (Blueprint $table) {

        });
    }
}

Long list of permission doesn't scroll

When you create plugin permissions, if the list is very long, it doesn't scroll and therefore you can't see them. If I add them by hand in the plugin.yaml they work but I can't see them.

Error message when trying to create new version with migration

This is the following message I receive when trying to save a version which contains a migration file.

Migration code should define a migration or seeder class. Leave the code field blank if you only want to update the version number.

Here is my migration file:

<?php namespace Radmin\Test\Updates;

use Schema;
use Winter\Storm\Database\Updates\Migration;

class BuilderTableCreateRadminTestSamples extends Migration
{
    public function up()
    {
        Schema::create('radmin_test_samples', function($table)
        {
            $table->engine = 'InnoDB';
            $table->increments('id')->unsigned();
            $table->string('name')->nullable();
            $table->timestamp('created_at')->nullable();
            $table->timestamp('updated_at')->nullable();
            $table->timestamp('deleted_at')->nullable();
        });
    }
    
    public function down()
    {
        Schema::dropIfExists('radmin_test_samples');
    }
}

This migration was generated from the database screen

No matter what contents I enter, it is always considered empty and does not allow me to save.

failed database version upgrade

Winter CMS Build

1.2

PHP Version

8.1

Database engine

PostgreSQL

Plugins installed

Builder

Issue description

I changed the column (e.g. drop) AND change name of table and tried to apply this upgrade to other system.

But i have some view which forbid to apply patch - but the name of table was changed. This shouldn't work like this. All or nothing. If it break - it should be still old name of table.

Steps to replicate

Changed the column (e.g. drop) AND change name of table and tried to apply this upgrade to other system.

Workaround

I have to change manually name of table and apply patch again

Composer install old version

When running composer require winter/wn-builder-plugin composer download the v1.0.27 tag that has the old brand.

RainLab.Builder conflicts

In a new project with no plugin installed, when I install the plugin I get a message:

Some issues have been detected and require attention:
The Winter.Builder plugin replaces RainLab.Builder, please remove RainLab.Builder to ensure there are no conflicts

but the RainLab.Builder plugin is not installed

($model) must be of type array, null given,

Hi,
Winter version 1.2.1
Laravel Framework 9.39.0 - Winter CMS
PHP 8.0.

After I try to save form I get:

TypeError: Winter\Builder\Behaviors\IndexModelFormOperations::updateJsonable(): Argument #1 ($model) must be of type array, null given, called in /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/plugins/winter/builder/behaviors/IndexModelFormOperations.php on line 78 and defined in /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/plugins/winter/builder/behaviors/IndexModelFormOperations.php:296

Full stack trace

TypeError: Winter\Builder\Behaviors\IndexModelFormOperations::updateJsonable(): Argument #1 ($model) must be of type array, null given, called in /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/plugins/winter/builder/behaviors/IndexModelFormOperations.php on line 78 and defined in /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/plugins/winter/builder/behaviors/IndexModelFormOperations.php:296
Stack trace:
#0 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/plugins/winter/builder/behaviors/IndexModelFormOperations.php(78): Winter\Builder\Behaviors\IndexModelFormOperations->updateJsonable(NULL, Array, Array)
#1 [internal function]: Winter\Builder\Behaviors\IndexModelFormOperations->onModelFormSave()
#2 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/winter/storm/src/Extension/ExtendableTrait.php(439): call_user_func_array(Array, Array)
#3 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/modules/backend/classes/Controller.php(184): Backend\Classes\Controller->extendableCall('onModelFormSave', Array)
#4 [internal function]: Backend\Classes\Controller->__call('onModelFormSave', Array)
#5 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/modules/backend/classes/Controller.php(629): call_user_func_array(Array, Array)
#6 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/modules/backend/classes/Controller.php(479): Backend\Classes\Controller->runAjaxHandler('onModelFormSave')
#7 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/modules/backend/classes/Controller.php(277): Backend\Classes\Controller->execAjaxHandlers()
#8 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/modules/backend/classes/BackendController.php(171): Backend\Classes\Controller->run('index', Array)
#9 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(54): Backend\Classes\BackendController->run('winter/builder')
#10 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/modules/backend/classes/BackendController.php(119): Illuminate\Routing\Controller->callAction('run', Array)
#11 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(43): Backend\Classes\BackendController->callAction('run', Array)
#12 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Routing/Route.php(260): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(Backend\Classes\BackendController), 'run')
#13 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Routing/Route.php(205): Illuminate\Routing\Route->runController()
#14 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Routing/Router.php(727): Illuminate\Routing\Route->run()
#15 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\Routing\Router->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
#16 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/modules/backend/classes/BackendController.php(68): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#17 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(162): Backend\Classes\BackendController->Backend\Classes\{closure}(Object(Illuminate\Http\Request), Object(Closure))
#18 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(50): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#19 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Routing\Middleware\SubstituteBindings->handle(Object(Illuminate\Http\Request), Object(Closure))
#20 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#21 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\View\Middleware\ShareErrorsFromSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#22 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(121): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#23 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): Illuminate\Session\Middleware\StartSession->handleStatefulRequest(Object(Illuminate\Http\Request), Object(Illuminate\Session\Store), Object(Closure))
#24 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure))
#25 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#26 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse->handle(Object(Illuminate\Http\Request), Object(Closure))
#27 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(67): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#28 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Illuminate\Cookie\Middleware\EncryptCookies->handle(Object(Illuminate\Http\Request), Object(Closure))
#29 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#30 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Routing/Router.php(728): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#31 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Routing/Router.php(705): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
#32 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Routing/Router.php(669): Illuminate\Routing\Router->runRoute(Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route))
#33 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/winter/storm/src/Router/CoreRouter.php(20): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
#34 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(190): Winter\Storm\Router\CoreRouter->dispatch(Object(Illuminate\Http\Request))
#35 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(141): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}(Object(Illuminate\Http\Request))
#36 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php(86): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#37 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/winter/storm/src/Foundation/Http/Middleware/CheckForMaintenanceMode.php(25): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle(Object(Illuminate\Http\Request), Object(Closure))
#38 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
#39 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/winter/storm/src/Foundation/Http/Middleware/CheckForTrustedProxies.php(56): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#40 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Foundation\Http\Middleware\CheckForTrustedProxies->handle(Object(Illuminate\Http\Request), Object(Closure))
#41 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/winter/storm/src/Http/Middleware/TrustHosts.php(46): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#42 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(180): Winter\Storm\Http\Middleware\TrustHosts->handle(Object(Illuminate\Http\Request), Object(Closure))
#43 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
#44 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(165): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#45 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(134): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
#46 /usr/home/Eternia/domains/eternia.usermd.net/public_html/wprzyczepy/index.php(43): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
#47 {main}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.