Jump to content

Developer Documentation

core/EditorLocations

What it is

An EditorLocations extension allows your application to define a location that an editor instance may be used in. This is important for multiple reasons:

  • An administrator may want to allow certain editor buttons to be available in some areas but not others
  • You may want to allow HTML to be used in some editors but not others, independent of group permissions
  • You may want to allow the administrator to control whether attachments can be uploaded in some editors
  • An EditorLocations extension is necessary to properly map where attachment files are being used

How to use

The extension has several required methods, and a few optional methods that you can define. You will also then need to pass this extension classname to your editor form helper instances later.

    /**
     * Can we use HTML in this editor?
     *
     * @param    \IPS\Member    $member    The member
     * @return    bool|null    NULL will cause the default value (based on the member's permissions) to be used, and is recommended in most cases. A boolean value will override that.
     */
    public function canUseHtml( $member )
    {
        return NULL;
    }

The canUseHtml() method is used to determine if a member can post HTML in the editor instance. Typically you will want to return NULL to let the software determine automatically if the member has permission to post HTML, however in some instances you may wish to explicitly enable or disable the ability to use HTML in an editor.

    /**
     * Can we use attachments in this editor?
     *
     * @param    \IPS\Member                    $member    The member
     * @param    \IPS\Helpers\Form\Editor    $field    The editor field
     * @return    bool|null    NULL will cause the default value (based on the member's permissions) to be used, and is recommended in most cases. A boolean value will override that.
     */
    public function canAttach( $member, $field )
    {
        return NULL;
    }

The canAttach() method determines if the user can upload attachments to this editor. You may wish to explicitly disable attachments in specific editors (e.g. if you provide a separate image upload field, in order to prevent confusion), in which case you can return FALSE from this method (or TRUE to explicitly enable attachments). NULL will allow the Invision Community software to determine automatically if the member has permission to upload attachments.

    /**
     * Permission check for attachments
     *
     * @param    \IPS\Member    $member    The member
     * @param    int|null    $id1    Primary ID
     * @param    int|null    $id2    Secondary ID
     * @param    string|null    $id3    Arbitrary data
     * @param    array        $attachment    The attachment data
     * @return    bool
     */
    public function attachmentPermissionCheck( $member, $id1, $id2, $id3, $attachment )
    {
        return TRUE;
    }

The attachmentPermissionCheck() is passed the $member being checked against, the ID values stored with the attachment, and the attachment data itself, and expects a boolean response to indicate if the member has permission to view the attachment. For private messages, for example, we need to verify if the member is a party to the conversation before permitting them to access the attachment, while for reports in the report center we need to verify the member can access reports before showing them the attachment.

    /**
     * Attachment lookup
     *
     * @param    int|null    $id1    Primary ID
     * @param    int|null    $id2    Secondary ID
     * @param    string|null    $id3    Arbitrary data
     * @return    \IPS\Http\Url|\IPS\Content|\IPS\Node\Model
     * @throws    \LogicException
     */
    public function attachmentLookup( $id1, $id2, $id3 )
    {
        // ....
    }

The attachmentLookup() method is passed the ID values stored with the attachment and expects, in turn, an instance of \IPS\Http\Url, \IPS\Content or \IPS\Node\Model to be returned. The method is designed to accept some data about an attachment and then return the content that the attachment is attached to. The method is designed to throw a LogicException, so you can call load() against a content item without attempting to catch it. e.g. return \IPS\myapp\ContentItem::load( $id1 ); If the content item does not exist, an exception will be thrown automatically.

    /**
     * Rebuild content post-upgrade
     *
     * @param    int|null    $offset    Offset to start from
     * @param    int|null    $max    Maximum to parse
     * @return    int            Number completed
     * @note    This method is optional and will only be called if it exists
     */
    public function rebuildContent( $offset, $max )
    {
        return $this->performRebuild( $offset, $max, array( 'IPS\Text\LegacyParser', 'parseStatic' ) );
    }

When a user upgrades to 4.x or higher, all content previously stored must be rebuilt. The rebuildContent() method allows you to control how your legacy content is rebuilt. Most extensions define a central performRebuild() method as you see here (outlined later in this article), so if you do the same you can likely copy the method above verbatim.

    /**
     * Rebuild attachment images in non-content item areas
     *
     * @param    int|null    $offset    Offset to start from
     * @param    int|null    $max    Maximum to parse
     * @return    int            Number completed
     */
    public function rebuildAttachmentImages( $offset, $max )
    {
        return $this->performRebuild( $offset, $max, array( 'IPS\Text\Parser', 'rebuildAttachmentUrls' ) );
    }

When a user upgrades to 4.x or higher, attachments in non-content areas need to rebuilt. The rebuildAttachmentImages() method allows you control how this occurs, however most extensions define a central performRebuild() method (outlined later) and if you do the same you can likely copy this method verbatim.

    /**
     * Rebuild content to add or remove image proxy
     *
     * @param    int|null        $offset        Offset to start from
     * @param    int|null        $max        Maximum to parse
     * @param    bool            $status        Enable/Disable Image Proxy
     * @return    int            Number completed
     * @note    This method is optional and will only be called if it exists
     */
    public function rebuildImageProxy( $offset, $max, $status=TRUE )
    {
        return $this->performRebuild( $offset, $max, array( 'IPS\Text\Parser', 'parseImageProxy' ) );
    }

When toggling the image proxy feature on and off in the AdminCP, the administrator is afforded an opportunity to rebuild their existing URLs. The rebuildImageProxy() method allows you to define how this occurs. As with the previously described two methods, most extensions use a centralized performRebuild() method for this purpose.

    /**
     * Total content count to be used in progress indicator
     *
     * @return    int            Total Count
     */
    public function contentCount()
    {
        return X;
    }

When content is being rebuilt through one of the previously described operations, the total number of content to be rebuilt is needed in order to ensure we show an accurate progress indicator. Most times, this method simply selects a count from a database table.

    /**
     * Perform rebuild - abstracted as the call for rebuildContent() and rebuildAttachmentImages() is nearly identical
     *
     * @param    int|null    $offset        Offset to start from
     * @param    int|null    $max        Maximum to parse
     * @param    callable    $callback    Method to call to rebuild content
     * @return    int            Number completed
     */
    protected function performRebuild( $offset, $max, $callback )
    {
        // Execute here...
    }

While this method is not part of the extension definition, most extensions process rebuilding attachment URLs, older content and proxy image rebuilds sufficiently similar that the extension defines one central method that the other methods simply call to. Generally when used, this method loops over the content records (i.e. by looping over records in a database table, using the $offset and $max values as the  LIMIT offsets for the database query), and then passes the content to the callback that was specified. It is important to catch any InvalidArgument exceptions that may be thrown, as old content can be unpredictable and may contain formatting issues that cause exceptions to be thrown when we attempt to rebuild it.

The rebuilt content should then be stored back in the database by updating the record that is being processed. Finally, the number of records completed should be returned (when 0 is returned, the rebuild process is considered completed).

Specifying the EditorLocations extension to use

The final step to using this extension is to define it when you create an Editor form helper instance.

$form->add( new \IPS\Helpers\Form\Editor( 'content', NULL, TRUE, array( 'app' => 'core', 'key' => 'ExtensionKey', 'autoSaveKey' => '...' ) ) );

Here, the editor instance will look for an EditorLocations key named "ExtensionKey" in the core application. The methods outlined above will then affect the behavior of the editor as previously noted.


  Report Document


×
×
  • Create New...