Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File Upload forms does not work with Relation Behavior and Pivot Model #1600

Closed
myst6re opened this issue Nov 14, 2015 · 9 comments
Closed

Comments

@myst6re
Copy link
Contributor

myst6re commented Nov 14, 2015

When you add a file upload form in a pivot field in the controller's relation configuration, the attachment is not saved/attached with the pivot model: the image is uploaded, an entry seems to be added in system_files table, but after saving the page, the association between the pivot table and system_files is not correctly saved.

@tschallacka
Copy link
Contributor

+1 I'm encountering the same issue.

owning model RichIndexPage

public $belongsToMany = ['richblock' => ['\ExitControl\RichIndexPageManager\Models\RichBlock',
                                          'key' =>'rich_page_id',
                                            'otherKey'=>'rich_block_id',
                                            'table' => 'rich_block_to_page',
                                            'order' => 'sortorder',
                                            'pivot'=>'sortorder',
                                            'timestamps'=>'true']];

Relation model RichBlock

public $belongsToMany = ['richpage' => ['\ExitControl\RichIndexPageManager\Models\RichIndexPage',
                                          'key' =>'rich_page_id',
                                            'otherKey'=>'rich_block_id',
                                            'table' => 'rich_block_to_page',
                                            'pivot'=>'sortorder',
                                            'timestamps'=>'true']];
public $attachOne = ['image' => ['System\Models\File',]];

@tschallacka
Copy link
Contributor

It has to do with deferred binding messing up, if I add this in
FileUpload.php on line 263 ish

if(strpos($this->alias,'Pivot')){
    $this->getRelationObject()->remove($file);
}
else {
    $this->getRelationObject()->remove($file, $this->sessionKey);
}

then it works ish, although the ajax postback still fails miserably.

So to summarise, the call actually arrives at it's destination, with all proper variables, it finds the relation and gets that, no problems. But the ajax postback doesn't get called, and the deferred binding does not get executed when the final form is saved.

Basically if you click the delete button of an image it will delete it visually, make the deferred binding table entry, but the loading bar will keep loading and the mouse pointer will keep as a loading icon and it will never stop, but neither will it throw an error.

If you try to edit the File details(name and description) and try to save that you get an exception that relationRichblockManagePivotFormImage has not been bound to the controller....

@tschallacka
Copy link
Contributor

I made a dirty workaround to allow me to do both things in the mean time...

in the relation render fields yaml add a partial where you will define your form fields for the pivot data

<div class="form-group  text-field span-full   " data-field-name="subtitle" id="Form-relationRichblockManageForm-field-RichBlock-subtitle-group">
    <!-- Text -->
    <?php
    $pivot = '';
    foreach($this->vars['formModel']->richblock as $block) {
        if($model->getKey() == $block->getKey()) {
            $pivot = $block->pivot->sortorder;
        }
    }
    ?>
    <!-- This one is important to be able to get a reference to your original owner -->
    <input type="hidden" name="RichBlock[pivot][owner]" value="<?= $this->vars['formModel']->getKey(); ?>">
    <!-- You can name this form field any way you want, but I chose for this setup -->
    <input type="text" name="RichBlock[pivot][sortorder]" id="Form-relationRichblockManageForm-field-RichBlock-sortorder" value="<?= $pivot ?>" placeholder="" class="form-control" autocomplete="off" maxlength="255">
</div>

Then in your Model(mine is RichBlock)

public function beforeSave() {
    $post = post('RichBlock');
    // I have only ONE relation field here... you miht have to fiddle around with sending additonal parameters
    // if you have multipe pivots to discern which field/property to find
    if(isset($post['pivot']) && isset($post['pivot']['owner'])) {
        // Ugly ugly ugly...
        $richpage = $this->richpage()->where($this->richpage()->first()->getKeyName(),$post['pivot']['owner'])->first();
        $richpage->pivot->sortorder = $post['pivot']['sortorder'];
        $richpage->pivot->save();
    }
}

@myst6re
Copy link
Contributor Author

myst6re commented Nov 19, 2015

In fact there is two problems by using an attachment in a pivot model:

  • The deferred binding is not committed
  • The method getKey() of the pivot model seems to return null, even after saving the model

For the first problem, you can fix it by specify the session key in the save lines in modules/backend/behaviors/RelationController.php:

public function onRelationManagePivotCreate()
{
    [...]
                foreach ($modelsToSave as $modelToSave) {
                    $modelToSave->save(null, $this->pivotWidget->getSessionKey());
                }
    [...]
}

public function onRelationManagePivotUpdate()
{
    [...]
        foreach ($modelsToSave as $modelToSave) {
            $modelToSave->save(null, $this->pivotWidget->getSessionKey());
        }
    [...]
}

For the second problem, I guess that a pivot model is identified by two ids (the associated models), and not by a main integer. But the system_files table needs an id to identify the model where the file is associated. There is many solutions to this problem, but that is not a simple change:

  • We can create a main identifier for pivot models
  • We can change the system_files table (add a column for pivot table, or using the existing id column that contains a merge between the ids of the pivot table (id_a | id_b << 32), yeah this is ugly)

@myst6re
Copy link
Contributor Author

myst6re commented Nov 19, 2015

Ok, I found a solution to my problem.

The patch above is needed, and you also need to add some attributes to your pivot table:

  • An attribute "id" auto-increment (it implies that the other keys will not be the primary, just unique)
  • An attribute with the name of the attachment (this works for attachOne, I don't know for attachMany). Not that this is a fake attribute, only used to lie to October.

Both attributes must be declared in the schema database and declared pivot attributes in the parent model.

Now the system_files table is correctly filled.

@myst6re
Copy link
Contributor Author

myst6re commented Nov 25, 2015

In the documentation and in #1409 it says deferred binding is not supported for pivot data. But I wonder if my fix is enough to enable deferred binding, it seems to work, no?

@daftspunk
Copy link
Member

Fixed by #1641

@mihailbishkek
Copy link

I can't attach file in pivot relation Manager. How I can do it?

@daftspunk
Copy link
Member

I can't attach file in pivot relation Manager. How I can do it?

Pivot models do not use a primary key and are therefore not compatible with system files or deferred binding so cannot be used with the fileupload widget. As an alternative, try using the mediafinder widget instead.

@octobercms octobercms deleted a comment from LukeTowers Sep 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

4 participants