Tutorial Mahara eigene Blocktypen

Aus Mahoodle

Wechseln zu: Navigation, Suche

Inhaltsverzeichnis

Die Entwicklung eigener Blocktypen

In einer Ansicht ist der Blocktyp ein Block, der sich in der Tabulatorleiste am oberen Fensterrand befindet und in die Ansicht gezogen werden kann. "Blogposting", "Profilinformationen" und "Textbox" sind einige der Beispielblocktypen.

Einige Blocktypen, wie zum Beispiel der Blogposting Block, sind mit Artefakten verknüpft. Andere, wie die Profilinformationen, sind mit mehr als einem Artefakt verbunden, wieder andere, wie die Textbox, sind mit keinem Artefakt verknüpft.

Wenn die Blocktypen in die Ansicht gezogen werden, wird eine "Block Instanz" angelegt. Blockinstanzen sind für die Blocktypen was Objekte für Klassen in der Objekt orientierten Programmierung sind. Jede Ansicht kann viele verschiedene Blockinstanzen aus verschiedenen Blocktypen beinhalten - so kann der Blogposting Blocktyp zweimal in in eine Ansicht eingefügt werden und jeweils unterschiedliche Blogposting anzeigen.

Mahara hat eine Plugin API Schnittstelle und erlaubt das Erstellen neuer Blocktypen für die Verwendung in den Ansichten. So wird das Hinzufügen eigener Blocktypen zum Kinderspiel.

Wo soll ich beginnen?

Zuerst muss festgelegt werden, ob der neue Blocktyp mit Artefakten verknüpft werden soll. Die Entscheidung ist einfach - Wird der neue Blocktyp ein Artefakt darstellen? Wenn JA, welche Sorte von Artefakt soll dargestellt werden?

Blocktypen, die Artefakte darstellen, werden Artefaktblocktypen genannt, die anderen blocktypen werden als Systemblocktypen bezeichnet.

  • Die Systemblocktypens werden im Verzeichnis htdocs/blocktype/ abgespeichert, jeweils in einem eigenen Unterverzeichnis.
  • Die Artefaktblocktypen werden im Verzeichnis htdocs/artefact/[artefactplugin]/blocktype, ebenfalls in einem eigenen Unterverzeichnis abgelegt.

Ein Beispiel Blocktyp

Let's have a look at the textbox blocktype, as it is as of 2007/11/01. Text boxes are just a WYSIWYG editor for people to put free text in. It lives under the 'general' tab in the views interface. Because no artefacts are involved, it lives in the htdocs/blocktype/textbox directory.

In diesem Verzeichnis ist ein Ordner und einige Dateien: lang/, lib.php, thumb.png und version.php.

  • Das lang/ Verzeichnis enthält die übersetzungen für den Blocktyp. Jede Sprache wird in einem getrennten Verzeichnis verwaltet.
  • Die lib.php Datei enthält die Klasse die die Blocktyp API implementiert und somit den Kern eines Blocktype darstellt. Diese Datei sollten wir uns auf jeden Fall näher ansehen.
  • thumb.png ist das Bild, das im "Tabbed-Interface" angezeigt wird, welches es uns ermöglicht Blocktypen auszuwählen. Man kann das Bild nach belieben editieren, nur sollte man sicherstellen, dass die Maße (Höhe und Breite) des Bildes erhalten bleiben.
  • version.php enthält Versionsinformationen zum Blocktypen und sollte aufgrund der Einfachheit selbsterklärend sein.

lib.php

Hier findet die Aktion statt. Die Datei enthält eine Klassendefinition, die in etwa so aussieht:

class PluginBlocktypeTextbox extends SystemBlocktype {

    public static function get_title() {
        return get_string('title', 'blocktype.textbox');
    }

    public static function get_description() {
        return get_string('description', 'blocktype.textbox');
    }

    public static function get_categories() {
        return array('general');
    }

