XF 2.0 Using attachments in add-on

AndrewSimm

Well-known member
I am creating an articles add-on that allows someone with permission to promote a post by clicking a link on the post (similar to the demo addon). Once the link is clicked an overlay loads where the title, date, section, and preview can be changed or added. I have everything working except adding an attachment.

My first question is around the entity. I am not extending anything, The article table stands on its own. What do I need to put into the entity and why does the existing article entity not work?

My second question is what would go in $article in step 4 below? When the form loads the article has yet to be created, so there is no key that I can enter. What I do grab is the thread_id and post_id and insert those into the articles table after the form is submitted.


1) Enter input into the template
Code:
<xf:macro template="helper_attach_upload" name="upload" arg-attachmentData="{$attachmentData}" />

2) Create an entity

3) Create a attachment_handler_class under development -> content_types

Content type: article
Field: attachment_handler_class
Value: Andrew\Articles\Attachment\Article
Add-on: [Andrew] Articles

4) Add the below code to your controller that will display the attachment upload button

Code:
 /** @var \XF\Repository\Attachment $attachmentRepo */
    $attachmentRepo = $this->repository('XF:Attachment');
    $attachmentData = $attachmentRepo->getEditorData('article', $article);

5) Add the below code to your controller where you save the form

Code:
 /** @var \XF\Service\Attachment\Preparer $inserter */
    $inserter = $this->service('XF:Attachment\Preparer');
    $associated = $inserter->associateAttachmentsWithContent($this->filter('attachment_hash'), 'article', $article->article_id);
    if ($associated)
    {
        $article->fastUpdate('attach_count', $article->attach_count + $associated);
    }
 
I know I'm answering this in the way I HATE it when people answer my questions in the same way... but...

Is there a reason you are using the attachment system for this? I use the attachment system in my XenCarta addon because the images are embedded into the page, with the attachment slider/viewer and are expected to be shared among the forums.

But for an article system, what reason is there to use the attachment system. If you're uploading an image as a header for your article, then that header shouldn't be expected to be exportable into the built in attachment system. Why not just reference your own internal data entity? For instance, in my XenPorta addon, it gives you the option to upload images for the feature slider... there are not part of the attachment system.
 
But... this is how I pull up associated attachments in XenCarta:
Code:
        $attachments = $this->finder('XF:Attachment')
            ->where('content_type', 'ewr_carta_page')
            ->where('content_id', $wiki->page_id)
            ->order('attach_date')
            ->fetch();
      
        $wiki->hydrateRelation('Attachments', \XF::em()->getBasicCollection($attachments->toArray()));

After doing this, any ATTACH bb-codes will be processed... and of course, you can put the attachment gallery in your template with:
Code:
                <xf:macro template="message_macros" name="attachments"
                    arg-attachments="{$wiki.Attachments}"
                    arg-message="{$wiki}"
                    arg-canView="{{ true }}" />

Of course, I create the page entity BEFORE I allow attachments to be uploaded. Doing them at the same time would require a Service handler like how posts do it.
 
And oh yes, don't forget to add an attachment relation to your entity:
Code:
        $structure->relations = [
            'Attachments' => [
                'entity' => 'XF:Attachment',
                'type' => self::TO_MANY,
                'conditions' => [
                    ['content_type', '=', 'ewr_carta_page'],
                    ['content_id', '=', '$page_id']
                ],
                'with' => 'Data',
                'order' => 'attach_date'
            ],
        ];

And you may need special functions in your entity, but I cant remember:
Code:
    public function canViewAttachments(&$error = null)
    {
        $visitor = \XF::visitor();
        
        return ($visitor->hasPermission('EWRcarta', 'viewAttachments'));
    }
    
    public function canUploadAndManageAttachments()
    {
        $visitor = \XF::visitor();

        return ($visitor->user_id && $visitor->hasPermission('EWRcarta', 'manageAttachments'));
    }

    public function isAttachmentEmbedded($attachmentId)
    {
        if (!$this->page_embed)
        {
            return false;
        }

        if ($attachmentId instanceof \XF\Entity\Attachment)
        {
            $attachmentId = $attachmentId->attachment_id;
        }

        return in_array($attachmentId, $this->page_embed);
    }
    
    public function getBbCodeRenderOptions($context, $type)
    {
        return [
            'entity' => $this,
            'attachments' => $this->Attachments,
            'viewAttachments' => $this->canViewAttachments(),
        ];
    }
 
I know I'm answering this in the way I HATE it when people answer my questions in the same way... but...

Is there a reason you are using the attachment system for this? I use the attachment system in my XenCarta addon because the images are embedded into the page, with the attachment slider/viewer and are expected to be shared among the forums.

But for an article system, what reason is there to use the attachment system. If you're uploading an image as a header for your article, then that header shouldn't be expected to be exportable into the built in attachment system. Why not just reference your own internal data entity? For instance, in my XenPorta addon, it gives you the option to upload images for the feature slider... there are not part of the attachment system.

I put together a quick article system when XF2 came out (https://www.canesinsight.com) and it works well. I've read that using the attachment system is more secure and wanted to make an add-on that I could share with others and was safe. Only users with permission would be able to post articles.
 
But for an article system, what reason is there to use the attachment system. If you're uploading an image as a header for your article, then that header shouldn't be expected to be exportable into the built in attachment system. Why not just reference your own internal data entity? For instance, in my XenPorta addon, it gives you the option to upload images for the feature slider... there are not part of the attachment system.
(I totally realize this is an old thread but my question is very relevant so hope no one minds the bump.)

I found this thread by trying to figure out how best to handle allowing images to be uploaded to a custom entity (similar to an article) for my addon which has a 1:1 relationship to a thread to allow members to post comments about it and I am curious why you wouldn't want to hook into the existing XF attachment mechanics.

Because I am thinking I don't want to have to write all the logic needed to process uploads and figure out how to store it in db/disk and I was able to re-use all the macros like helper_attach_upload and the mechanics of it works. But I do feel somewhat bounded by the conditions in XF's attachments system but then it feels like it'll take me more work/time to create a custom one for my addon.

@Jaxel so I'm curious if I am misunderstanding what you are suggesting with the above or it's simpler than how I'm thinking it is?

Thanks!
 
Top Bottom