示例#1
0
     break;
 case 'publish':
 case 'publish_now':
     // Publish NOW:
     // Check that this action request is not a CSRF hacked request:
     $Session->assert_received_crumb('item');
     $post_status = $action == 'publish_now' ? 'published' : param('post_status', 'string', 'published');
     // Check permissions:
     /* TODO: Check extra categories!!! */
     $current_User->check_perm('item_post!' . $post_status, 'edit', true, $edited_Item);
     $edited_Item->set('status', $post_status);
     if ($action == 'publish_now') {
         // Update post dates
         $current_User->check_perm('blog_edit_ts', 'edit', true, $Blog->ID);
         // fp> TODO: remove seconds ONLY if date is in the future
         $edited_Item->set('datestart', remove_seconds($localtimenow));
         $edited_Item->set('datemodified', date('Y-m-d H:i:s', $localtimenow));
     }
     // UPDATE POST IN DB:
     $edited_Item->dbupdate();
     // Execute or schedule notifications & pings:
     $edited_Item->handle_post_processing(false);
     // Set the success message corresponding for the new status
     switch ($edited_Item->status) {
         case 'published':
             $success_message = T_('Post has been published.');
             break;
         case 'community':
             $success_message = T_('The post is now visible by the community.');
             break;
         case 'protected':
示例#2
0
 /**
  * Set param value
  *
  * By default, all values will be considered strings
  *
  * @todo extra_cat_IDs recording
  *
  * @param string parameter name
  * @param mixed parameter value
  * @param boolean true to set to NULL if empty value
  * @return boolean true, if a value has been set; false if it has not changed
  */
 function set($parname, $parvalue, $make_null = false)
 {
     switch ($parname) {
         case 'main_cat_ID':
             $r = $this->set_param('main_cat_ID', 'number', $parvalue, false);
             // make sure main cat is in extracat list and there are no duplicates
             $this->extra_cat_IDs[] = $this->main_cat_ID;
             $this->extra_cat_IDs = array_unique($this->extra_cat_IDs);
             // Invalidate derived property:
             $this->blog_ID = NULL;
             unset($this->main_Chapter);
             // dereference
             $this->main_Chapter = NULL;
             unset($this->Blog);
             $this->Blog = NULL;
             return $r;
         case 'extra_cat_IDs':
             // ARRAY! We do not record this change (yet)
             $this->extra_cat_IDs = $parvalue;
             // make sure main cat is in extracat list and there are no duplicates
             $this->extra_cat_IDs[] = $this->main_cat_ID;
             $this->extra_cat_IDs = array_unique($this->extra_cat_IDs);
             break;
         case 'issue_date':
         case 'datestart':
             // Remove seconds from issue date and start date
             // fp> TODO: this should only be done if the date is in the future. If it's in the past there are no sideeffects to having seconds.
             // asimo> Why do we have two parameter with the same content if only one is stored in the database?
             // Also it doesn't make sense to remove seconds from a db date field because the database format has seconds anyway.
             // If we remove seconds from datstart field, then datestart will be always inserted into the dbchagnes even if it was not changed.
             // If we don't want seconds in the end of the datestart then we need to remove it in the itemlight constructor as well.
             // asimo> We have to set seconds to '00' and not remove them, this way the posts can appear right after creating, and the format is OK as well.
             $parvalue_empty_seconds = remove_seconds(strtotime($parvalue), 'Y-m-d H:i:s');
             $this->issue_date = $parvalue_empty_seconds;
             return $this->set_param('datestart', 'date', $parvalue_empty_seconds, false);
         case 'ptyp_ID':
         case 'canonical_slug_ID':
         case 'tiny_slug_ID':
         case 'dateset':
         case 'excerpt_autogenerated':
             return $this->set_param($parname, 'number', $parvalue, true);
         default:
             return $this->set_param($parname, 'string', $parvalue, $make_null);
     }
 }
示例#3
0
    /**
     * Restricts the datestart param to a specific date range.
     *
     * Start date gets restricted to minutes only (to make the query more
     * cachable).
     *
     * Priorities:
     *  -dstart and/or dstop
     *  -week + m
     *  -m
     * @todo  -dstart + x days
     * @see ItemList2::get_advertised_start_date()
     *
     * @param string YYYYMMDDHHMMSS (everything after YYYY is optional) or ''
     * @param integer week number or ''
     * @param string YYYYMMDDHHMMSS to start at, '' for first available
     * @param string YYYYMMDDHHMMSS to stop at
     * @param mixed Do not show posts before this timestamp, can be 'now'
     * @param mixed Do not show posts after this timestamp, can be 'now'
     */
    function where_datestart($m = '', $w = '', $dstart = '', $dstop = '', $timestamp_min = '', $timestamp_max = 'now')
    {
        global $time_difference, $DB;
        $this->m = $m;
        $this->w = $w;
        $this->dstart = $dstart;
        $this->dstop = $dstop;
        $this->timestamp_min = $timestamp_min;
        $this->timestamp_max = $timestamp_max;
        $start_is_set = false;
        $stop_is_set = false;
        // if a start date is specified in the querystring, crop anything before
        if (!empty($dstart)) {
            // Add trailing 0s: YYYYMMDDHHMMSS
            $dstart0 = $dstart . '00000000000000';
            // TODO: this is NOT correct, should be 0101 for month
            // Start date in MySQL format: seconds get omitted (rounded to lower to minute for caching purposes)
            $dstart_mysql = substr($dstart0, 0, 4) . '-' . substr($dstart0, 4, 2) . '-' . substr($dstart0, 6, 2) . ' ' . substr($dstart0, 8, 2) . ':' . substr($dstart0, 10, 2);
            $this->WHERE_and($this->dbprefix . 'datestart >= ' . $DB->quote($dstart_mysql) . '
													OR ( ' . $this->dbprefix . 'datedeadline IS NULL AND ' . $this->dbprefix . 'datestart >= ' . $DB->quote($dstart_mysql) . ' )');
            $start_is_set = true;
        }
        // if a stop date is specified in the querystring, crop anything before
        if (!empty($dstop)) {
            switch (strlen($dstop)) {
                case '4':
                    // We have only year, add one to year
                    $dstop_mysql = $dstop + 1 . '-01-01 00:00:00';
                    break;
                case '6':
                    // We have year month, add one to month
                    $dstop_mysql = date("Y-m-d H:i:s ", mktime(0, 0, 0, substr($dstop, 4, 2) + 1, 01, substr($dstop, 0, 4)));
                    break;
                case '8':
                    // We have year mounth day, add one to day
                    $dstop_mysql = date("Y-m-d H:i:s ", mktime(0, 0, 0, substr($dstop, 4, 2), substr($dstop, 6, 2) + 1, substr($dstop, 0, 4)));
                    break;
                case '10':
                    // We have year mounth day hour, add one to hour
                    $dstop_mysql = date("Y-m-d H:i:s ", mktime(substr($dstop, 8, 2) + 1, 0, 0, substr($dstop, 4, 2), substr($dstop, 6, 2), substr($dstop, 0, 4)));
                    break;
                case '12':
                    // We have year mounth day hour minute, add one to minute
                    $dstop_mysql = date("Y-m-d H:i:s ", mktime(substr($dstop, 8, 2), substr($dstop, 8, 2) + 1, 0, substr($dstop, 4, 2), substr($dstop, 6, 2), substr($dstop, 0, 4)));
                    break;
                default:
                    // add one to second
                    // Stop date in MySQL format: seconds get omitted (rounded to lower to minute for caching purposes)
                    $dstop_mysql = substr($dstop, 0, 4) . '-' . substr($dstop, 4, 2) . '-' . substr($dstop, 6, 2) . ' ' . substr($dstop, 8, 2) . ':' . substr($dstop, 10, 2);
            }
            $this->WHERE_and($this->dbprefix . 'datestart < ' . $DB->quote($dstop_mysql));
            // NOT <= comparator because we compare to the superior stop date
            $stop_is_set = true;
        }
        if (!$start_is_set || !$stop_is_set) {
            if (!is_null($w) && strlen($m) == 4) {
                // If a week number is specified (with a year)
                // Note: we use PHP to calculate week boundaries in order to handle weeks
                // that overlap 2 years properly, even when start on week is monday (which MYSQL won't handle properly)
                $start_date_for_week = get_start_date_for_week($m, $w, locale_startofweek());
                $this->WHERE_and($this->dbprefix . "datestart >= '" . date('Y-m-d', $start_date_for_week) . "'");
                $this->WHERE_and($this->dbprefix . "datestart < '" . date('Y-m-d', $start_date_for_week + 604800) . "'");
                // + 7 days
                $start_is_set = true;
                $stop_is_set = true;
            } elseif (!empty($m)) {
                // We want to restrict on an interval:
                $this->WHERE_and('EXTRACT(YEAR FROM ' . $this->dbprefix . 'datestart)=' . intval(substr($m, 0, 4)));
                if (strlen($m) > 5) {
                    $this->WHERE_and('EXTRACT(MONTH FROM ' . $this->dbprefix . 'datestart)=' . intval(substr($m, 4, 2)));
                }
                if (strlen($m) > 7) {
                    $this->WHERE_and('EXTRACT(DAY FROM ' . $this->dbprefix . 'datestart)=' . intval(substr($m, 6, 2)));
                }
                if (strlen($m) > 9) {
                    $this->WHERE_and('EXTRACT(HOUR FROM ' . $this->dbprefix . 'datestart)=' . intval(substr($m, 8, 2)));
                }
                if (strlen($m) > 11) {
                    $this->WHERE_and('EXTRACT(MINUTE FROM ' . $this->dbprefix . 'datestart)=' . intval(substr($m, 10, 2)));
                }
                if (strlen($m) > 13) {
                    $this->WHERE_and('EXTRACT(SECOND FROM ' . $this->dbprefix . 'datestart)=' . intval(substr($m, 12, 2)));
                }
                $start_is_set = true;
                $stop_is_set = true;
            }
        }
        // TODO: start + x days
        // TODO: stop - x days
        // SILENT limits!
        // Timestamp limits:
        if ($timestamp_min == 'now') {
            // echo 'hide past';
            $timestamp_min = time();
        }
        if (!empty($timestamp_min)) {
            // Hide posts before
            // echo 'hide before '.$timestamp_min;
            $date_min = remove_seconds($timestamp_min + $time_difference);
            $this->WHERE_and($this->dbprefix . 'datestart >= ' . $DB->quote($date_min));
        }
        if ($timestamp_max == 'now') {
            // echo 'hide future';
            $timestamp_max = time();
        }
        if (!empty($timestamp_max)) {
            // Hide posts after
            // echo 'after';
            $date_max = remove_seconds($timestamp_max + $time_difference);
            $this->WHERE_and($this->dbprefix . 'datestart <= ' . $DB->quote($date_max));
        }
    }
    /**
     * Display the widget!
     *
     * @param array MUST contain at least the basic display params
     */
    function display($params)
    {
        global $localtimenow;
        $this->init_display($params);
        if ($this->disp_params['order_by'] == 'RAND' && isset($this->BlockCache)) {
            // Do NOT cache if display order is random
            $this->BlockCache->abort_collect();
        }
        global $Blog;
        $list_blogs = $this->disp_params['blog_ID'] ? $this->disp_params['blog_ID'] : $Blog->ID;
        //pre_dump( $list_blogs );
        // Display photos:
        // TODO: permissions, complete statuses...
        // TODO: A FileList object based on ItemListLight but adding File data into the query?
        //          overriding ItemListLigth::query() for starters ;)
        $FileCache =& get_FileCache();
        $FileList = new DataObjectList2($FileCache);
        // Query list of files:
        $SQL = new SQL();
        $SQL->SELECT('post_ID, post_datestart, post_datemodified, post_main_cat_ID, post_urltitle, post_canonical_slug_ID,
									post_tiny_slug_ID, post_ptyp_ID, post_title, post_excerpt, post_url, file_ID,
									file_title, file_root_type, file_root_ID, file_path, file_alt, file_desc');
        $SQL->FROM('T_categories INNER JOIN T_postcats ON cat_ID = postcat_cat_ID
									INNER JOIN T_items__item ON postcat_post_ID = post_ID
									INNER JOIN T_links ON post_ID = link_itm_ID
									INNER JOIN T_files ON link_file_ID = file_ID');
        $SQL->WHERE('cat_blog_ID IN (' . $list_blogs . ')');
        // fp> TODO: want to restrict on images :]
        $SQL->WHERE_and('post_status = "published"');
        // TODO: this is a dirty hack. More should be shown.
        $SQL->WHERE_and('post_datestart <= \'' . remove_seconds($localtimenow) . '\'');
        if (!empty($this->disp_params['item_type'])) {
            // Get items only with specified type
            $SQL->WHERE_and('post_ptyp_ID = ' . intval($this->disp_params['item_type']));
        }
        $SQL->GROUP_BY('link_ID');
        $SQL->LIMIT($this->disp_params['limit'] * 4);
        // fp> TODO: because we have no way of getting images only, we get 4 times more data than requested and hope that 25% at least will be images :/
        $SQL->ORDER_BY(gen_order_clause($this->disp_params['order_by'], $this->disp_params['order_dir'], 'post_', 'post_ID ' . $this->disp_params['order_dir'] . ', link_ID'));
        $FileList->sql = $SQL->get();
        $FileList->query(false, false, false, 'Media index widget');
        $layout = $this->disp_params['thumb_layout'];
        $nb_cols = $this->disp_params['grid_nb_cols'];
        $count = 0;
        $r = '';
        /**
         * @var File
         */
        while ($File =& $FileList->get_next()) {
            if ($count >= $this->disp_params['limit']) {
                // We have enough images already!
                break;
            }
            if (!$File->is_image()) {
                // Skip anything that is not an image
                // fp> TODO: maybe this property should be stored in link_ltype_ID or in the files table
                continue;
            }
            if ($layout == 'grid') {
                if ($count % $nb_cols == 0) {
                    $r .= $this->disp_params['grid_colstart'];
                }
                $r .= $this->disp_params['grid_cellstart'];
            } else {
                $r .= $this->disp_params['item_start'];
            }
            // 1/ Hack a dirty permalink( will redirect to canonical):
            // $link = url_add_param( $Blog->get('url'), 'p='.$post_ID );
            // 2/ Hack a link to the right "page". Very daring!!
            // $link = url_add_param( $Blog->get('url'), 'paged='.$count );
            // 3/ Instantiate a light object in order to get permamnent url:
            $ItemLight = new ItemLight($FileList->get_row_by_idx($FileList->current_idx - 1));
            // index had already been incremented
            $r .= '<a href="' . $ItemLight->get_permanent_url() . '">';
            // Generate the IMG THUMBNAIL tag with all the alt, title and desc if available
            $r .= $File->get_thumb_imgtag($this->disp_params['thumb_size'], '', '', $ItemLight->title);
            $r .= '</a>';
            if ($this->disp_params['disp_image_title']) {
                $title = $File->get('title') ? $this->get('title') : $ItemLight->title;
                $r .= '<span class="note">' . $title . '</span>';
            }
            ++$count;
            if ($layout == 'grid') {
                $r .= $this->disp_params['grid_cellend'];
                if ($count % $nb_cols == 0) {
                    $r .= $this->disp_params['grid_colend'];
                }
            } else {
                $r .= $this->disp_params['item_end'];
            }
        }
        // Exit if no files found
        if (empty($r)) {
            return;
        }
        echo $this->disp_params['block_start'];
        // Display title if requested
        $this->disp_title();
        if ($layout == 'grid') {
            echo $this->disp_params['grid_start'];
        } else {
            echo $this->disp_params['list_start'];
        }
        echo $r;
        if ($layout == 'grid') {
            if ($count && $count % $nb_cols != 0) {
                echo $this->disp_params['grid_colend'];
            }
            echo $this->disp_params['grid_end'];
        } else {
            echo $this->disp_params['list_end'];
        }
        echo $this->disp_params['block_end'];
        return true;
    }
示例#5
0
/**
 * Retrieves all tags from published posts
 *
 * @param integer the id of the blog or array of blog ids. Set NULL to use current blog
 * @param integer maximum number of returned tags
 * @param string a comma separated list of tags to ignore/exclude
 * @param bool true to skip tags from pages, intro posts and sidebar stuff
 * @return array of tags
 */
function get_tags($blog_ids, $limit = 0, $filter_list = NULL, $skip_intro_posts = false)
{
    global $DB, $localtimenow, $posttypes_specialtypes;
    $BlogCache =& get_BlogCache();
    if (is_null($blog_ids)) {
        global $blog;
        $blog_ids = $blog;
    }
    if (is_array($blog_ids)) {
        // Get quoted ID list
        $blog_ids = $DB->quote($blog_ids);
        $where_cats = 'cat_blog_ID IN (' . $blog_ids . ')';
    } else {
        $Blog =& $BlogCache->get_by_ID($blog_ids);
        // Get list of relevant blogs
        $where_cats = trim($Blog->get_sql_where_aggregate_coll_IDs('cat_blog_ID'));
    }
    // fp> verrry dirty and params; TODO: clean up
    // dh> oddly, this appears to not get cached by the query cache. Have experimented a bit, but not found the reason.
    //     It worked locally somehow, but not live.
    //     This takes up to ~50% (but more likely 15%) off the total SQL time. With the query being cached, it would be far better.
    // build query, only joining categories, if not using all.
    $sql = 'SELECT LOWER(tag_name) AS tag_name, post_datestart, COUNT(DISTINCT itag_itm_ID) AS tag_count, tag_ID, cat_blog_ID
			FROM T_items__tag
			INNER JOIN T_items__itemtag ON itag_tag_ID = tag_ID';
    if ($where_cats != '1') {
        // we have to join the cats
        $sql .= '
		 INNER JOIN T_postcats ON itag_itm_ID = postcat_post_ID
		 INNER JOIN T_categories ON postcat_cat_ID = cat_ID';
    }
    $sql .= "\n\t\t INNER JOIN T_items__item ON itag_itm_ID = post_ID\n\t\t WHERE {$where_cats}\n\t\t   AND post_status = 'published' AND post_datestart < '" . remove_seconds($localtimenow) . "'";
    if ($skip_intro_posts) {
        $sql .= ' AND post_ptyp_ID NOT IN (' . implode(',', $posttypes_specialtypes) . ')';
    }
    if (!empty($filter_list)) {
        // Filter tags
        $filter_list = explode(',', $filter_list);
        $filter_tags = array();
        foreach ($filter_list as $l_tag) {
            $filter_tags[] = '"' . $DB->escape(trim($l_tag)) . '"';
        }
        $sql .= ' AND tag_name NOT IN (' . implode(', ', $filter_tags) . ')';
    }
    $sql .= ' GROUP BY tag_name ORDER BY tag_count DESC';
    if (!empty($limit)) {
        $sql .= ' LIMIT ' . $limit;
    }
    return $DB->get_results($sql, OBJECT, 'Get tags');
}
示例#6
0
/**
 * Retrieves all tags from published posts
 *
 * @param integer the id of the blog or array of blog ids. Set NULL to use current blog
 * @param integer maximum number of returned tags
 * @param string a comma separated list of tags to ignore/exclude
 * @param bool true to skip tags from pages, intro posts and sidebar stuff
 * @return array of tags
 */
function get_tags($blog_ids, $limit = 0, $filter_list = NULL, $skip_intro_posts = false)
{
    global $DB, $localtimenow, $posttypes_specialtypes;
    $BlogCache =& get_BlogCache();
    if (is_null($blog_ids)) {
        global $blog;
        $blog_ids = $blog;
    }
    if (is_array($blog_ids)) {
        // Get quoted ID list
        $where_cat_clause = 'cat_blog_ID IN ( ' . $DB->quote($blog_ids) . ' )';
    } else {
        // Get list of relevant blogs
        $Blog =& $BlogCache->get_by_ID($blog_ids);
        $where_cat_clause = trim($Blog->get_sql_where_aggregate_coll_IDs('cat_blog_ID'));
    }
    // Build query to get the tags:
    $tags_SQL = new SQL();
    $tags_SQL->SELECT('tag_name, COUNT( DISTINCT itag_itm_ID ) AS tag_count, tag_ID, cat_blog_ID');
    $tags_SQL->FROM('T_items__tag');
    $tags_SQL->FROM_add('INNER JOIN T_items__itemtag ON itag_tag_ID = tag_ID');
    $tags_SQL->FROM_add('INNER JOIN T_items__item ON itag_itm_ID = post_ID');
    $tags_SQL->FROM_add('INNER JOIN T_postcats ON itag_itm_ID = postcat_post_ID');
    $tags_SQL->FROM_add('INNER JOIN T_categories ON postcat_cat_ID = cat_ID');
    $tags_SQL->WHERE($where_cat_clause);
    $tags_SQL->WHERE_and('post_status = "published"');
    $tags_SQL->WHERE_and('post_datestart < ' . $DB->quote(remove_seconds($localtimenow)));
    if ($skip_intro_posts) {
        // Skip "Intro" posts
        $tags_SQL->WHERE_and('post_ityp_ID NOT IN ( ' . implode(', ', $posttypes_specialtypes) . ' )');
    }
    if (!empty($filter_list)) {
        // Filter tags
        $tags_SQL->WHERE_and('tag_name NOT IN ( ' . $DB->quote(explode(', ', $filter_list)) . ' )');
    }
    $tags_SQL->GROUP_BY('tag_name');
    $tags_SQL->ORDER_BY('tag_count DESC');
    if (!empty($limit)) {
        // Limit
        $tags_SQL->LIMIT($limit);
    }
    return $DB->get_results($tags_SQL->get(), OBJECT, 'Get tags');
}
    /**
     * Display the widget!
     *
     * @param array MUST contain at least the basic display params
     */
    function display($params)
    {
        global $localtimenow, $DB, $Blog;
        $this->init_display($params);
        $blog_ID = intval($this->disp_params['blog_ID']);
        if (empty($blog_ID)) {
            // Use current blog by default
            $blog_ID = $Blog->ID;
        }
        $BlogCache =& get_BlogCache();
        if (!$BlogCache->get_by_ID($blog_ID, false, false)) {
            // No blog exists
            return;
        }
        // Display photos:
        // TODO: permissions, complete statuses...
        // TODO: A FileList object based on ItemListLight but adding File data into the query?
        //          overriding ItemListLigth::query() for starters ;)
        // Init caches
        $FileCache =& get_FileCache();
        $ItemCache =& get_ItemCache();
        // Query list of files and posts fields:
        // Note: We use ItemQuery to get attachments from all posts which should be visible ( even in case of aggregate blogs )
        $ItemQuery = new ItemQuery($ItemCache->dbtablename, $ItemCache->dbprefix, $ItemCache->dbIDname);
        $ItemQuery->SELECT('post_ID, post_datestart, post_datemodified, post_main_cat_ID, post_urltitle, post_canonical_slug_ID,
									post_tiny_slug_ID, post_ityp_ID, post_title, post_excerpt, post_url, file_ID, file_type,
									file_title, file_root_type, file_root_ID, file_path, file_alt, file_desc, file_path_hash');
        $ItemQuery->FROM_add('INNER JOIN T_links ON post_ID = link_itm_ID');
        $ItemQuery->FROM_add('INNER JOIN T_files ON link_file_ID = file_ID');
        $ItemQuery->where_chapter($blog_ID);
        if ($this->disp_params['item_visibility'] == 'public') {
            // Get images only of the public items
            $ItemQuery->where_visibility(array('published'));
        } else {
            // Get image of all available posts for current user
            $ItemQuery->where_visibility(NULL);
        }
        $ItemQuery->WHERE_and('( file_type = "image" ) OR ( file_type IS NULL )');
        $ItemQuery->WHERE_and('post_datestart <= \'' . remove_seconds($localtimenow) . '\'');
        $ItemQuery->WHERE_and('link_position != "cover"');
        if (!empty($this->disp_params['item_type'])) {
            // Get items only with specified type
            $ItemQuery->WHERE_and('post_ityp_ID = ' . intval($this->disp_params['item_type']));
        }
        $ItemQuery->GROUP_BY('link_ID');
        // fp> TODO: because no way of getting images only, we get 4 times more data than requested and hope that 25% at least will be images :/
        // asimo> This was updated and we get images and those files where we don't know the file type yet. Now we get 2 times more data than requested.
        // Maybe it would be good to get only the requested amount of files, because after a very short period the file types will be set for all images.
        $ItemQuery->LIMIT(intval($this->disp_params['limit']) * 2);
        $ItemQuery->ORDER_BY(gen_order_clause($this->disp_params['order_by'], $this->disp_params['order_dir'], 'post_', 'post_ID ' . $this->disp_params['order_dir'] . ', link_ID'));
        // Init FileList with the above defined query
        $FileList = new DataObjectList2($FileCache);
        $FileList->sql = $ItemQuery->get();
        $FileList->query(false, false, false, 'Media index widget');
        $layout = $this->disp_params['thumb_layout'];
        $nb_cols = $this->disp_params['grid_nb_cols'];
        $count = 0;
        $r = '';
        /**
         * @var File
         */
        while ($File =& $FileList->get_next()) {
            if ($count >= $this->disp_params['limit']) {
                // We have enough images already!
                break;
            }
            if (!$File->is_image()) {
                // Skip anything that is not an image
                // Only images are selected or those files where we don't know the file type yet.
                // This check is only for those files where we don't know the filte type. The file type will be set during the check.
                continue;
            }
            if ($layout == 'grid') {
                // Grid layout
                if ($count % $nb_cols == 0) {
                    $r .= $this->disp_params['grid_colstart'];
                }
                $r .= $this->disp_params['grid_cellstart'];
            } elseif ($layout == 'flow') {
                // Flow block layout
                $r .= $this->disp_params['flow_block_start'];
            } else {
                // List layout
                $r .= $this->disp_params['item_start'];
            }
            // 1/ Hack a dirty permalink( will redirect to canonical):
            // $link = url_add_param( $Blog->get('url'), 'p='.$post_ID );
            // 2/ Hack a link to the right "page". Very daring!!
            // $link = url_add_param( $Blog->get('url'), 'paged='.$count );
            // 3/ Instantiate a light object in order to get permamnent url:
            $ItemLight = new ItemLight($FileList->get_row_by_idx($FileList->current_idx - 1));
            // index had already been incremented
            $r .= '<a href="' . $ItemLight->get_permanent_url() . '">';
            // Generate the IMG THUMBNAIL tag with all the alt, title and desc if available
            $r .= $File->get_thumb_imgtag($this->disp_params['thumb_size'], '', '', $ItemLight->title);
            $r .= '</a>';
            if ($this->disp_params['disp_image_title']) {
                // Dislay title of image or item
                $title = $File->get('title') ? $File->get('title') : $ItemLight->title;
                if (!empty($title)) {
                    $r .= '<span class="note">' . $title . '</span>';
                }
            }
            ++$count;
            if ($layout == 'grid') {
                // Grid layout
                $r .= $this->disp_params['grid_cellend'];
                if ($count % $nb_cols == 0) {
                    $r .= $this->disp_params['grid_colend'];
                }
            } elseif ($layout == 'flow') {
                // Flow block layout
                $r .= $this->disp_params['flow_block_end'];
            } else {
                // List layout
                $r .= $this->disp_params['item_end'];
            }
        }
        // Exit if no files found
        if (empty($r)) {
            return;
        }
        echo $this->disp_params['block_start'];
        // Display title if requested
        $this->disp_title();
        echo $this->disp_params['block_body_start'];
        if ($layout == 'grid') {
            // Grid layout
            echo $this->disp_params['grid_start'];
        } elseif ($layout == 'flow') {
            // Flow block layout
            echo $this->disp_params['flow_start'];
        } else {
            // List layout
            echo $this->disp_params['list_start'];
        }
        echo $r;
        if ($layout == 'grid') {
            // Grid layout
            if ($count && $count % $nb_cols != 0) {
                echo $this->disp_params['grid_colend'];
            }
            echo $this->disp_params['grid_end'];
        } elseif ($layout == 'flow') {
            // Flow block layout
            echo $this->disp_params['flow_end'];
        } else {
            // List layout
            echo $this->disp_params['list_end'];
        }
        echo $this->disp_params['block_body_end'];
        echo $this->disp_params['block_end'];
        return true;
    }