1

I am working on a student management system.
How can I add extra select field (e.g. select user, select class.) to com_content, so that I can assign the article to the specific student (e.g. mark-sheet) and the parent can also see his child student data (mark-sheet)?

I have created user groups and access levels for all classes. For example a student log-in and can see his result but cannot see any other student's result, and same works for parent.

2

This article shows you how to do that http://magazine.joomla.org/issues/issue-dec-2014/item/2402-adding-fields-to-com-content-the-smart-way & https://github.com/katalystsol/plg_content_ksextras

Basically it involves create a custom cotent plugin that hooks into Joomla's onContentPrepareForm() and onContentPrepareData() methods.

here's a copy of the plugin's code

<?php
/**
 * @copyright Copyright 2014 Katalyst Solutions, LLC. All Rights Reserved.
 * @license    GNU General Public License version 2 or later;
 */

defined('_JEXEC') or die;
jimport('joomla.plugin.plugin');

/**
 * This is a custom testimonial plugin class to add additional fields to com_content to allow it to be used for reviews/testimonials 
 * and output the data using schema.org/Review. It will add an additional tab called Testimonial
 */
class plgContentKSExtras extends JPlugin
{
    /** var string Name of the plugin */
    protected $plg_name;

    /** var array List of fields to look for in the $attribs */
    protected $ksfields;

    /** var string The organization name */
    protected $organization;

    /** var string Organization Type used for Schema.org */
    protected $organization_type;

    /** var string Category */
    protected $category;

    /** var boolean Limit plugin to selected category */
    protected $limit_to_category;

    /** var boolean Include child categories */
    protected $include_child_categories;

    public function __construct(& $subject, $config)
    {
        // We only want to use this with com_content
        $jinput = JFactory::getApplication()->input;
        $option = $jinput->get('option');
        if ($option <> 'com_content')
        {
            return true;
        }

        parent::__construct($subject, $config);

        $this->plg_name                 = 'ksextras';
        $this->ksfields                 = $this->setKSFields();

        // Get the plugin parameters
        $this->organization             = $this->params->get('organization');
        $this->organization_type        = $this->params->get('organization_type');
        $this->category                 = $this->params->get('category');
        $this->limit_to_category        = $this->params->get('limit_to_category');
        $this->include_child_categories = $this->params->get('include_child_categories');

        // Load the language file for the plugin
        $this->loadLanguage();
    }

    /**
     * Set the values for the ksfields array
     * These should correspond to the fields in extras/testimonial.xml
     * These should not use the same name as any com_content attribs fields
     *
     * @return array
     */
    protected function setKSFields()
    {
        $ksfields = array (
            'testimonial_by',
            'author_job_title',
            'author_affiliation',
            'rating',
            'author_address',
            'author_locality',
            'author_region',
            'author_postal_code',
            'author_url',
        );

        return $ksfields;
    }

    /**
     * Prepare the form to add to the article edit
     *
     * @param object $form
     * @param object $data
     *
     * @return bool
     */
    public function onContentPrepareForm($form, $data)
    {
        // If the category id is set, then check if the plugin should be limited to a specific category
        if (!empty($data->catid))
        {
            $this->getChildCategories($data->catid);
            if ($this->limit_to_category && !$this->checkCategory($data->catid))
            {
                return true;
            }
        }

        if (!($form instanceof JForm))
        {
            $this->_subject->setError('JERROR_NOT_A_FORM');
            return false;
        }

        // Check that we are manipulating a valid form
        $name = $form->getName();

        if (!in_array($name, array('com_content.article')))
        {
            return true;
        }

        // Add the extra fields to the form
        JForm::addFormPath(dirname(__FILE__) . '/extras');
        $form->loadFile('testimonial', false);

        // Load the data from table into the form
        $articleId = isset($data->id) ? $data->id : 0;

        // If there is already an $articleId, then the article is in edit mode 
        // and we need to retrieve the data from the database
        if ($articleId)
        {
            // Load the data from the database
            $db = JFactory::getDbo();
            $query = $db->getQuery(true);
            $query->select('article_id, data');
            $query->from('#__content_ksextras');
            $query->where('article_id = '.$db->Quote($articleId));
            $db->setQuery($query);

            $attribs = $db->loadObject();

            // Check for a database error.
            if ($db->getErrorNum())
            {
                $this->_subject->setError($db->getErrorMsg());
                return false;
            }

            // json_decode the data
            if (!empty($attribs->data))
            {
                $ksdata = json_decode(json_decode($attribs->data));
            }
        }

        // fill in the form with data
        if(isset($attribs))
        {
            foreach ($this->ksfields as $ksfield)
            {
                $data->attribs[$ksfield] = isset($ksdata->$ksfield) ? $ksdata->$ksfield : '';
            }
        }

        return true;
    }

