public static function import_sample_properties($ws, $el_properties, $el, $files, $structure, $items, $real, $el_id, $item_uid)
    {
        global $DB;
        $el_properties_associative = array();
        foreach ($el_properties as $foo => $property) {
            if (!empty($property) && is_array($property)) {
                $property = $property[0];
            }
            if (empty($property->value)) {
                continue;
            }
            // get the original ID for files and categories
            // "translate" those IDs for the ones assigned on the new website
            // for example:
            // (old website) file id: 35    =>  (new website) file id: 3
            // ...and also translate nv:// urls in (text) properties values
            switch ($property->type) {
                case 'file':
                case 'image':
                    if (in_array($property->multilanguage, array('true', '1'))) {
                        foreach ($property->value as $plang => $pval) {
                            if (isset($files[$pval]->id)) {
                                $property->value[$plang] = $files[$pval]->id;
                            }
                        }
                    } else {
                        if (isset($files[$property->value]->id)) {
                            $property->value = $files[$property->value]->id;
                        }
                    }
                    break;
                case 'category':
                    if (in_array($property->multilanguage, array('true', '1'))) {
                        foreach ($property->value as $plang => $pval) {
                            if (isset($structure[$pval]->id)) {
                                $property->value[$plang] = $structure[$pval]->id;
                            }
                        }
                    } else {
                        if (isset($structure[$property->value]->id)) {
                            $property->value = $structure[$property->value]->id;
                        }
                    }
                    break;
                case 'categories':
                    if (in_array($property->multilanguage, array('true', '1'))) {
                        foreach ($property->value as $plang => $pval) {
                            $property_categories_old = explode(',', $pval);
                            $property_categories_new = array();
                            foreach ($property_categories_old as $oc) {
                                $property_categories_new[] = $structure[$oc]->id;
                            }
                            $property->value[$plang] = implode(',', $property_categories_new);
                        }
                    } else {
                        $property_categories_old = explode(',', $property->value);
                        $property_categories_new = array();
                        foreach ($property_categories_old as $oc) {
                            $property_categories_new[] = $structure[$oc]->id;
                        }
                        $property->value = implode(',', $property_categories_new);
                    }
                    break;
                case 'element':
                    // is multi-language forced for this property?
                    if (in_array($property->multilanguage, array('true', '1'))) {
                        foreach ($property->value as $olang => $oval) {
                            if (isset($items[$oval]->id)) {
                                $property->value[$olang] = $items[$oval]->id;
                            }
                        }
                    } else {
                        if (isset($items[$property->value]->id)) {
                            $property->value = $items[$property->value]->id;
                        }
                    }
                    break;
                default:
                    if (is_array($property->value)) {
                        // multilanguage property
                        foreach ($property->value as $lang => $pvalue) {
                            $property->value[$lang] = theme::import_sample_translate_nv_urls($pvalue, $structure, $items);
                        }
                    } else {
                        if (!is_string($property->value)) {
                            $property->value = theme::import_sample_translate_nv_urls($property->value, $structure, $items);
                        }
                    }
            }
            $el_properties_associative[$property->id] = $property->value;
        }
        if (!empty($el_properties_associative)) {
            if ($el == 'block_group_block') {
                $template = $real[$el_id]->code;
            } else {
                if ($el == 'block') {
                    $template = $real[$el_id]->type;
                } else {
                    $template = $real[$el_id]->template;
                    if (empty($template) && $el == 'item' && $real[$el_id]->embedding == 1) {
                        // we have to get the template set in the category of the item
                        $template = $DB->query_single('template', 'nv_structure', ' id = ' . protect($real[$el_id]->category) . ' AND 
								  website = ' . $ws->id);
                    }
                }
            }
            property::save_properties_from_array($el, $real[$el_id]->id, $template, $el_properties_associative, $ws, $item_uid);
        }
    }
Exemple #2
0
function run()
{
    global $layout;
    global $DB;
    global $website;
    global $theme;
    global $user;
    $out = '';
    $item = new item();
    switch ($_REQUEST['act']) {
        case 'json':
        case 1:
            // json data retrieval & operations
            switch ($_REQUEST['oper']) {
                case 'del':
                    // remove rows
                    $ids = $_REQUEST['ids'];
                    foreach ($ids as $id) {
                        $item->load($id);
                        $item->delete();
                    }
                    echo json_encode(true);
                    break;
                default:
                    // list or search
                    // translation of request search & order fields
                    switch ($_REQUEST['searchField']) {
                        case 'id':
                            $_REQUEST['searchField'] = 'i.id';
                            break;
                        case 'title':
                            $_REQUEST['searchField'] = 'd.text';
                            break;
                        case 'language':
                            $_REQUEST['searchField'] = 'd.lang';
                            break;
                        case 'category':
                            $_REQUEST['searchField'] = 'i.category';
                            break;
                        case 'dates':
                            $_REQUEST['searchField'] = 'i.date_published';
                            break;
                        case 'permission':
                            $_REQUEST['searchField'] = 'i.permission';
                            break;
                        default:
                    }
                    if ($_REQUEST['sidx'] == 'dates') {
                        $_REQUEST['sidx'] = 'i.date_published';
                    }
                    $page = intval($_REQUEST['page']);
                    $max = intval($_REQUEST['rows']);
                    $offset = ($page - 1) * $max;
                    $orderby = $_REQUEST['sidx'] . ' ' . $_REQUEST['sord'];
                    $where = ' i.website = ' . $website->id;
                    if ($_REQUEST['_search'] == 'true' || isset($_REQUEST['quicksearch'])) {
                        if (isset($_REQUEST['quicksearch'])) {
                            $where .= $item->quicksearch($_REQUEST['quicksearch']);
                        } else {
                            if (isset($_REQUEST['filters'])) {
                                if (is_array($_REQUEST['filters'])) {
                                    $filters = json_decode(json_encode($_REQUEST['filters']), FALSE);
                                } else {
                                    $filters = json_decode($_REQUEST['filters']);
                                }
                                for ($r = 0; $r < count($filters->rules); $r++) {
                                    switch ($filters->rules[$r]->field) {
                                        case 'id':
                                            $filters->rules[$r]->field = 'i.id';
                                            break;
                                        case 'title':
                                            $filters->rules[$r]->field = 'd.text';
                                            break;
                                        case 'language':
                                            $filters->rules[$r]->field = 'd.lang';
                                            break;
                                        case 'category':
                                            $filters->rules[$r]->field = 'i.category';
                                            break;
                                        case 'dates':
                                            $filters->rules[$r]->field = 'i.date_published';
                                            break;
                                        case 'permission':
                                            $filters->rules[$r]->field = 'i.permission';
                                            break;
                                        default:
                                    }
                                }
                                $where .= navitable::jqgridsearch(json_encode($filters));
                            } else {
                                // single search
                                $where .= ' AND ' . navitable::jqgridcompare($_REQUEST['searchField'], $_REQUEST['searchOper'], $_REQUEST['searchString']);
                            }
                        }
                    }
                    $sql = ' SELECT SQL_CALC_FOUND_ROWS
					                i.*, d.text as title, d.lang as language,
                                    u.username as author_username,
                                    (   SELECT COUNT(*)
                                        FROM nv_comments cm
                                        WHERE cm.item = i.id
                                          AND cm.website = ' . $website->id . '
                                    ) as comments
							   FROM nv_items i
						  LEFT JOIN nv_webdictionary d
						  		 	 ON i.id = d.node_id
								 	AND d.node_type = "item"
									AND d.subtype = "title"
									AND d.lang = "' . $website->languages_list[0] . '"
									AND d.website = ' . $website->id . '
						  LEFT JOIN nv_users u
						  			 ON u.id = i.author
							  WHERE ' . $where . '	
						   GROUP BY i.id, d.text, d.lang, u.username						   
						   ORDER BY ' . $orderby . ' 
							  LIMIT ' . $max . '
							 OFFSET ' . $offset;
                    if (!$DB->query($sql, 'array')) {
                        throw new Exception($DB->get_last_error());
                    }
                    $dataset = $DB->result();
                    $total = $DB->foundRows();
                    $dataset = grid_notes::summary($dataset, 'item', 'id');
                    $access = array(0 => '<img src="img/icons/silk/page_white_go.png" align="absmiddle" title="' . t(254, 'Everybody') . '" />', 1 => '<img src="img/icons/silk/lock.png" align="absmiddle" title="' . t(361, 'Web users only') . '" />', 2 => '<img src="img/icons/silk/user_gray.png" align="absmiddle" title="' . t(363, 'Users who have not yet signed up or signed in') . '" />', 3 => '<img src="img/icons/silk/group_key.png" align="absmiddle" title="' . t(512, "Selected web user groups") . '" />');
                    $permissions = array(0 => '<img src="img/icons/silk/world.png" align="absmiddle" /> ' . t(69, 'Published'), 1 => '<img src="img/icons/silk/world_dawn.png" align="absmiddle" /> ' . t(70, 'Private'), 2 => '<img src="img/icons/silk/world_night.png" align="absmiddle" /> ' . t(81, 'Hidden'));
                    $hierarchy = structure::hierarchy(0);
                    // we need to format the values and retrieve the needed strings from the dictionary
                    $out = array();
                    for ($i = 0; $i < count($dataset); $i++) {
                        if (empty($dataset[$i])) {
                            continue;
                        }
                        if (empty($dataset[$i]['date_published'])) {
                            $dataset[$i]['date_published'] = '&infin;';
                        } else {
                            $dataset[$i]['date_published'] = core_ts2date($dataset[$i]['date_published'], false);
                        }
                        if (empty($dataset[$i]['date_unpublish'])) {
                            $dataset[$i]['date_unpublish'] = '&infin;';
                        } else {
                            $dataset[$i]['date_unpublish'] = core_ts2date($dataset[$i]['date_unpublish'], false);
                        }
                        if (empty($dataset[$i]['date_to_display'])) {
                            $dataset[$i]['date_to_display'] = '';
                        } else {
                            $dataset[$i]['date_to_display'] = core_ts2date($dataset[$i]['date_to_display'], false);
                        }
                        if ($dataset[$i]['category'] > 0) {
                            $category_path = structure::hierarchyPath($hierarchy, $dataset[$i]['category']);
                            if (is_array($category_path)) {
                                $dataset[$i]['category_path'] = implode(' › ', $category_path);
                            } else {
                                $dataset[$i]['category_path'] = $category_path;
                            }
                        }
                        $category_text = '';
                        if ($dataset[$i]['association'] == 'free') {
                            $category_text = '[ ' . strtolower(t(100, 'Free')) . ' ]';
                        } else {
                            $category_text = $dataset[$i]['category_path'];
                        }
                        $item_views = $dataset[$i]['views'];
                        if ($item_views > 1000) {
                            $item_views = round($item_views / 1000) . "K";
                        }
                        $item_comments = $dataset[$i]['comments'];
                        if ($item_comments > 1000) {
                            $item_comments = round($item_comments / 1000) . "K";
                        }
                        //$social_rating = '<img src="img/icons/silk/star.png" align="absmiddle" width="12px" height="12px" /> '.
                        //    '<span style="font-size: 90%;">'.$dataset[$i]['score'].' ('.$dataset[$i]['votes'].')</span>';
                        //$social_rating = '<i class="fa fa-fw fa-eye" /> <span style="font-size: 90%;">'.$dataset[$i]['views'].'</span>';
                        $social_rating = '<img src="img/icons/silk/eye.png" align="absmiddle" width="12px" height="12px" /> ' . '<span style="font-size: 90%;">' . $item_views . '</span>';
                        //$social_comments = '<i class="fa fa-fw fa-comments-o" /> <span style="font-size: 90%;">'.$dataset[$i]['comments'].'</span>';
                        $social_comments = '<img src="img/icons/silk/comments.png" align="absmiddle" width="12px" height="12px" /> ' . '<span style="font-size: 90%;">' . $item_comments . '</span>';
                        if (empty($dataset[$i]['title'])) {
                            // if title is empty for the default language,
                            // try to load the title in another language
                            $DB->query('
                                SELECT lang, text
                                  FROM nv_webdictionary
                                 WHERE website = ' . $website->id . ' AND
                                        node_type = "item" AND
                                        subtype="title" AND
                                        node_id = ' . $dataset[$i]['id'] . ' AND
                                        text != ""
                                ORDER BY id ASC');
                            $titles = $DB->result();
                            if (!empty($titles)) {
                                $dataset[$i]['title'] = '<img src="img/icons/silk/comment.png" align="absmiddle" />';
                                $dataset[$i]['title'] .= '<small>' . $titles[0]->lang . '</small>&nbsp;&nbsp;';
                                $dataset[$i]['title'] .= $titles[0]->text;
                            }
                        }
                        $out[$i] = array(0 => $dataset[$i]['id'], 1 => '<div class="list-row" data-permission="' . $dataset[$i]['permission'] . '">' . $dataset[$i]['title'] . '</div>', 2 => $social_rating . '&nbsp;&nbsp;' . $social_comments, 3 => $category_text, 4 => $dataset[$i]['date_to_display'], 5 => $dataset[$i]['date_published'] . ' - ' . $dataset[$i]['date_unpublish'], 6 => $access[$dataset[$i]['access']] . ' ' . $permissions[$dataset[$i]['permission']], 7 => $dataset[$i]['_grid_notes_html']);
                    }
                    navitable::jqgridJson($out, $page, $offset, $max, $total);
                    break;
            }
            core_terminate();
            break;
        case 'load':
        case 'create':
        case 'edit':
        case 2:
            // edit/new form
            if (!empty($_REQUEST['id'])) {
                $item->load(intval($_REQUEST['id']));
                if ($user->permission("items.edit") == "false" && $item->author != $user->id) {
                    $layout->navigate_notification(t(610, "Sorry, you are not allowed to execute the requested function"), true);
                    $_REQUEST['act'] = 'list';
                    return run();
                }
                // check if the current user can edit this item
                if ($item->association == 'category' && !empty($item->category)) {
                    if (!structure::category_allowed($item->category)) {
                        $layout->navigate_notification(t(610, "Sorry, you are not allowed to execute the requested function"), true);
                        $_REQUEST['act'] = 'list';
                        return run();
                    }
                }
            }
            if (isset($_REQUEST['form-sent'])) {
                $item->load_from_post();
                try {
                    $item->save();
                    property::save_properties_from_post('item', $item->id);
                    if (!empty($_REQUEST['items-order'])) {
                        item::reorder($_REQUEST['items-order']);
                    }
                    $layout->navigate_notification(t(53, "Data saved successfully."), false, false, 'fa fa-check');
                    $item->load($item->id);
                    users_log::action($_REQUEST['fid'], $item->id, 'save', $item->dictionary[$website->languages_list[0]]['title'], json_encode($_REQUEST));
                } catch (Exception $e) {
                    $layout->navigate_notification($e->getMessage(), true, true);
                }
            } else {
                users_log::action($_REQUEST['fid'], $item->id, 'load', $item->dictionary[$website->languages_list[0]]['title']);
            }
            $out = items_form($item);
            break;
        case 'delete':
        case 4:
            // remove
            if (!empty($_REQUEST['id'])) {
                $item->load(intval($_REQUEST['id']));
                try {
                    if (!empty($item->id)) {
                        $deleted = $item->delete() > 0;
                        if ($deleted) {
                            $layout->navigate_notification(t(55, 'Item removed successfully.'), false);
                            $out = items_list();
                            users_log::action($_REQUEST['fid'], $item->id, 'remove', $item->dictionary[$website->languages_list[0]]['title'], json_encode($_REQUEST));
                        }
                    }
                    if (!$deleted) {
                        $layout->navigate_notification(t(56, 'Unexpected error.'), false);
                        if (!empty($item->id)) {
                            $out = items_form($item);
                        } else {
                            $out = items_list();
                        }
                    }
                } catch (Exception $e) {
                    $layout->navigate_notification($e->getMessage(), true);
                    if (!empty($item->id)) {
                        $out = items_form($item);
                    }
                }
            }
            break;
        case 'duplicate':
            if (!empty($_REQUEST['id'])) {
                $item->load(intval($_REQUEST['id']));
                if ($item->association == 'category' && $item->embedding == 1) {
                    // get structure template
                    $category = new structure();
                    $category->load($item->category);
                    $properties = property::load_properties_associative('structure', $category->template, 'item', $item->id);
                } else {
                    $properties = property::load_properties_associative('item', $item->template, 'item', $item->id);
                }
                // try to duplicate
                $item->id = 0;
                $ok = $item->insert();
                if ($ok) {
                    // duplicate item properties too (but don't duplicate comments)
                    if ($item->association == 'category' && $item->embedding == 1) {
                        $ok = property::save_properties_from_array('item', $item->id, $category->template, $properties);
                    } else {
                        $ok = property::save_properties_from_array('item', $item->id, $item->template, $properties);
                    }
                }
                if ($ok) {
                    $layout->navigate_notification(t(478, 'Item duplicated successfully.'), false, false, 'fa fa-check');
                    $out = items_form($item);
                } else {
                    $layout->navigate_notification(t(56, 'Unexpected error.'), false);
                    $item = new item();
                    $item->load(intval($_REQUEST['id']));
                    $out = items_form($item);
                }
                users_log::action($_REQUEST['fid'], $item->id, 'duplicate', $item->dictionary[$website->languages_list[0]]['title'], json_encode($_REQUEST));
            }
            break;
        case 89:
            if (!empty($_REQUEST['id'])) {
                $DB->execute('DELETE FROM nv_webdictionary_history WHERE id = ' . intval($_REQUEST['id']) . ' LIMIT 1');
                echo 'true';
            } else {
                echo 'false';
            }
            core_terminate();
            break;
        case 90:
            $DB->query('SELECT id, date_created, autosave
						  FROM nv_webdictionary_history
						 WHERE node_type = "item"
						   AND subtype = ' . protect('section-' . $_REQUEST['section']) . '
						   AND lang = ' . protect($_GET['lang']) . '
						   AND node_id = ' . protect($_REQUEST['id']) . '
						   AND website = ' . $website->id . ' 
				      ORDER BY date_created DESC', 'array');
            $result = $DB->result();
            if (!is_array($result)) {
                $result = array();
            }
            for ($i = 0; $i < count($result); $i++) {
                $result[$i]['date'] = core_ts2date($result[$i]['date_created'], true);
                if ($result[$i]['autosave'] == 1) {
                    $result[$i]['date'] .= ' (' . t(273, 'Autosave') . ')';
                }
            }
            echo json_encode($result);
            core_terminate();
            break;
        case "search_by_title":
        case 91:
            // json search title request (for "copy from" dialog)
            $DB->query('
				SELECT node_id as id, text as label, text as value
				  FROM nv_webdictionary
				 WHERE node_type = "item"
				   AND subtype = "title"
				   AND lang = ' . protect($_REQUEST['lang']) . '
				   AND website = ' . $website->id . '
				   AND text LIKE ' . protect('%' . $_REQUEST['title'] . '%') . '
		      ORDER BY text ASC
			     LIMIT 20', 'array');
            echo json_encode($DB->result());
            core_terminate();
            break;
        case "raw_zone_content":
            // return raw item contents
            if (empty($_REQUEST['section'])) {
                $_REQUEST['section'] = 'main';
            }
            if ($_REQUEST['history'] == 'true') {
                $DB->query('SELECT text
							  FROM nv_webdictionary_history
							 WHERE node_type = "item"
							   AND website = ' . $website->id . ' 
							   AND id = ' . protect($_REQUEST['id']), 'array');
                $data = $DB->first();
                echo $data['text'];
            } else {
                if ($_REQUEST['zone'] == 'section') {
                    $DB->query('SELECT text
							  FROM nv_webdictionary
							 WHERE node_type = "item"
							   AND subtype = ' . protect('section-' . $_REQUEST['section']) . '
							   AND lang = ' . protect($_REQUEST['lang']) . '
							   AND website = ' . $website->id . ' 
							   AND node_id = ' . protect($_REQUEST['node_id']), 'array');
                    $data = $DB->first();
                    echo $data['text'];
                } else {
                    if ($_REQUEST['zone'] == 'property') {
                        $DB->query('SELECT text
							  FROM nv_webdictionary
							 WHERE node_type = "property-item"
							   AND subtype = ' . protect('property-' . $_REQUEST['section'] . '-' . $_REQUEST['lang']) . '
							   AND lang = ' . protect($_REQUEST['lang']) . '
							   AND website = ' . $website->id . '
							   AND node_id = ' . protect($_REQUEST['node_id']), 'array');
                        $data = $DB->first();
                        echo $data['text'];
                    }
                }
            }
            core_terminate();
            break;
            // return raw template content
        // return raw template content
        case 93:
            $DB->query('SELECT file
						  FROM nv_templates
						 WHERE enabled = 1
						   AND id = ' . protect($_REQUEST['id']) . '
						   AND website = ' . $website->id, 'array');
            $data = $DB->first();
            echo @file_get_contents(NAVIGATE_PRIVATE . '/' . $website->id . '/templates/' . $data['file']);
            core_terminate();
            break;
        case "copy_from_template_zones":
            // return template sections and (textarea) properties for a content id
            $item = new item();
            $item->load(intval($_REQUEST['id']));
            $template = $item->load_template();
            $zones = array();
            for ($ts = 0; $ts < count($template->sections); $ts++) {
                $title = $template->sections[$ts]['name'];
                if (!empty($theme)) {
                    $title = $theme->t($title);
                }
                if ($title == '#main#') {
                    $title = t(238, 'Main content');
                }
                $zones[] = array('type' => 'section', 'id' => $template->sections[$ts]['id'], 'title' => $title);
            }
            for ($ps = 0; $ps < count($template->properties); $ps++) {
                // ignore structure properties
                if (isset($template->properties[$ps]->element) && $template->properties[$ps]->element != 'item') {
                    continue;
                }
                // ignore non-textual properties
                if (!in_array($template->properties[$ps]->type, array("text", "textarea", "rich_textarea"))) {
                    continue;
                }
                $title = $template->properties[$ps]->name;
                if (!empty($theme)) {
                    $title = $theme->t($title);
                }
                $zones[] = array('type' => 'property', 'id' => $template->properties[$ps]->id, 'title' => $title);
            }
            echo json_encode($zones);
            core_terminate();
            break;
        case 95:
            // free path checking
            $path = $_REQUEST['path'];
            $id = $_REQUEST['id'];
            $DB->query('SELECT type, object_id, lang
	 					  FROM nv_paths
						 WHERE path = ' . protect($path) . '
						   AND website = ' . $website->id);
            $rs = $DB->result();
            echo json_encode($rs);
            core_terminate();
            break;
        case 96:
            // return category paths
            echo json_encode(path::loadElementPaths('structure', intval($_REQUEST['id'])));
            core_terminate();
            break;
        case 'json_find_user':
            // json find user by name request (for "moderator" autocomplete)
            $DB->query('
				SELECT id, username as text
				  FROM nv_users
				 WHERE username LIKE ' . protect('%' . $_REQUEST['username'] . '%') . '
		      ORDER BY username ASC
			     LIMIT 30', 'array
			');
            $rows = $DB->result();
            $total = $DB->foundRows();
            echo json_encode(array('items' => $rows, 'total_count' => $total));
            core_terminate();
            break;
        case 'json_find_item':
            // find items by its title
            // any language
            $template_filter = '';
            if (!empty($_REQUEST['template'])) {
                $template_filter = ' AND nvi.template = ' . protect($_REQUEST['template']) . ' ';
            }
            if (!empty($_REQUEST['association'])) {
                $template_filter = ' AND nvi.association = ' . protect($_REQUEST['association']) . ' ';
            }
            if (isset($_REQUEST['embedding'])) {
                $template_filter = ' AND nvi.embedding = ' . protect($_REQUEST['embedding']) . ' ';
            }
            $text = $_REQUEST['title'];
            if (!empty($_REQUEST['term'])) {
                // tagit request
                $text = $_REQUEST['term'];
            }
            $DB->query('
				SELECT SQL_CALC_FOUND_ROWS DISTINCT nvw.node_id as id, nvw.text as text
				  FROM nv_webdictionary nvw, nv_items nvi
				 WHERE nvw.node_type = "item"
				   AND nvw.node_id = nvi.id
				   ' . $template_filter . '
				   AND nvw.subtype = "title"
				   AND nvw.website = ' . $website->id . '
				   AND nvw.website = nvi.website
				   AND nvw.text LIKE ' . protect('%' . $text . '%') . '
		        GROUP BY nvw.node_id, nvw.text
		        ORDER BY nvw.text ASC
			     LIMIT ' . intval($_REQUEST['page_limit']) . '
			     OFFSET ' . max(0, intval($_REQUEST['page_limit']) * (intval($_REQUEST['page']) - 1)), 'array');
            $rows = $DB->result();
            $total = $DB->foundRows();
            if ($_REQUEST['association'] == 'free') {
                for ($i = 0; $i < count($rows); $i++) {
                    $rows[$i]['path'] = $DB->query_single('path', 'nv_paths', '	website = ' . protect($website->id) . ' AND 
							type="item" AND 
							object_id="' . $rows[$i]['id'] . '" AND 
							lang="' . $website->languages_list[0] . '"
						');
                    if (empty($rows[$i]['path'])) {
                        $rows[$i]['path'] = '/node/' . $rows[$i]['id'];
                    }
                }
            }
            if (empty($_REQUEST['format']) || $_REQUEST['format'] == 'select2') {
                echo json_encode(array('items' => $rows, 'totalCount' => $total));
            } else {
                if ($_REQUEST['format'] == 'tagit') {
                    $tags_json = array();
                    foreach ($rows as $row) {
                        $tags_json[] = json_decode('{ "id": "' . $row['id'] . '", "label": "' . $row['text'] . '", "value": "' . $row['text'] . '" }');
                    }
                    echo json_encode($tags_json);
                }
            }
            core_terminate();
            break;
        case 98:
            // change comment status
            if (empty($_REQUEST['id'])) {
                echo "false";
                core_terminate();
            }
            switch ($_REQUEST['opt']) {
                case 'publish':
                    $DB->execute('
						UPDATE nv_comments
						   SET status = 0
						 WHERE website = ' . $website->id . ' AND
						       id = ' . $_REQUEST['id']);
                    break;
                case 'unpublish':
                    $DB->execute('
						UPDATE nv_comments
						   SET status = 1
						 WHERE website = ' . $website->id . ' AND
						       id = ' . $_REQUEST['id']);
                    break;
                case 'delete':
                    $DB->execute('
						DELETE FROM nv_comments
						 WHERE website = ' . $website->id . ' AND
							   id = ' . $_REQUEST['id']);
                    break;
            }
            $error = $DB->get_last_error();
            if (empty($error)) {
                echo 'true';
            } else {
                echo 'false';
            }
            core_terminate();
            break;
        case 'autosave':
            if (!empty($_REQUEST['id'])) {
                $iDictionary = array();
                foreach ($_REQUEST as $key => $value) {
                    if (strpos($key, 'section-') === 0) {
                        $lang = substr($key, -2, 2);
                        $kname = substr($key, 0, strlen($key) - 3);
                        $iDictionary[$lang][$kname] = $value;
                    }
                }
                $changed = webdictionary_history::save_element_strings('item', intval($_REQUEST['id']), $iDictionary, true);
                if ($changed) {
                    echo 'changes_saved';
                } else {
                    echo 'no_changes';
                }
                core_terminate();
            }
            echo 'false';
            core_terminate();
            break;
        case 'votes_reset':
            webuser_vote::remove_object_votes('item', intval($_REQUEST['id']));
            echo 'true';
            core_terminate();
            break;
        case 'votes_by_webuser':
            if ($_POST['oper'] == 'del') {
                $ids = explode(',', $_POST['id']);
                for ($i = 0; $i < count($ids); $i++) {
                    if ($ids[$i] > 0) {
                        $vote = new webuser_vote();
                        $vote->load($ids[$i]);
                        $vote->delete();
                    }
                }
                webuser_vote::update_object_score('item', $vote->object_id);
                echo 'true';
                core_terminate();
            }
            $max = intval($_GET['rows']);
            $page = intval($_GET['page']);
            $offset = ($page - 1) * $max;
            if ($_REQUEST['_search'] == 'false') {
                list($dataset, $total) = webuser_vote::object_votes_by_webuser('item', intval($_REQUEST['id']), $_REQUEST['sidx'] . ' ' . $_REQUEST['sord'], $offset, $max);
            }
            $out = array();
            for ($i = 0; $i < count($dataset); $i++) {
                if (empty($dataset[$i])) {
                    continue;
                }
                $out[$i] = array(0 => $dataset[$i]['id'], 1 => core_ts2date($dataset[$i]['date'], true), 2 => $dataset[$i]['username']);
            }
            navitable::jqgridJson($out, $page, $offset, $max, $total);
            core_terminate();
            break;
        case 'items_order':
            if (!empty($_POST['items-order'])) {
                // save new order
                $response = item::reorder($_POST['items-order']);
                if ($response !== true) {
                    echo $response['error'];
                } else {
                    echo 'true';
                }
            } else {
                // show ordered list
                echo items_order($_REQUEST['category']);
            }
            core_terminate();
            break;
        case 'json_tags_search':
            $tags = nvweb_tags_retrieve(null, null, 'top', $_REQUEST['term'], $_REQUEST['lang']);
            $tags_json = array();
            foreach (array_keys($tags) as $tag) {
                $tags_json[] = json_decode('{ "id": "' . $tag . '", "label": "' . $tag . '", "value": "' . $tag . '" }');
            }
            echo json_encode($tags_json);
            core_terminate();
            break;
        case 'json_tags_ranking':
            $tags = nvweb_tags_retrieve(100, null, 'top', null, $_REQUEST['lang']);
            $tags = array_keys($tags);
            echo json_encode($tags);
            core_terminate();
            break;
        case 'list':
        case 0:
            // list / search result
        // list / search result
        default:
            $out = items_list();
            break;
    }
    return $out;
}
function nvweb_comments($vars = array())
{
    global $website;
    global $DB;
    global $current;
    global $webgets;
    global $dictionary;
    global $webuser;
    global $theme;
    global $events;
    global $session;
    $webget = 'comments';
    if (!isset($webgets[$webget])) {
        $webgets[$webget] = array();
        global $lang;
        if (empty($lang)) {
            $lang = new language();
            $lang->load($current['lang']);
        }
        // default translations
        $webgets[$webget]['translations'] = array('post_a_comment' => t(379, 'Post a comment'), 'name' => t(159, 'Name'), 'email' => t(44, 'E-Mail'), 'website' => t(177, 'Website'), 'message' => t(380, 'Message'), 'email_will_not_be_published' => t(381, 'E-Mail will not be published'), 'submit' => t(382, 'Submit'), 'sign_in_or_sign_up_to_post_a_comment' => t(383, 'Sign in or Sign up to post a comment'), 'comments_on_this_entry_are_closed' => t(384, 'Comments on this entry are closed'), 'please_dont_leave_any_field_blank' => t(385, 'Please don\'t leave any field blank'), 'your_comment_has_been_received_and_will_be_published_shortly' => t(386, 'Your comment has been received and will be published shortly'), 'new_comment' => t(387, 'New comment'), 'review_comments' => t(388, 'Review comments'));
        // theme translations
        // if the web theme has custom translations for this string subtypes, use it (for the user selected language)
        /* just add the following translations to your json theme dictionary:
        
        			"post_a_comment": "Post a comment",
        			"name": "Name",
        			"email": "E-Mail",
        			"website": "Website",
        			"message": "Message",
        			"email_will_not_be_published": "E-Mail will not be published",
        			"submit": "Submit",
        			"sign_in_or_sign_up_to_post_a_comment": "Sign in or Sign up to post a comment",
        			"comments_on_this_entry_are_closed": "Comments on this entry are closed",
        			"please_dont_leave_any_field_blank": "Please don't leave any field blank",
        			"your_comment_has_been_received_and_will_be_published_shortly": "Your comment has been received and will be published shortly",
        			"new_comment": "New comment",
        			"review_comments": "Review comments"
        		*/
        if (!empty($website->theme) && method_exists($theme, 't')) {
            foreach ($webgets[$webget]['translations'] as $code => $text) {
                $theme_translation = $theme->t($code);
                if (!empty($theme_translation) && $theme_translation != $code) {
                    $webgets[$webget]['translations'][$code] = $theme_translation;
                }
            }
        }
    }
    // set default callback
    if (empty($vars['callback'])) {
        $vars['callback'] = 'alert';
    }
    // check callback attributes
    $callback = $vars['callback'];
    if (!empty($vars['alert_callback'])) {
        $callback = $vars['alert_callback'];
    } else {
        if (!empty($vars['callback_alert'])) {
            $callback = $vars['callback_alert'];
        }
    }
    $callback_error = $callback;
    if (!empty($vars['error_callback'])) {
        $callback_error = $vars['error_callback'];
    } else {
        if (!empty($vars['callback_error'])) {
            $callback_error = $vars['callback_error'];
        }
    }
    $out = '';
    // if the current page belongs to a structure entry
    // we need to get the associated elements to retrieve and post its comments
    // (because structure entry pages can't have associated comments)
    // so, ONLY the FIRST element associated to a category can have comments in a structure entry page
    // (of course if the element has its own page, it can have its own comments)
    $element = $current['object'];
    if ($current['type'] == 'structure') {
        if (empty($current['structure_elements'])) {
            $current['structure_elements'] = $element->elements();
        }
        $element = $current['structure_elements'][0];
    }
    switch (@$vars['mode']) {
        case 'process':
            if (isset($_GET['nv_approve_comment'])) {
                // process 1-click comment approval
                $comment = new comment();
                $comment->load($_GET['id']);
                if (!empty($comment->id) && $comment->status == -1) {
                    $hash = $_GET['hash'];
                    if ($hash == sha1($comment->id . $comment->email . APP_UNIQUE . serialize($website->contact_emails))) {
                        // hash check passed
                        $comment->status = 0;
                        $comment->save();
                        $response = t(555, "Item has been successfully published.");
                        if ($vars['notify'] == 'inline' || $callback == 'inline') {
                            $out = '<div class="comment-success">' . $response . '</div>';
                        } else {
                            if (!isset($vars['notify']) || $vars['notify'] == 'callback') {
                                nvweb_after_body("js", $callback . '("' . $response . '");');
                            }
                        }
                    } else {
                        $response = t(344, "Security error");
                        if ($vars['notify'] == 'inline' || $callback_error == 'inline') {
                            $out = '<div class="comment-error">' . $response . '</div>';
                        } else {
                            if (!isset($vars['notify']) || $vars['notify'] == 'callback') {
                                nvweb_after_body("js", $callback_error . '("' . $response . '");');
                            }
                        }
                    }
                } else {
                    $response = t(56, "Unexpected error");
                    if ($vars['notify'] == 'inline' || $callback_error == 'inline') {
                        $out = '<div class="comment-error">' . $response . '</div>';
                    } else {
                        if (!isset($vars['notify']) || $vars['notify'] == 'callback') {
                            nvweb_after_body("js", $callback_error . '("' . $response . '");');
                        }
                    }
                }
            }
            if (isset($_GET['nv_remove_comment'])) {
                // process 1-click comment removal
                $comment = new comment();
                $comment->load($_GET['id']);
                if (!empty($comment->id) && $comment->status == -1) {
                    $hash = $_GET['hash'];
                    if ($hash == sha1($comment->id . $comment->email . APP_UNIQUE . serialize($website->contact_emails))) {
                        // hash check passed
                        $comment->delete();
                        $response = t(55, "Item successfully deleted");
                        if ($vars['notify'] == 'inline' || $callback == 'inline') {
                            $out = '<div class="comment-success">' . $response . '</div>';
                        } else {
                            if (!isset($vars['notify']) || $vars['notify'] == 'callback') {
                                nvweb_after_body("js", $callback . '("' . $response . '");');
                            }
                        }
                    } else {
                        $response = t(344, "Security error");
                        if ($vars['notify'] == 'inline' || $callback_error == 'inline') {
                            $out = '<div class="comment-error">' . $response . '</div>';
                        } else {
                            if (!isset($vars['notify']) || $vars['notify'] == 'callback') {
                                nvweb_after_body("js", $callback_error . '("' . $response . '");');
                            }
                        }
                    }
                } else {
                    $response = t(56, "Unexpected error");
                    if ($vars['notify'] == 'inline' || $callback_error == 'inline') {
                        $out = '<div class="comment-error">' . $response . '</div>';
                    } else {
                        if (!isset($vars['notify']) || $vars['notify'] == 'callback') {
                            nvweb_after_body("js", $callback_error . '("' . $response . '");');
                        }
                    }
                }
            }
            if ($_REQUEST['form-type'] == 'comment-reply' || isset($_POST[$vars['field-message']])) {
                // add comment
                if (empty($vars['field-name'])) {
                    $vars['field-name'] = 'reply-name';
                }
                if (empty($vars['field-email'])) {
                    $vars['field-email'] = 'reply-email';
                }
                if (empty($vars['field-url'])) {
                    $vars['field-url'] = 'reply-url';
                }
                if (empty($vars['field-message'])) {
                    $vars['field-message'] = 'reply-message';
                }
                if (!empty($vars['element'])) {
                    $element = $vars['element'];
                }
                $comment_name = @$_REQUEST[$vars['field-name']];
                $comment_email = @$_REQUEST[$vars['field-email']];
                $comment_url = @$_REQUEST[$vars['field-url']];
                $comment_message = @$_REQUEST[$vars['field-message']];
                if ((empty($comment_name) || empty($comment_email)) && empty($webuser->id) || empty($comment_message)) {
                    $response = $webgets[$webget]['translations']['please_dont_leave_any_field_blank'];
                    if ($vars['notify'] == 'inline' || $callback_error == 'inline') {
                        $out = '<div class="comment-error">' . $response . '</div>';
                    } else {
                        if (!isset($vars['notify']) || $vars['notify'] == 'callback') {
                            nvweb_after_body("js", $callback_error . '("' . $response . '");');
                        }
                    }
                    return $out;
                }
                $status = -1;
                // new comment, not approved
                if (empty($element->comments_moderator)) {
                    $status = 0;
                }
                // all comments auto-approved
                // remove any <nv /> or {{nv}} tag
                $comment_name = core_remove_nvtags($comment_name);
                $comment_name = strip_tags($comment_name);
                $comment_message = core_remove_nvtags($comment_message);
                $comment = new comment();
                $comment->id = 0;
                $comment->website = $website->id;
                $comment->item = $element->id;
                $comment->user = empty($webuser->id) ? 0 : $webuser->id;
                $comment->name = $comment_name;
                $comment->email = filter_var($comment_email, FILTER_SANITIZE_EMAIL);
                $comment->url = filter_var($comment_url, FILTER_SANITIZE_URL);
                $comment->ip = core_ip();
                $comment->date_created = core_time();
                $comment->date_modified = 0;
                $comment->status = $status;
                $comment->message = $comment_message;
                $properties = array();
                // check if there are comment properties values
                if (isset($vars['field-properties-prefix'])) {
                    // check every possible property
                    $e_properties = property::elements($element->template, 'comment');
                    for ($ep = 0; $ep < count($e_properties); $ep++) {
                        if (isset($_POST[$vars['field-properties-prefix'] . $e_properties[$ep]->id])) {
                            $properties[$e_properties[$ep]->id] = $_POST[$vars['field-properties-prefix'] . $e_properties[$ep]->id];
                        }
                    }
                }
                // trigger the "new_comment" event through the extensions system before inserting it!
                $extensions_messages = $events->trigger('comment', 'before_insert', array('comment' => $comment, 'properties' => $properties));
                foreach ($extensions_messages as $ext_name => $ext_result) {
                    if (isset($ext_result['error'])) {
                        $response = $ext_result['error'];
                        if ($vars['notify'] == 'inline' || $callback_error == 'inline') {
                            $out = '<div class="comment-error">' . $response . '</div>';
                        } else {
                            if (!isset($vars['notify']) || $vars['notify'] == 'callback') {
                                nvweb_after_body("js", $callback_error . '("' . $response . '");');
                            }
                        }
                        return $out;
                    }
                }
                $comment->insert();
                if (!empty($properties)) {
                    property::save_properties_from_array('comment', $comment->id, $element->template, $properties);
                }
                // reload the element to retrieve the new comments
                $element = new item();
                $element->load($comment->item);
                if ($current['type'] == 'item' && !isset($vars['element'])) {
                    $current['object'] = $element;
                }
                // trigger the "new_comment" event through the extensions system
                $events->trigger('comment', 'after_insert', array('comment' => &$comment, 'properties' => $properties));
                if (!empty($comment->id)) {
                    if ($status == -1) {
                        $response = $webgets[$webget]['translations']['your_comment_has_been_received_and_will_be_published_shortly'];
                        if ($vars['notify'] == 'inline' || $callback_error == 'inline') {
                            $out = '<div class="comment-success">' . $response . '</div>';
                        } else {
                            if (!isset($vars['notify']) || $vars['notify'] == 'callback') {
                                nvweb_after_body("js", $callback . '("' . $response . '");');
                            }
                        }
                    } else {
                        $response = $webgets[$webget]['translations']['your_comment_has_been_received_and_will_be_published_shortly'];
                        if ($vars['notify'] == 'inline' || $callback_error == 'inline') {
                            $out = '<div class="comment-success">' . $response . '</div>';
                        } else {
                            if (!isset($vars['notify']) || $vars['notify'] == 'callback') {
                                nvweb_after_body("js", $callback . '("' . $response . '");');
                            }
                        }
                    }
                }
                $notify_addresses = $website->contact_emails;
                if (!empty($element->comments_moderator)) {
                    $notify_addresses[] = user::email_of($element->comments_moderator);
                }
                $hash = sha1($comment->id . $comment->email . APP_UNIQUE . serialize($website->contact_emails));
                $base_url = nvweb_source_url('element', $element->id);
                // default colors
                $background_color = '#E5F1FF';
                $text_color = '#595959';
                $title_color = '#595959';
                $background_color_db = $DB->query_single('value', 'nv_permissions', 'name = ' . protect("nvweb.comments.background_color") . ' AND website = ' . protect($website->id), 'id DESC');
                $text_color_db = $DB->query_single('value', 'nv_permissions', 'name = ' . protect("nvweb.comments.text_color") . ' AND website = ' . protect($website->id), 'id DESC');
                $title_color_db = $DB->query_single('value', 'nv_permissions', 'name = ' . protect("nvweb.comments.titles_color") . ' AND website = ' . protect($website->id), 'id DESC');
                if (!empty($background_color_db)) {
                    $background_color = str_replace('"', '', $background_color_db);
                }
                if (!empty($text_color_db)) {
                    $text_color = str_replace('"', '', $text_color_db);
                }
                if (!empty($title_color_db)) {
                    $title_color = str_replace('"', '', $title_color_db);
                }
                $message = navigate_compose_email(array(array('title' => t(9, 'Content'), 'content' => $element->dictionary[$current['lang']]['title']), array('title' => $webgets[$webget]['translations']['name'], 'content' => $comment_name . @$webuser->username), array('title' => $webgets[$webget]['translations']['email'], 'content' => $comment_email . @$webuser->email), array('title' => $webgets[$webget]['translations']['website'], 'content' => $comment_url . @$webuser->social_website), array('title' => $webgets[$webget]['translations']['message'], 'content' => nl2br($comment_message)), array('footer' => '<a href="' . NAVIGATE_URL . '/' . NAVIGATE_MAIN . '?wid=' . $website->id . '&fid=10&act=2&tab=5&id=' . $element->id . '"><strong>' . $webgets[$webget]['translations']['review_comments'] . '</strong></a>' . '&nbsp;&nbsp;|&nbsp;&nbsp;' . '<a style=" color: #008830" href="' . $base_url . '?nv_approve_comment&id=' . $comment->id . '&hash=' . $hash . '">' . t(258, "Publish") . '</a>' . '&nbsp;&nbsp;|&nbsp;&nbsp;' . '<a style=" color: #FF0090" href="' . $base_url . '?nv_remove_comment&id=' . $comment->id . '&hash=' . $hash . '">' . t(525, "Remove comment (without confirmation)") . '</a>')), array('background' => $background_color, 'title-color' => $title_color, 'content-color' => $text_color));
                // trying to implement One-Click actions (used in Google GMail)
                // You need to be registered with Google first: https://developers.google.com/gmail/markup/registering-with-google
                $one_click_actions = '
                    <script type="application/ld+json">
                    {
                        "@context": "http://schema.org",
                        "@type": "EmailMessage",
                        "potentialAction":
                        {
                            "@type": "ViewAction",
                            "name": "' . $webgets[$webget]['translations']['review_comments'] . '",
                            "url": "' . NAVIGATE_URL . '/' . NAVIGATE_MAIN . '?wid=' . $website->id . '&fid=10&act=2&tab=5&id=' . $element->id . '"
                        }
                    }
                    </script>
				';
                $message = '<html><head>' . $one_click_actions . '</head><body>' . $message . '</body></html>';
                foreach ($website->contact_emails as $contact_address) {
                    @nvweb_send_email($website->name . ' | ' . $webgets[$webget]['translations']['new_comment'], $message, $contact_address, null, true);
                }
            }
            break;
        case 'reply':
            if ($element->comments_enabled_to == 2 && empty($webuser->id)) {
                // Post a comment form (unsigned users)
                $out = '
					<div class="comments-reply">
						<div><div class="comments-reply-info">' . $webgets[$webget]['translations']['post_a_comment'] . '</div></div>
						<br />
						<form action="' . NVWEB_ABSOLUTE . '/' . $current['route'] . '" method="post">
							<input type="hidden" name="form-type" value="comment-reply" />
							<div class="comments-reply-field"><label>' . $webgets[$webget]['translations']['name'] . '</label> <input type="text" name="reply-name" value="" /></div>
							<div class="comments-reply-field"><label>' . $webgets[$webget]['translations']['email'] . ' *</label> <input type="text" name="reply-email" value="" /></div>
							<div class="comments-reply-field"><label>' . $webgets[$webget]['translations']['message'] . '</label> <textarea name="reply-message"></textarea></div>
							<!-- {{navigate-comments-reply-extra-fields-placeholder}} -->
							<div class="comments-reply-field comments-reply-field-info-email"><label>&nbsp;</label> * ' . $webgets[$webget]['translations']['email_will_not_be_published'] . '</div>
							<div class="comments-reply-field comments-reply-field-submit"><input class="comments-reply-submit" type="submit" value="' . $webgets[$webget]['translations']['submit'] . '" /></div>
						</form>
					</div>
				';
                $extensions_messages = $events->trigger('comment', 'reply_extra_fields', array('html' => &$out));
                // add any extra field generated
                if (!empty($extensions_messages)) {
                    $extra_fields = array_map(function ($v) {
                        return $v;
                    }, array_values($extensions_messages));
                    $out = str_replace('<!-- {{navigate-comments-reply-extra-fields-placeholder}} -->', implode("\n", $extra_fields), $out);
                }
            } else {
                if ($element->comments_enabled_to > 0 && !empty($webuser->id)) {
                    // Post a comment form (signed in users)
                    if (empty($vars['avatar_size'])) {
                        $vars['avatar_size'] = 32;
                    }
                    $avatar_url = NVWEB_OBJECT . '?type=blank';
                    if (!empty($webuser->avatar)) {
                        $avatar_url = NVWEB_OBJECT . '?wid=' . $website->id . '&id=' . $webuser->avatar . '&amp;disposition=inline&width=' . $vars['avatar_size'] . '&height=' . $vars['avatar_size'];
                    }
                    $out = '
					<div class="comments-reply">
						<div><div class="comments-reply-info">' . $webgets[$webget]['translations']['post_a_comment'] . '</div></div>
						<br />
						<form action="' . NVWEB_ABSOLUTE . '/' . $current['route'] . '" method="post">
							<input type="hidden" name="form-type" value="comment-reply" />
							<div class="comments-reply-field"><label style="display: none;">&nbsp;</label> <img src="' . $avatar_url . '" width="' . $vars['avatar_size'] . '" height="' . $vars['avatar_size'] . '" align="absmiddle" /> <span class="comments-reply-username">' . $webuser->username . '</span><a class="comments-reply-signout" href="?webuser_signout">(x)</a></div>
							<br />
							<div class="comments-reply-field"><label>' . $webgets[$webget]['translations']['message'] . '</label> <textarea name="reply-message"></textarea></div>
							<!-- {{navigate-comments-reply-extra-fields-placeholder}} -->
							<div class="comments-reply-field-submit"><input class="comments-reply-submit" type="submit" value="' . $webgets[$webget]['translations']['submit'] . '" /></div>
						</form>
					</div>
				';
                    $extensions_messages = $events->trigger('comment', 'reply_extra_fields', array('html' => $out));
                    // add any extra field generated
                    if (!empty($extensions_messages)) {
                        $extra_fields = array_map(function ($v) {
                            return $v;
                        }, array_values($extensions_messages));
                        $out = str_replace('<!-- {{navigate-comments-reply-extra-fields-placeholder}} -->', implode("\n", $extra_fields), $out);
                    }
                } else {
                    if ($element->comments_enabled_to == 1) {
                        $out = '<div class="comments-reply">
                            <div class="comments-reply-info">' . $webgets[$webget]['translations']['sign_in_or_sign_up_to_post_a_comment'] . '</div>
                        </div>';
                    } else {
                        $out = '<div class="comments-reply">
                            <div class="comments-reply-info">' . $webgets[$webget]['translations']['comments_on_this_entry_are_closed'] . '</div>
                        </div>';
                    }
                }
            }
            break;
        case 'comments':
            setlocale(LC_ALL, $website->languages[$session['lang']]['system_locale']);
            list($comments, $comments_total) = nvweb_comments_list(0, NULL, NULL, $vars['order']);
            // get all comments of the current entry
            if (empty($vars['avatar_size'])) {
                $vars['avatar_size'] = '48';
            }
            if (empty($vars['date_format'])) {
                $vars['date_format'] = '%d %B %Y %H:%M';
            }
            for ($c = 0; $c < $comments_total; $c++) {
                $avatar = $comments[$c]->avatar;
                if (!empty($avatar)) {
                    $avatar = '<img src="' . NVWEB_OBJECT . '?type=image&id=' . $avatar . '" width="' . $vars['avatar_size'] . 'px" height="' . $vars['avatar_size'] . 'px"/>';
                } else {
                    $avatar = '<img src="data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" width="' . $vars['avatar_size'] . 'px" height="' . $vars['avatar_size'] . 'px"/>';
                }
                $comment = new comment();
                $comment->load_from_resultset(array($comments[$c]));
                $depth = 'data-depth="' . $comment->depth() . '"';
                $out .= '
					<div class="comment"' . $depth . '>
						<div class="comment-avatar">' . $avatar . '</div>
						<div class="comment-username">' . (!empty($comments[$c]->username) ? $comments[$c]->username : $comments[$c]->name) . '</div>
						<div class="comment-date">' . Encoding::toUTF8(strftime($vars['date_format'], $comments[$c]->date_created)) . '</div>
						<div class="comment-message">' . nl2br($comments[$c]->message) . '</div>
						<div style="clear:both"></div>
					</div>
				';
            }
            break;
    }
    return $out;
}