Commit a2f56dba authored by Cecilia Vela Gurovic's avatar Cecilia Vela Gurovic
Browse files

Bug 1870444: Cover images for portfolios

- added cove mage field to view/collection settings
- it works for personal/group/institution/site portfolios
- creates the "Cover Images" folder if it doesn't exist to store the cover images
as default location. This is created when navgating to a view/collection settings section.
- there is an upgrade to add 'coverimage' column to view and
collection tables on the db.
- the cover image is displayed in the view/collection card
on pages and collections section
- copy views/collections should copy the cover image
- display the image in the card of pages and collections if it has one.
If there's no image it should display the desctiption or nothing if there's
no description. If it has cover image and a description, then it displays
the image and when hover over it will display the description.
On mobile it will display the description when touched

TODO
- accessibility
- importing views/collections should import the cover image

behatnotneeded
Change-Id: I72e305ba437ba20df23f8ede224d399eb97f02d1
parent cf6603f7
Loading
Loading
Loading
Loading
+82 −0
Original line number Diff line number Diff line
@@ -2536,6 +2536,88 @@ class ArtefactTypeImage extends ArtefactTypeFile {
    public static function is_metaartefact() {
        return false;
    }

    public static function get_coverimage($options=null) {
        $url = get_config('wwwroot') . 'thumb.php?type=coverimagebyid&id=' . hsc($options['id']);

        if (isset($options['viewid'])) {
            $url .= '&view=' . $options['viewid'];
        }
        if (isset($options['size'])) {
            $url .= '&size=' . $options['size'];
        }
        else {
            $url .= '&width=200';
        }

        return $url;
    }

    /**
     * Render's the cover image thumbnail and exits
     */
    public static function download_coverimage_thumbnail($artefactid, $type=null) {
        global $USER;
        $id = $artefactid;
        $size = get_imagesize_parameters();
        $earlyexpiry = param_boolean('earlyexpiry', false);

        $mimetype = get_field('artefact_file_files', 'filetype', 'artefact', $id);

        if ($id && $fileid = get_field('artefact_file_files', 'fileid', 'artefact', $id)) {
            $orientation = get_field('artefact_file_image', 'orientation', 'artefact', $id);

            if ($path = get_dataroot_image_path('artefact/file', $fileid, $size, $orientation)) {
                if ($mimetype) {
                    header('Content-type: ' . $mimetype);

                    if (!get_config('nocache')) {
                        // We can't cache 'profileicon' for as long, because the
                        // user can change it at any time.
                        $maxage = 600; // 10 minutes
                        header('Expires: '. gmdate('D, d M Y H:i:s', time() + $maxage) .' GMT');
                        header('Cache-Control: max-age=' . $maxage);
                        header('Pragma: public');
                    }

                    readfile($path);
                    perf_to_log();
                    exit;
                }
            }
        }
    }


    /**
     * Gets the id of the Cover images folder for the user/group/institution/site
     * @param $user the user object of the owner of the view/collection
     * @param $group the group id of the view/collection to get the image cover
     * @param $institution the institution name that owns the view/collection to get the image cover
     * institution='mahara' if it's a site's portfolio
     */
    public static function get_coverimage_folder($user=null, $group=null, $institution=null) {
        $foldername = get_string('coverimagefolder', 'view');
        if ($folder = ArtefactTypeFolder::get_folder_by_name($foldername, null, $user->get('id'), $group, $institution)) {
            $folderid = $folder->id;
        }
        else {
            $data = array('title' => $foldername);
            if ($group) {
                $data['group'] = $group;
            }
            else if ($institution) {
                $data['institution'] = $institution;
            }
            else {
                $data['owner'] = $user->get('id');
            }
            $folder = new ArtefactTypeFolder(0, (object) $data);
            $folder->commit();
            $folderid = $folder->get('id');
        }
        return $folderid;
    }
}