    /**
     * Runs on content preparation.
     * Called after the data for a JForm has been retrieved.
     *
     * @param   string  $context    The context for the data
     * @param   object  $data       An object containing the data for the form.
     *
     * @return boolean
     */
    public function onContentPrepareData($context, $data)
    {
        if (is_object($data))
        {
            $articleId = isset($data->id) ? $data->id : 0;

            if ($articleId > 0)
            {
                // Load the data from the database
                $db = JFactory::getDbo();
                $query = $db->getQuery(true);
                $query->select('data');
                $query->from('#__content_ksextras');
                $query->where('article_id = '.$db->Quote($articleId));
                $db->setQuery($query);
                $results = $db->loadObject();

                // Check for a database error
                if ($db->getErrorNum())
                {
                    $this->_subject->setError($db->getErrorMsg());
                    return false;
                }

                $ksdata = (count($results)) ? json_decode(json_decode($results->data)) : new stdClass;

                // Merge the data
                $data->attribs = array();

                foreach ($this->ksfields as $ksfield)
                {
                    $data->attribs[$ksfield] = isset($ksdata->$ksfield) ? $ksdata->$ksfield : '';
                }
            }
            else
            {
                // Load the form
                JForm::addFormPath(dirname(__FILE__).'/extras');
                $form = new JForm('com_content.article');
                $form->loadFile('testimonial', false);

                // Merge the default values
                $data->attribs = array();
                foreach ($form->getFieldset('attribs') as $field)
                {
                    $data->attribs[] = array($field->fieldname, $field->value);
                }
            }
        }

        return true;
    }

    /**
     * Fires after content save post event hook to save custom data into #__content_ksextras
     *
     * @param $context
     * @param $data
     * @param $isNew
     *
     * @return bool
     */
    public function onContentAfterSave($context, $data, $isNew)
    {
        // Check if we are manipulating a valid form
        if (!in_array($context, array('com_content.article')))
        {
            return true;
        }

        // Get the article id or set to 0 if new article (it should have an id at this point)
        $articleId = isset($data->id) ? $data->id : 0;

        // Get the attributes
        $attribs = json_decode($data->attribs);

        // Pull out the extra fields to insert into the table
        $ksattribs = array();
        foreach ($this->ksfields as $ksfield)
        {
            $ksattribs[$ksfield] = isset($attribs->$ksfield) ? $attribs->$ksfield : '';
        }
        $ksattribs = json_encode($ksattribs);

        // Get the database object
        $db = JFactory::getDbo();

        // Check for an existing entry
        $db->setQuery('SELECT COUNT(*) FROM #__content_ksextras WHERE article_id = '.$articleId);
        $res = $db->loadResult();

        // Updating or adding
        if (!empty($res)) // updating record
        {
            $this->updateRecord($ksattribs, $articleId);
        }
        else // Adding a new record
        {
            $this->insertRecord($ksattribs, $articleId);
        }
    }

    /**
    * Remove the data when the article is deleted
    *
    * Method is called before (after?) article data is deleted from the database
    *
    * @param string The context for the content passed to the plugin.
    * @param object The data relating to the content that was deleted.
    *
    * @return bool
    * @throws JException
    */
    public function onContentAfterDelete($context, $data)
    {
         // get the article id
        $articleId = isset($data->id) ? (int) $data->id : 0;

        if ($articleId)
        {
            try
            {
                $db = JFactory::getDbo();

                $db->setQuery('DELETE FROM #__content_ksextras WHERE article_id = '.$articleId );

                if (!$db->execute()) {
                    throw new Exception($db->getErrorMsg());
                }
            }
            catch (JException $e)
            {
                $this->_subject->setError($e->getMessage());

                return false;
            }
        }

        return true;
    }

    /**
     * The first stage in preparing the content for output
     *
     * @param $context
     * @param $article
     * @param $params
     * @param $page
     *
     * @return string
     */
    public function onContentPrepare($context, &$article, &$params, $page = 0)
    {
        if (!isset($article->testimonial) || !count($article->testimonial))
        {
            return;
        }

        // add extra css for table
        $doc = JFactory::getDocument();
        //$doc->addStyleSheet(JURI::base(true).'/plugins/content/ksextras/extras/ksextras.css');

        // construct a result table on the fly   
        jimport('joomla.html.grid');
        $table = new JGrid();

        // Create columns
        $table->addColumn('attr')->addColumn('value');   

        // populate
        $rownr = 0;
        foreach ($article->testimonial as $attr => $value)
        {
            $table->addRow(array('class' => 'row'.($rownr % 2)));
            $table->setRowCell('attr', $attr);
            $table->setRowCell('value', $value);
            $rownr++;
        }

        // wrap table in a classed <div>
        $suffix = $this->params->get('testimonialclass_sfx', 'testimonial');
        $html = '<div class="'.$suffix.'">'.(string)$table.'</div>';

        $article->text = $html.$article->text;
    }

