media_objects
Github

	function media_objects() {
#		$img = module('dynamic')->placeholder_img(array('width' => 300, 'height' => 200));
		$img = url('/dynamic/placeholder/64x64');
		$body = 'Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.';
		$date = date('Y-m-d H:i:s');

		return _class('html')->media_objects([
			11 => [
				'link'	=> url('/comments/view/11'),
				'img'	=> $img,
				'alt'	=> '64x64',
				'head'	=> 'Comment 1',
				'body'	=> $body,
				'date'	=> $date,
			],
			22 => [
				'link'	=> url('/comments/view/22'),
				'img'	=> $img,
				'alt'	=> '64x64',
				'head'	=> 'Comment 2',
				'body'	=> $body,
				'date'	=> $date,
			],
			33 => [
				'link'	=> url('/comments/view/33'),
				'img'	=> $img,
				'alt'	=> '64x64',
				'head'	=> 'Comment 3',
				'body'	=> $body,
				'parent_id'	=> 22,
			],
			44 => [
				'link'	=> url('/comments/view/44'),
				'img'	=> $img,
				'body'	=> $body,
				'date'	=> $date,
				'parent_id'	=> 33,
			],
			55 => [
				'img'	=> $img,
				'body'	=> $body,
				'parent_id'	=> 44,
			],
			66 => [
				'link'	=> url('/comments/view/66'),
				'img'	=> $img,
				'alt'	=> '64x64',
				'head'	=> 'Comment 6',
				'body'	=> $body,
				'date'	=> $date,
			],
		]);
	}
	function media_objects($data = [], $extra = []) {
		$extra['id'] = $extra['id'] ?: __FUNCTION__.'_'.++$this->_ids[__FUNCTION__];
		if ($data) {
			$data = $this->_recursive_sort_items($data);
		}
		$img_class = ($extra['img_class'] ?: 'media-object'). ($extra['img_class_add'] ? ' '.$extra['img_class_add'] : '');
		$keys = array_keys($data);
		$keys_counter = array_flip($keys);
		$items = [];
		foreach ((array)$data as $id => $item) {
			$next_id = $keys[$keys_counter[$id] + 1];
			$next_item = $next_id ? $data[$next_id] : [];
			$close_num_levels = 1;
			if ($next_item) {
				$close_num_levels = $item['level'] - $next_item['level'] + 1;
				if ($close_num_levels < 0) {
					$close_num_levels = 0;
				}
			} elseif ($item['level'] > 0) {
				$close_num_levels = $item['level'] + 1;
			}
			$items[] = '
				<div class="media">
					<a class="pull-left"'.($item['link'] ? ' href="'.$item['link'].'"' : '').'>'
					.'<img class="'.$img_class.'" alt="'.$item['alt'].'" src="'.$item['img'].'"'.($item['img_width'] ? ' width="'.$item['img_width'].'"' : '').($item['img_height'] ? ' height="'.$item['img_height'].'"' : '').'></a>
					<div class="media-body">
						<h4 class="media-heading">'
						.($item['link'] ? '<a href="'.$item['link'].'">' : ''). $item['head']. ($item['link'] ? '</a>' : '')
						.($item['date'] ? ' <small class="pull-right">'._format_date($item['date'], $extra['date_format'] ?: 'full').'</small>' : '')
						. '</h4>'
						.$item['body'].'
			';
			if ($close_num_levels) {
				$items[] = str_repeat(PHP_EOL.'</div></div>'.PHP_EOL, $close_num_levels);
			}
		}
		return '<div class="media-objects'.($extra['class'] ? ' '.$extra['class'] : '').'" id="'.$extra['id'].'">'.implode(PHP_EOL, (array)$items).'</div>';
	}
64x64

Comment 1 2018-12-12 15:46:34

Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
64x64

Comment 2 2018-12-12 15:46:34

Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
64x64

Comment 3

Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.

 2018-12-12 15:46:34

Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.

Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.
64x64

Comment 6 2018-12-12 15:46:34

Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec lacinia congue felis in faucibus.