Error Following Add-On Block Controller.php Validation Function

Permalink
I am building an Add-On for concrete5.8.1.0 and preparing it for submission. I had gone through 95%+ of the checklist items for submission and everything was working well until I revisited the validation function.

The validation works correctly if the block has never been saved. It displays a small dialog with the error message. After fixing the problem(s) and clicking on the Save button it saves fine.

But if the block has already been saved and a validation error occurs, it again displays the validation error message fine, which I then fix, but it then fails with a fatal exception error when I press the save button.

Log Error:
"Exception Occurred: /home/*****/public_html/concrete/controllers/backend/user_interface/block.php:85 Call to a member function getBlockTypeHandle() on null (1)"

Here are lines 84 and 85 of /concrete/controllers/backend/user_interface/block.php :

$b = \Block::getByID($_REQUEST['bID'], $nvc, $ax); 
if ($b->getBlockTypeHandle() == BLOCK_HANDLE_SCRAPBOOK_PROXY) {


I am using the standard validation function:

public function validate($args)
{
    $error = Core::make('helper/validation/error');
    $groupTitle = $args['agGroupTitle'];
    if (($groupTitle == null) || (trim($groupTitle) === "")) {
        $error->add(t('Group Title is missing on the Options Tab.'));
    }
    // other validations follow and they all work also…
    return $error;
}


public function save($args) in the add-on controller.php never gets called when the exception occurs. Other than when the validation function returns an error the save function always works fine.

After the error occurs it appears the database gets corrupted if I save the changes so I always “Discard Changes” after the error in order to keep working on the problem. I have reinstalled a clean database on several occasions but the problem persists.

Can anyone help me figure out what’s causing this?

jfhencken
 
MrKDilkington replied on at Permalink Reply
MrKDilkington
Hi jfhencken,

Have you tried testing the block on a fresh install without any other custom code, blocks, or themes?

Another option would be sending the code to someone for testing along with the specific steps to reproduce the issue.
JohntheFish replied on at Permalink Reply
JohntheFish
The cause of this type of problem is often further back in the flow, perhaps in the way the block controller is set up and the add/edit methods.
jfhencken replied on at Permalink Reply
jfhencken
MrKDilkington and JohntheFish,
Thank you so much for taking time to help out on this issue. I am currently in the process of looking for the source of the problem based upon both of your suggestions. I will report back with my findings...
jfhencken replied on at Permalink Reply
jfhencken
MrKDikington and JohntheFish,
Thank you for taking the time to help me on this issue.
I tried a fresh install using just the built-in Elemental theme. I created a new blank page and made sure to install my add-on as the only block manually added to the page. I get the same results – when I edit the already saved and published block to force a validation error the exception pops up after (1) the function validation($args) is called, (2) the problem is fixed and (3) I click Save a second time.
I had considered that I could do as much validation as possible with the built in form widgets validation and bypass the validation method but then I would just be working around a bug that needs to be dealt with.
I also took a close look at JohntheFish’s suggestion that the problem could be related to the add/edit methods. I tried commenting out any questionable code with no success. My add-on’s add/edit methods are almost identical to the built-in Image Slider add/edit methods. Here are the main methods in my add-on:
public function add()
{
    // nothing here
}
public function edit()
{
    $db = Database::get();
    $query = $db->GetAll('SELECT * from btXXXXXXItems WHERE bID = ? ORDER BY sortOrder', array($this->bID));
    $this->set('rows', $query);
}
public function getEntries()
{
    $db = Database::get();
    $r = $db->GetAll('SELECT * from btXXXXXXItems WHERE bID = ? ORDER BY sortOrder', array($this->bID));
    $rows = array();

Following the example of the built-in c5.8.1.0 image_slider the add.php and the edit.php files both contain:
<?php
defined('C5_EXECUTE') or die("Access Denied.");
$this->inc('form_setup_html.php');

MrKDikington, perhaps it is time to take you up on your suggestion to have someone more knowledgeable than myself take a look at my add-on package. How would I go about finding such a person?
JohntheFish replied on at Permalink Reply
JohntheFish
Looks like you are manipulating a secondary table for a list of items.
bID changes each time a block is edited, so the association with the secondary table is lost.

Look for examples in core blocks that us ethe duplicate() method.
JohntheFish replied on at Permalink Reply
JohntheFish
An alternate approach is to serialise the data and keep ,it in the blocks primary table

https://legacy-documentation.concrete5.org/tutorials/save-and-retrie...
jfhencken replied on at Permalink Reply
jfhencken
JohntheFish,
Thanks for your feedback. I do use the duplicate() method. I modeled my add-on after the concrete5.8 image_slider and I use most of the methods as they are implemented in that block, but I did not implement the FileTrackableInterface or the AggregateTracker.
Here is my duplicate() method:
public function duplicate($newBID)
{
    parent::duplicate($newBID);
    $db = Database::get();
    $v = array($this->bID);
    $q = 'select * from btXXXXXXItems where bID = ?';
    $r = $db->query($q, $v);
    while ($row = $r->FetchRow()) {
        $db->execute('INSERT INTO btXXXXXXItems (bID, sortOrder, aiT, aiD, aiOC, aiPC) values(?,?,?,?,?,?)',
            array(
                $newBID,
                $row['sortOrder'],
                $row['aiT'],
                $row['aiD'],
                $row['aiOC'],

Any other reasons you can think of that would cause the exception to occur?
jfhencken replied on at Permalink Reply
jfhencken
I found out partially why I have the error.
I added an Image Slider block to a page and found out that the only fields that are validated in the validate() method are also pre-validated on the front end by the form widget. Therefore the validate() method is NEVER called in the built in Image Slider block. When I changed the “min” value of the Slide Duration form widget from 1 to 0 in form_setup_html.php it allowed me to enter a 0 which in turn called the validate() method. The validate() method opened an error dialog. I fixed the problem and resaved the block. That caused the same exception to happen in the image_slider block that I am getting in my add-on block.
Should I report this as a bug in the Concrete5.8.1.0 release?
JohntheFish replied on at Permalink Reply
JohntheFish
If you can document it in a repeatable way, open an issue on github. Issues get more attention than the bug tracker does.
jfhencken replied on at Permalink Reply
jfhencken
Opening an issue on GitHub says:

*Check these before submitting new issues*
- [X ] this is not a question
Questions should be submitted tohttps://www.concrete5.org/community/forums...
- [ ] this is an issue that I tested with the development version of GitHub
Bugs of stable releases should be submitted tohttps://www.concrete5.org/developers/bugs/...
- [X ] I describe all the steps to show how to replicate the bug
If all the above conditions are met, feel free to delete this whole message and to submit your issue with as much details as you can.

Since my issue is NOT "an issue that I tested with the development version of GitHub" and "Bugs of stable releases should be submitted tohttps://www.concrete5.org/developers/bugs/"... is there another GitHub place I should submit this to or should I just ignore the second condition?
vr5 replied on at Permalink Reply
vr5
I have the same error on C5.8.2.1