     /**
    * Insert a new record into the database
    *
    * @param $attribs our extra fields in object form
    * @param $articleId the article id we are relating the fields to
    *
    * @return bool
    * @throws Exception
    */
    public function insertRecord($attribs, $articleId)
    {
        // Get a db connection.
        $db = JFactory::getDbo();

        // Create a new query object.
        $query = $db->getQuery(true);

        // Insert columns.
        $columns = array('article_id', 'data', 'created', 'created_by');

        $user = JFactory::getUser();
        $created_by = $user->id;
        $created = JFactory::getDate()->toSql();

        // Insert values.
        $values = array(
            $articleId,
            $db->quote(json_encode($attribs)),
            $db->quote($created),
            $created_by,
        );

        // insert query
        $query
            ->insert($db->quoteName('#__content_ksextras'))
            ->columns($db->quoteName($columns))
            ->values(implode(',', $values));

        // set the query
        $db->setQuery($query);

        // execute, throw an exception if we have a problem
        if (!$db->execute()) {
            throw new Exception($db->getErrorMsg());
        }

        return true;
    }


    /**
    * Update record function
    *
    * @param $attribs requires object of attributes from form
    * @param $articleId id of the article we are relating to
    *
    * @return bool
    * @throws Exception
    */
    protected function updateRecord($attribs, $articleId)
    {
        $db = JFactory::getDbo();

        // Create a new query object.
        $query = $db->getQuery(true);

        $conditions = array(
            'article_id='.$articleId,
        );

        $user = JFactory::getUser();
        $modified_by = $user->id;
        $modified = JFactory::getDate()->toSql();

        // Fields to update.
        $fields = array(
            'data='.$db->quote(json_encode($attribs)),
            'modified='.$db->quote($modified),
            'modified_by='.$modified_by,
        );

        // update query
        $query->update($db->quoteName('#__content_ksextras'))->set($fields)->where($conditions);

        // set the query
        $db->setQuery($query);

        // execute, throw an exception if we have a problem
        if (!$db->execute()) {
            throw new Exception($db->getErrorMsg());
        }

        return true;
    }

    /**
     * Check the article category against the category selected by the plugin
     *
     * @param integer   $article_cat        The category of the article
     * 
     * @return boolean
     */
    protected function checkCategory($article_cat)
    {
        if ($this->category == $article_cat)
        {
            return true;
        }

        // Need to check if the current category's parent or grand-parent 
        // is the category selected for this plugin
        if ($this->include_child_categories)
        {
            $parents = $this->getParentCategories($article_cat);
            if (in_array($this->category, $parents))
            {
                return true;
            }
        }

        return false;
    }

    /**
     * Get a list of the category children
     *
     * @param integer   $catId  The id of the category to check
     *
     * @return array
     */
    protected function getChildCategories($catId)
    {
        jimport('joomla.application.categories');
        $categories = JCategories::getInstance('Content');
        $cat        = $categories->get($catId);
        $children   = $cat->getChildren();
        $childCats  = array();

        foreach ($children as $child)
        {
            $childCats[] = $child->id;
        }

        return $childCats;
    }

    /**
     * Get a list of the category parent(s)
     *
     * @param integer   $catId  The id of the category to check
     *
     * @return array
     */
    protected function getParentCategories($catId)
    {
        $parentCats = array();

        jimport('joomla.application.categories');
        $categories = JCategories::getInstance('Content');
        $cat        = $categories->get($catId);

        // Check the parent_id. If it is an integer > 0, update the array and 
        // check for a parent_id of the parent... Only going up 2 levels...
        if ((int)$cat->parent_id)
        {
            $parentCats[]   = $cat->parent_id;
            $parent         = $cat->getParent();
            if ((int) $parent->parent_id)
            {
                $parentCats[] = $parent->parent_id;
            }
        }

        return $parentCats;
    }

}

````

  • thanks for your code and explanation #Rob . I will test it and comment back. i think you are trying to say that i have to make a custom plugin but which variable do i use to show user list in the com_content to assign article to. actually i have referred to that code before and the choose country list is the step to my answer but i don't know how to put user select field to assign article to student and parent. – Rj Rana Apr 23 '15 at 4:36
  • Re-reading your question, I see its a bit more complex than I thought with respect to the access control. Personally I probably wouldn't use com_content but rather Fabrik to build this. (disclaimer I'm one of the core coders for fabrik) - It would allow you to build lists of entries/articles on which you can create list pre-filters specifying things like "only show students own entries" – Rob Clayburn Apr 23 '15 at 15:42
  • Excited to know that you are one of the core developers of "Fabrik". i haven't use Fabrik but have heard a lot about that extension.will it create custom fields in com_content such as "Student-name, Student-ID" or it has its own procedure ? and secondly will it gives the option to add access control to articles and other component and modules. Thanks #Rob for your helpful information. – Rj Rana Apr 24 '15 at 5:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.