class ArtefactTypeProfileIcon extends ArtefactTypeImage {
+26 −6
Original line number Diff line number Diff line
@@ -103,15 +103,19 @@ else {
        $confirm = null;
    }
}
$elements['submit'] = array(
$elements['submitform'] = array(
    'type'      => $type,
    'class' => 'btn-primary',
    'value'     => $submitstr,
    'confirm'   => $confirm,
    'goto'      => $baseurl,
);

$form = pieform(array(
    'name' => 'edit',
    'method'     => 'post',
    'jsform'     => true,
    'jssuccesscallback' => 'edit_callback',
    'jserrorcallback'   => 'edit_callback',
    'plugintype' => 'core',
    'pluginname' => 'collection',
    'validatecallback' => 'collectionedit_validate',
@@ -119,11 +123,17 @@ $form = pieform(array(
    'elements' => $elements,
));

$inlinejs = <<<EOF
function edit_callback(form, data) {
    edit_coverimage.callback(form, data);
};
EOF;

$smarty = smarty();
setpageicon($smarty, 'icon-folder-open');

$smarty->assign('headingclass', 'page-header');

$smarty->assign('INLINEJAVASCRIPT', $inlinejs);
$smarty->assign('form', $form);
$smarty->display('collection/edit.tpl');

@@ -154,11 +164,21 @@ function collectionedit_submit(Pieform $form, $values) {
    if (empty($values['framework'])) {
        $values['framework'] = null;
    }
    $values['coverimage'] = (isset($values['coverimage']) ? $values['coverimage'] : null);
    $collection = Collection::save($values);
    if (!$new) {
        $SESSION->add_ok_msg(get_string('collectionsaved', 'collection'));

    $result = array(
        'error'   => false,
        'message' => get_string('collectionsaved', 'collection'),
        'goto'    => $collection->post_edit_redirect_url($new, $copy, $urlparams),
    );

    if ($form->submitted_by_js()) {
        // Redirect back to the note page from within the iframe
        $SESSION->add_ok_msg($result['message']);
        $form->json_reply(PIEFORM_OK, $result, false);
    }
    $collection->post_edit_redirect($new, $copy, $urlparams);
    $form->reply(PIEFORM_OK, $result);
}

function edit_cancel_submit() {
+5 −0
Original line number Diff line number Diff line
@@ -539,3 +539,8 @@ $string['accessibilitymodedescription'] = 'This page has the accessible layout e
 In this mode, the page blocks will have full page width and will be displayed one after the other.
 To change a block position, navigate to it, grab it with the \'Enter\' key, and move it up and down the list of blocks with the arrow keys.';
$string['blocktypeis'] = ' %s blocktype';

// Cover image
$string['coverimage'] = 'Cover image';
$string['coverimagefolder'] = 'Cover images';
$string['coverimagedescription'] = 'The dimensions recommended are width 180px and height is 130px.';
+91 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ class Collection {
    private $views;
    private $tags;
    private $framework;
    private $coverimage;

    const UNSUBMITTED = 0;
    const SUBMITTED = 1;
@@ -78,6 +79,9 @@ class Collection {
        if ($field == 'views') {
            return $this->views();
        }
        if ($field == 'coverimage') {
            return $this->get_coverimage();
        }
        return $this->{$field};
    }

@@ -261,6 +265,38 @@ class Collection {
        return $name . $ext;
    }

    /**
     * Copy the cover image of the collection template
     *
     * @param Collection $template the collection template
     * @param array $collectiondata contains data about owner, group, institution of the copy
     * @return int new image artefact id
     */
    private static function copy_setting_coverimage(Collection $template, $collectiondata) {
        safe_require('artefact', 'file');
        $coverimageid = $template->get('coverimage');
        $owner = isset($collectiondata['owner']) ? $collectiondata['owner'] : null;
        $group = isset($collectiondata['group']) ? $collectiondata['group'] : null;
        $institution = isset($collectiondata['institution']) ? $collectiondata['institution'] : null;
        if ($coverimageid) {
            try {
                $a = artefact_instance_from_id($coverimageid);
                if ($a instanceof ArtefactTypeImage) {
                    $newid = $a->copy_for_new_owner(
                      $owner,
                      $group,
                      $institution
                    );
                }
                return $newid;
            }
            catch (Exception $e) {
                return null;
            }
        }
        return null;
    }

    /**
     * Creates a Collection for the given user, based off a given template and other
     * Collection information supplied.
@@ -310,6 +346,7 @@ class Collection {
            $data->name = $collectiondata['name'];
        }
        $data->description = $colltemplate->get('description');
        $data->coverimage = self::copy_setting_coverimage($colltemplate, $collectiondata);
        $data->tags = $colltemplate->get('tags');
        $data->navigation = $colltemplate->get('navigation');
        if (!empty($collectiondata['group'])) {
@@ -325,6 +362,7 @@ class Collection {
            $data->owner = $userid;
        }
        $data->framework = $colltemplate->get('framework');
        $data->coverimage = $colltemplate->get('coverimage');
        $data->submittedstatus = 0;

        $collection = self::save($data);
@@ -546,6 +584,11 @@ class Collection {
    * @return array $elements
    */
    public function get_collectionform_elements() {
        safe_require('artefact', 'file');
        global $USER;
        $folder = ArtefactTypeImage::get_coverimage_folder($USER, $this->group, $this->institution);

        $highlight = array(0);
        $elements = array(
            'name' => array(
                'type' => 'text',
@@ -578,6 +621,35 @@ class Collection {
                'description' => get_string('viewnavigationdesc','collection'),
                'defaultvalue' => 1,
            ),
            'coverimage' => array(
                'type'         => 'filebrowser',
                'title'        => get_string('coverimage', 'view'),
                'description'  => get_string('coverimagedescription', 'view'),
                'folder'       => $folder,
                'highlight'    => $highlight,
                'accept'       => 'image/jpg,image/png',
                'institution'  => $this->institution,
                'group'        => $this->group,
        //         // 'browse'       => $browse,
                'page'         => '',
        //         // 'browsehelp'   => 'browsemyfiles',
                'filters'      => array(
                     'artefacttype' => array('image'),
                ),
                'config'       => array(
                    'upload'          => true,
                    'uploadagreement' => get_config_plugin('artefact', 'file', 'uploadagreement'),
                    'resizeonuploaduseroption' => get_config_plugin('artefact', 'file', 'resizeonuploaduseroption'),
                    'resizeonuploaduserdefault' => $USER->get_account_preference('resizeonuploaduserdefault'),
                    'createfolder'    => false,
                    'edit'            => false,
                    'select'          => true,
                    'selectone'       => true,
                ),
                'selectlistcallback' => 'artefact_get_records_by_id',
                'selectcallback'     => 'add_view_coverimage',
                'unselectcallback'   => 'delete_view_coverimage',
            ),
        );
        if ($frameworks = $this->get_available_frameworks()) {
            $options = array('' => get_string('noframeworkselected', 'module.framework'));
@@ -600,6 +672,9 @@ class Collection {
                if ($k === 'tags') {
                    $elements[$k]['defaultvalue'] = $this->get_tags();
                }
                else if ($k == 'coverimage') {
                    $elements[$k]['defaultvalue'] = ($this->get('coverimage') ? array($this->get('coverimage')) : null);
                }
                else {
                    $elements[$k]['defaultvalue'] = $this->$k;
                }
@@ -1047,6 +1122,14 @@ class Collection {
     * after editing the collection, redirect back to the appropriate place
     */
    public function post_edit_redirect($new=false, $copy=false, $urlparams=null) {
        $redirecturl = post_edit_redirect_url($new, $copy, $urlparams);
        redirect($redirecturl);
    }

    /**
     * returns the url that we need to redirect to sfter editing a collection
     */
    public function post_edit_redirect_url($new=false, $copy=false, $urlparams=null) {
        if ($new || $copy) {
            $urlparams['id'] = $this->get('id');
            $redirecturl = '/collection/views.php';
@@ -1074,7 +1157,7 @@ class Collection {
        if ($urlparams) {
            $redirecturl .= '?' . http_build_query($urlparams);
        }
        redirect($redirecturl);
        return $redirecturl;
    }

    public static function search_by_view_id($viewid) {
@@ -1387,6 +1470,13 @@ class Collection {
        }
    }

    public function get_coverimage() {
        if ($this->coverimage && get_field('artefact', 'id', 'id', $this->coverimage)) {
            return $this->coverimage;
        }
        return null;
    }

    /**
     * Returns the collection tags
     *
+4 −0
Original line number Diff line number Diff line
@@ -756,6 +756,7 @@
                <FIELD NAME="instructions" TYPE="text" NOTNULL="false" />
                <FIELD NAME="instructionscollapsed" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" />
                <FIELD NAME="accessibleview" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" />
                <FIELD NAME="coverimage" TYPE="int" LENGTH="10" NOTNULL="false"/>
            </FIELDS>
            <KEYS>
                <KEY NAME="primary" TYPE="primary" FIELDS="id" />
@@ -765,6 +766,7 @@
                <KEY NAME="groupfk" TYPE="foreign" FIELDS="group" REFTABLE="group" REFFIELDS="id" />
                <KEY NAME="institutionfk" TYPE="foreign" FIELDS="institution" REFTABLE="institution" REFFIELDS="name" />
                <KEY NAME="typefk" TYPE="foreign" FIELDS="type" REFTABLE="view_type" REFFIELDS="type" />
                <KEY NAME="coverimagefk" TYPE="foreign" FIELDS="coverimage" REFTABLE="artefact" REFFIELDS="id" />
            </KEYS>
            <INDEXES>
                <INDEX NAME="urliduk" UNIQUE="true" FIELDS="urlid,owner,group,institution" />
@@ -1032,6 +1034,7 @@
                <FIELD NAME="group" TYPE="int" LENGTH="10" NOTNULL="false" />
                <FIELD NAME="institution" TYPE="char" LENGTH="255" NOTNULL="false" />
                <FIELD NAME="framework" TYPE="int" LENGTH="10" NOTNULL="false" />
                <FIELD NAME="coverimage" TYPE="int" LENGTH="10" NOTNULL="false" />
            </FIELDS>
            <KEYS>
                <KEY NAME="primary" TYPE="primary" FIELDS="id" />
@@ -1040,6 +1043,7 @@
                <KEY NAME="submittedhostfk" TYPE="foreign" FIELDS="submittedhost" REFTABLE="host" REFFIELDS="wwwroot" />
                <KEY NAME="groupfk" TYPE="foreign" FIELDS="group" REFTABLE="group" REFFIELDS="id"  />
                <KEY NAME="institutionfk" TYPE="foreign" FIELDS="institution" REFTABLE="institution" REFFIELDS="name"  />
                <KEY NAME="coverimagefk" TYPE="foreign" FIELDS="coverimage" REFTABLE="artefact" REFFIELDS="id"  />
            </KEYS>
        </TABLE>
        <TABLE NAME="collection_view">
Loading