אדר א

חוויותיי עם יצירת תוסף ב-Moodle

לאחרונה התבקשתי ליצור תוסף (אם מעניין אתכם לדעת, אז מה שהוא עושה זה מציג ב-my את כל הפעילויות ומשאבים שנוספו בקורסים בהם הם משתמשים בתפקיד שיצרנו: מורה משתף, אבל לא אכנס ללוגיקה של התוסף). זו לא הפעם הראשונה שאני יוצרת תוסף אבל אני לא יוצרת אותם בתדירות מספיק גבוהה כדי לזכור איך לעשות את זה כל פעם. לכן החלטתי עכשיו לתעד את החלקים החשובים בתהליך כדי לחסוך לי כמה דקות בפעם הבאה.
בפוסט הזה אלא אתמקד בשני דברים כללים שאני תמיד צריכה: בניית תוסף, ושימוש ב-mustache.

בניית תוסף בסיסי

מערכת המוודל שלנו היא בגרסה 3.3, והתוסף הזה מתאים לגרסה זו. אני לא יודעת מה יהיה מצבו בגרסאות קודמות או מתקדמות יותר.

בבניית התוסף הסתמכתי על התיעוד של מוודל, אבל לא הייתי צריכה את כל הקוד משם ולכן העדפתי להשתמש בתבנית מוכנה של תוסף, ולמחוק ממנה מה שלא מתאים לי.

לקחתי תבנית מוכנה, והסרתי ממנה את הקבצים הבאים:

  • .travis.yml
  • composer.json
  • edit_form.php
  • settings.php

גם ב-block_newblock.php מחקתי קוד. חלק מחקתי כדי שההסרות של הקבצים הנ”ל לא תשפענה על הקוד, וחלק כי לא הייתי צריכה את הקוד עצמו:

  • ב-get_content מחקתי הכל מלבד השורות שממלאות את $this->content כדי שאוכל להחזיר אותו.
    function get_content() {
        global $CFG, $OUTPUT, $DB, $USER;
    
        if ($this->content !== null) {
            return $this->content;
        }
    
        if (empty($this->instance)) {
            $this->content = '';
            return $this->content;
        }
    
        $renderer = $this->page->get_renderer('block_lifeneighbor');
    
        $this->content = new stdClass();
        $this->content->text = '';
        $this->content->footer = '';
    
        return $this->content;
    }
    
  • בפונקציה has_config הגדרתי שיחזיר false כי אין קובץ settings.php.
  • גם את הפונקציה instance_allow_multiple הגדרתי שתחזיר false. משבצת אחת מספיקה.
  • את הפונקציה applicable_formats שיניתי מפני שרציתי שהמשבצת תופיע רק בדף “העדכונים שלי”. פירוט בפיסקה הבאה.
  • את הפונקציה cron מחקתי.

כדי שמשבצת תופיע בדף העדכונים שלי, ורק שם

צריך להגדיר בשני מקומות:

המקום הראשון הוא ב-db/access.php של המשבצת יש מערך של capabilities. הפריט הראשון אומר לו להראות את המשבצת בדף ה-my:

$capabilities = array(

    'block/lifeneighbor:myaddinstance' => array(
        'captype' => 'write',
        'contextlevel' => CONTEXT_SYSTEM,
        'archetypes' => array(
            'manager' => CAP_ALLOW
        ),

        'clonepermissionsfrom' => 'moodle/my:manageblocks'
    ),

    'block/lifeneighbor:addinstance' => array(
        'riskbitmask' => RISK_SPAM | RISK_XSS,

        'captype' => 'write',
        'contextlevel' => CONTEXT_BLOCK,
        'archetypes' => array(
        ),

        'clonepermissionsfrom' => 'moodle/site:manageblocks'
    ),
);

(הפריט השני נועד כדי לא לקבל שגיאות במסכים אחרים, שבהם איננו רוצים שהמשבצת תופיע).

המקום השני הוא הפונקציהapplicable_formats. כך צריך להגדירה:

public function applicable_formats() {
return array('my' => true
);
}

הצגת התוכן באמצעות Mustache-ים