    public static function render_instance(BlockInstance $instance) {
        $configdata = $instance->get('configdata');
        $text = (isset($configdata['text'])) ? $configdata['text'] : '';
        return $text;
    }

    public static function has_instance_config() {
        return true;
    }

    public static function instance_config_form($instance) {
        $configdata = $instance->get('configdata');
        return array(
            'text' => array(
                'type' => 'tinywysiwyg',
                'width' => '90%',
                'height' => '150px',
                'defaultvalue' => $configdata['text'],
            ),
        );
    }

    public static function instance_config_save($values) {
        global $USER;
        if (!get_account_preference($USER->get('id'), 'wysiwyg')) {
            $values['text'] = format_whitespace($values['text']);
        }
        else {
            $values['text'] = clean_text($values['text']);
        }
        return $values;
    }

}

The PluginBlocktypeTextbox class

This class extends the SystemBlocktype class and implements the required methods to be a valid system blocktype. The class is called PluginTypeTextbox and lives in a directory called 'textbox'. These things are related - if your blocktype is called 'flobber' then it should live in a directory called 'flobber' and the class should be called 'PluginBlocktypeFlobber'.

The static method get_title returns the title for the block, as seen in the tabbed interface for choosing blocktypes. It uses get_string to return a translated value if the user is using another language.

The static method get_description is very similar, returning the description seen below the title in the blocktype choosing interface.

get_categories is a method that returns an array of the categories that the blocktype is in. The textbox claims it is in the 'general' category, and so appears under the general tab. Blocktypes can be in more than one category. The allowed categories names are in the blocktype_category table in the database.

render_instance is where much of the action takes place. This method needs to return the HTML that will be displayed in each blockinstance. In our example, the blockinstance is queried for its configuration data, and the 'text' field of it is used as the HTML.

has_instance_config returns whether this blocktype has a configuration form. Some do not, although most of them will.

instance_config_form returns the elements for the pieform that will be used to configure the blockinstance. In this case, the form contains a 'text' element that is a tiny WYSIWYG editor. Its default value is the text config data for the block - and because the element is called 'text', when the config form is saved then the value of the WYSIWYG editor will be used as the text configuration data for the blockinstance.

instance_config_save is a callback function that allows the blocktype to modify the data submitted before it is saved. In this case, it makes sure that the text is correctly formatted depending on whether the user has the WYSIWYG editor enabled or disabled. Note that the actual saving is handled by the blocktype API itself, so blocktypes do not have to do it themselves.

An Artefact Blocktype

The image blocktype, in the htdocs/artefact/file/blocktype directory, deals with showing images that users have uploaded to their files section. As of 2007/11/01, it looks like this:

class PluginBlocktypeImage extends PluginBlocktype {
                
    public static function get_title() {
        return get_string('title', 'blocktype.file/image');
    }           
                
    public static function get_description() {
        return get_string('description', 'blocktype.file/image');
    }           
                
    public static function get_categories() {
        return array('file', 'images');
    }
    
    public static function render_instance(BlockInstance $instance) {
        require_once(get_config('docroot') . 'lib/artefact.php');
        $configdata = $instance->get('configdata'); // this will make sure to unserialize it for us
        $configdata['viewid'] = $instance->get('view');
            
        // This can be either an image or profileicon. They both implement 
        // render_self 
        $result = '';
        if (isset($configdata['artefactid'])) {
            $image = artefact_instance_from_id($configdata['artefactid']);
            
            if ($image instanceof ArtefactTypeProfileIcon) {
                $src = get_config('wwwroot') . 'thumb.php?type=profileiconbyid&id=' . $configdata['artefactid'];
                $description = $image->get('title');
            }
            else {
                $src = get_config('wwwroot') . 'artefact/file/download.php?file=' . $configdata['artefactid'];
                $src .= '&view=' . $instance->get('view');
                $description = $image->get('description');
            }

            if (!empty($configdata['width'])) {
                $src .= '&maxwidth=' . $configdata['width'];
            }
             
            $result  = '<div class="center"><div>';
            $result .= '<a href="' . get_config('wwwroot') . 'view/view.php?id=' . $instance->get('view') . '&artefact=' . $configdata['artefactid'] . '"><img src="' . hsc($src) . '" alt="' . hsc($description) .'"></a>';
            $result .= '</div>';
            
            $description = (is_a($image, 'ArtefacttypeImage')) ? $image->get('description') : $image->get('title');
            if (!empty($configdata['showdescription']) && $description) {
                $result .= '<p>' . $description . '</p>';
            }
            $result .= '</div>';
        }

        return $result;
    }

