Content Builder Publicator

The publicator can be used as a content builder to not only format text and upload images, but also to add videos, quotes, and headers to your content.

Table for the builder

To work with the Publicator component, you only need to create two fields of type TEXT in the object table (for example, publications):

CREATE TABLE `bff_test_posts` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT, -- Object (publication) ID
  `content` longtext NOT NULL,                   -- Publication content
  `content_search` longtext NOT NULL,            -- Search field for text content
  -- Other fields
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Component Settings and Initialization

By default, the content of the Publicator component is multilingual. You can also specify allowed types of content blocks and other component settings. Let's consider an example of such settings:

/**
 * Content builder settings
 * @return array
 */
public function publicatorSettings()
{
    $aSettings = array(
        'title' => false,
        'langs' => $this->locale->getLanguages(),            # List of used languages
        'images_path' => \bff::path('posts', 'images'),      # Path to the publicator images folder; replace 'posts' with the module (addon) name for working with objects
        'images_path_tmp' => \bff::path('tmp', 'images'),    # Path to the temporary image storage folder
        'images_url' => \bff::url('posts', 'images'),
        'images_url_tmp' => \bff::url('tmp', 'images'),
        # Gallery parameters                                   # Gallery settings
        'gallery_sz_view' => array(
            'width' => 750,
            'height' => false,
            'vertical' => array('width' => false, 'height' => 640),
            'quality' => 95,
            'sharp' => array()
        ), 
        # Video parameters                                     # Video settings
        'video_width'  => 330,
        'video_height' => 240,
    );
    
    return $aSettings;
}

Be sure to create a folder to store images and then specify the path to it. In the settings, specify the path using bff::path(module_name, folder_title), where images will be stored, and the URL to retrieve them using bff::url(module_name, folder_title). Also, specify the characteristics of the blocks, such as the width of the gallery images and the video block.

We initialize the Publicator component $publicatorComponent by specifying the constructor settings.

/**
 * Initializes the \bff\db\Publicator component
 * @return \bff\db\Publicator the component
 */
public function initPublicator()
{
    $aSettings = $this->publicatorSettings();
    # Connect the content constructor
    $publicatorComponent = $this->attachComponent('publicator', new \bff\db\Publicator($this->module_name, $aSettings));
    return $publicatorComponent;
}

Using the object in the admin panel

You can find a detailed process of using this component in forms in this article.

Displaying content from the constructor

After adding content, there is a need to display it. Let's consider an example of displaying content on a publication page.

In the method responsible for rendering the publication page on the frontend, we prepare the constructor data from the 'content' field of the database table, which is saved in the admin panel. We use the view(data, record_id, template, template_dir) method of the Publicator component to prepare the data, where the parameters are:

  • the publisher's data saved in the content field
  • the object ID (publication)
  • the rendering template
  • the path to the template directory
$publicatorComponent = $this->initPublicator();
$content = $publicatorComponent->view($item['content'], $item['id'], 'view.content', $this->module_dir_tpl);

The template for rendering the publisher's content may look like this:

 <?php
 
 use \bff\db\Publicator;
 
 if( ! empty($aData['b']))
 {
     $galleryIndex = 0;
     foreach($aData['b'] as $v)
     {
         switch($v['type'])
         {
             case Publicator::blockTypeSubtitle: # block "Subtitle" h2, h3 ...
             {
                 $size = 'h'.$v['size'];
                 ?><div class="block block-subtitle"><<?= $size ?>><?= $v['text'][LNG]; ?></<?= $size ?>></div><?
             } break;
             case Publicator::blockTypeText: # block "Text"
             {
                 ?><div class="block block-text"><?= $v['text'][LNG]; ?></div><?
             } break;
             case Publicator::blockTypePhoto: # block "Photo"
             {
                 ?><div class="faq-help-img">
                     <img src="<?= $v['url'][Publicator::szView]; ?>" alt="<?= $v['alt'][LNG] ?>" />
                     <?= ( ! empty($v['text'][LNG]) ? '<div>'.$v['text'][LNG].'</div>' : ''); ?>
                   </div><?
             } break;
             case Publicator::blockTypeGallery: # block "Photo Gallery"
             {
                 $galleryIndex++;
                 ?><div class="txt-gallery">
                     <div class="fotorama" id="imageGallery<?= $galleryIndex ?>" data-auto="false">
                     <? foreach($v['p'] as $gp) { ?>
                         <a href="<?= ($gp['url'][Publicator::szView]) ?>" data-thumb="<?= ($gp['url'][Publicator::szThumbnail]) ?>" data-caption="<?= $gp['alt'][LNG] ?>" alt="<?= $gp['alt'][LNG] ?>"></a>
                     <? } ?>
                     </div>
                   </div>
                   <script type="text/javascript">
                     <? js::start(); ?>
                     $(function(){
                         $('#imageGallery<?= $galleryIndex ?>').fotorama({
                           width: '100%', maxwidth: '100%', maxheight: 640,
                           allowfullscreen: false,
                           thumbmargin: 10,
                           thumbborderwidth: 1,
                           ratio: 750/640,
                           nav: 'thumbs', fit: 'contain',
                           keyboard: true,
                           loop: true, click: true, swipe: true
                         });
                     });
                     <? js::stop(); ?>
                   </script>
                 <?
             } break;
             case Publicator::blockTypeVideo: # block "Video"
             {
                 ?><div class="block block-video">
                     <object width="<?= $this->sett['video_width']; ?>" height="<?= $this->sett['video_height']; ?>">
                         <param name="allowfullscreen" value="true" />
                         <param name="allowscriptaccess" value="always" />
                         <param name="wmode" value="transparent" />
                         <param name="movie" value="<?= $v['video']; ?>" />
                         <embed src="<?= $v['video']; ?>" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" wmode="transparent" width="<?= $this->sett['video_width']; ?>" height="<?= $this->sett['video_height']; ?>"></embed>
                     </object>
                   </div><?
             } break;
         }
     }
 
     if( $galleryIndex > 0 ) {
         # javascript for "Photo Gallery" block
         tpl::includeJS(array('fotorama/fotorama'), false);
         tpl::includeCSS('/js/fotorama/fotorama', false);
     }
 } 
?>