בגרסאות האחרונות של מוודל, התחילו להכתוב HTML בתבניות mustache. אפשר לקרוא על mustache כאן, על התחביר שלו כאן, ועל שילובו ב-Moodle – כאן. יצא לי להשתמש ב-mustache בתבנית שבניתי בשנה שעברה (ושאני עדיין מקווה לכתוב קצת עליה בבלוג) כך שלא באתי כלוח חלק. חוץ מזה, כמו בתבנית, אני לא אוהבת להתחיל מאפס אלא לקחת משהו דומה שכבר קיים, ולהתאים אותו לצרכיי.

  1. יצירת קובץ ה-mustache:
    הקוד שרציתי לייצר היה דומה מאוד לזה שיוצרת המשבצת myoverview, אז לקחתי ממנה את הקובץ courses-view-course-item.mustache ושמתי במשבצת שלי תחת תיקיית templates.
  2. הקריאה לקובץ ה-mustache:
    צריכה להיעשות מתוך renderer. יצרתי תיקיית classes ובתוכה תיקיית output. בתוכה יצרתי קלאס בשם renderer ויצרתי פונקציה בשם render_main. הפונקציה קוראת לפונקציה render_from_template ממחלקת הבסיס, מעבירה לה כפרמטר ראשון את שם קובץ ה-mustache, ובפרמטר השני את המידע שאותו יציג קובץ ה-mustache (אני העברתי קריאה לפונקציה שתיצור את זה).

    /**
    * Return the main content for the block overview.
    *
    * @return string HTML string
    */
    public function render_main() {
    return $this->render_from_template('block_lifeneighbor/courses-view-course-item', $this->export_for_template($this));
    }
  3. בפונקציה get_content שיניתי את מה שמשימים ל-$content->text. יצרתי אוביקט שקורא ל-renderer והעברתי ל-$content->text את מה שמחזירה הפונקציה:
    $renderer = $this->page->get_renderer('block_lifeneighbor');
    
    $this->content->text = $renderer->render_main();
    

מה מציג ה-mustache

יש סוגים שונים של data שהייתי צריכה להציג בתוסף הזה, וכל אחד מהם אתגר אותי בצורה שונה. אפרט כאן את הסוגים השונים ואת דרכי הצגתם. מטבע הדברים יש עוד סוגי data שאפשר להציג עם mustache, אבל הפוסט הזה מתעד רק את מה שאני חוויתי.

אנחנו רוצים להראות מערך של קורסים. המערך מכיל אוביקטים שכל אחד מהם הוא קורס.

קודם ניצור את המעטפת של ה-HTML שיציג את המערך

  1. ניצור את המערך בפונקציה שהגדרנו (ושאת שמה שלחנו כפרמטר ל-render_from_template)
    $output[$i++]['coursename'] = $recent_activity->fullname;
  2. נחזיר את המערך ונקרא לו coursesview:
    return [
    'coursesview' => $output
    ];
  3. בקובץ ה-mustache נעטוף את כל ה-HTML המיוצר בתגית שבודקת אם קיים אוביקט coursesview:
    {{#coursesview}}
    {{/coursesview}}

כעת ניצוק לתוך תגיות ה-HTML שדות מהאוביקטים שממלאים את המערך

  1. בתוך העטיפה הנ”ל ניצור את ה-HTML, שבו למשל בכותרת נקרא לפריט ה-fullname שמילאנו בו
    {{#coursesview}}
    <h4><a href="{{viewurl}}" class="">{{coursename}}</a></h4>
    {{/coursesview}}
    

אם מערך מכיל טיפוס פשוט כמו int או מחרוזת, ולא אוביקט עם שדות

למשל מערך כזה:

"coursemodules": Array { [0] => "מטלה ב'", [1] => "מטלה א'"}

אז כדי להציג  את התוכן של כל איבר נשתמש בנקודה:

{{#coursemodules}}
    <a href="{{moduleurl}}">
        {{.}}
    </a>
{{/coursemodules}}

אם השדה מכיל תגית HTML

אם נקרא לו כרגיל, עם שני סוגריים מסולסלים לפניו ואחריו, ה-HTML יעבור encoding ויוצג כטקסט רגיל ולא כקוד. כדי להציג את זה כקוד, צריך לעטוף את השדה ב-3 סוגריים מסולסלים:

{{{icon}}}

וזהו.

***

מעניין אותי באיזו דרך אתם בונים תוספים, מה החוויות שלכם משילוב mustache, ובכלל, כל מה שיש לכם להוסיף או להעיר על הפוסט יתקבל בברכה.

תמונה של שפם (mustache) שנוצרה על ידי rawpixel.com – www.freepik.com

כתבו תגובה

כתובת הדוא"ל שלכם לא תוצג.