    public static function get_artefacts(BlockInstance $instance) {
        $configdata = $instance->get('configdata');
        if (isset($configdata['artefactid'])) {
            return array($configdata['artefactid']);
        }
        return false;
    }

    public static function has_instance_config() {
        return true;
    }

    public static function instance_config_form($instance) {
        $configdata = $instance->get('configdata');
        return array(
            self::artefactchooser_element((isset($configdata['artefactid'])) ? $configdata['artefactid'] : null),
            'showdescription' => array(
                'type'  => 'checkbox',
                'title' => get_string('showdescription', 'blocktype.file/image'),
                'defaultvalue' => $configdata['showdescription'],
            ),
            'width' => array(
                'type' => 'text',
                'title' => get_string('width', 'blocktype.file/image'),
                'size' => 3,
                'description' => get_string('widthdescription', 'blocktype.file/image'),
                'rules' => array(
                    'minvalue' => 16,
                    'maxvalue' => get_config('imagemaxwidth'),
                ),
                'defaultvalue' => (isset($configdata['width'])) ? $configdata['width'] : '',
            ),
        );
    }

    public static function artefactchooser_element($default=null) {
        return array(
            'name'  => 'artefactid',
            'type'  => 'artefactchooser',
            'title' => get_string('image'),
            'defaultvalue' => $default,
            'rules' => array(
                'required' => true,
            ),
            'blocktype' => 'image',
            'limit' => 5,
            'artefacttypes' => array('image', 'profileicon'),
            'template' => 'artefact:file:artefactchooser-element.tpl',
        );
    }

    /**
     * Optional method. If specified, allows the blocktype class to munge the 
     * artefactchooser element data before it's templated
     *
     * Note: this method is the same as the one for the 'filedownload' blocktype
     */
    public static function artefactchooser_get_element_data($artefact) {
        $artefact->icon = call_static_method(generate_artefact_class_name($artefact->artefacttype), 'get_icon', array('id' => $artefact->id));
        if ($artefact->artefacttype == 'profileicon') {
            $artefact->hovertitle  =  $artefact->note;
            if ($artefact->title) {
                $artefact->hovertitle .= ': ' . $artefact->title;
            }
        }
        else {
            $artefact->hovertitle  =  $artefact->title;
            if ($artefact->description) {
                $artefact->hovertitle .= ': ' . $artefact->description;
            }
        }
        $artefact->title       = str_shorten($artefact->title, 20);
        $artefact->description = ($artefact->artefacttype == 'profileicon') ? $artefact->title : $artefact->description;

        return $artefact;
    }

}

This blocktype is more complicated than the textbox. The differences are outlined below:

The get_title and get_description methods are similar to their textbox counterparts, however they use a namespaced section name - blocktype.file/image. The first part of the section is always "blocktype", then after the period is "artefactplugin/blocktype".

The get_artefacts method is required for artefact blocktypes. It returns the IDs of any artefacts in the blocktype, which are used by Mahara to assert whether an artefact is in a given view.

The instance_config_form includes a call to self::artefactchooser_element. This method returns an artefactchooser pieform element, which is used to select which artefact or artefacts should be in the blockinstance. This is the element that allows pagination through the artefacts available.

Persönliche Werkzeuge
Herunterladen