Саша Туманов

Саша Туманов

С нами с 11 марта 2013; Место в рейтинге пользователей: #132
Саша Туманов
20 апреля 2020, 22:05
1
+1
Вот готовое к использованию для вывода ленты юзера:

<?php
$cacheKey = "insta_".md5($url);

if (!$pdo = $modx->getService('pdoTools')) return false;
$returnCache = $modx->cacheManager->get("$cacheKey");
$data = '';

if(!$returnCache) {
	$doc = new DOMDocument();
	libxml_use_internal_errors(true);
	$doc->loadHTMLFile($url);
	libxml_clear_errors();
	$xpath = new DOMXpath($doc);
	$sharedData = $xpath->query("//html/body/script[1]")->item(0)->textContent;
	preg_match_all('/window\._sharedData = \{(.*)\};/ism', $sharedData, $matches);
	if (!empty($matches[1][0])) {
		$res = json_decode('{' . $matches[1][0] . '}', true);
		
		$media = array_slice($res['entry_data']['ProfilePage'][0]['graphql']['user']['edge_owner_to_timeline_media']['edges'], 0, $limit);
		if (!empty($media)) {
			foreach ($media as $row) {
				$data .= $pdo->getChunk($tpl, array(
					// 'image'     => $row['node']['display_url'],
					'thumb'     => $row['node']['thumbnail_src'],
					// 'thumb_150' => $row['node']['thumbnail_resources'][0]['src'],
					'thumb_240' => $row['node']['thumbnail_resources'][1]['src']
				));
			}
		}
	}
	$modx->cacheManager->set($cacheKey, $data, 7200*60);
	return $data;
}

return $returnCache;

И вызов:

{$_modx->runSnippet("@FILE snippets/parseInsta.php", [
	'url' => 'https://www.instagram.com/someuser/',
	'limit' => 4,
	'tpl' => '@INLINE <a href="{$thumb}" class="gallery__item"><img src="{$thumb_240}" alt=""></a>'
])}
Саша Туманов
20 апреля 2020, 18:07
0
Вот тоже интересно. Хотелось бы хранить код модификаторов в файловой системе, причем не прибегая к штатной возможности создания статических файлов.
Почему-то конструкция предлагаемая Василием для вызова плагинов из файловой системы, в случае с модификаторами не работает.
if ($pdoTools = $modx->getService('pdoTools')) {
    $pdoTools->runSnippet('@FILE plugins/my_plugin.php', $scriptProperties);
}
Подозреваю, что дело в событии на которое навешивается плагин, но не уверен. Подскажите пожалуйста, как правильно подтягивать код модификаторов из файлов
Саша Туманов
03 апреля 2020, 17:23
0
В скайп стукните.
sasha.tumanov
Саша Туманов
09 сентября 2019, 07:35
0
Вот, вдруг кому-нибудь всё еще интересно. Создаю три tv для каждого контекста и показываю каждый только в соответствующем контексте:

if($modx->event->name == 'OnDocFormRender') {
	$tvs = [
		"tags_web",
		"tags_ua",
		"tags_en"
	];
	$context = $resource->get('context_key');
	$tohide = "";

	foreach ($tvs as $tv) {
		if (! $res = $modx->getObject('modTemplateVar', array('name' => $tv)))
			continue;
		$tv_id = $res->get("id");
		$tv_ctx = end(explode("_", $tv));
		if ($tv_ctx == $context) 
			continue;

		$tohide .= "'tv".$tv_id."',";
	}
	$tohide = rtrim($tohide, ',');
        
        // Такие функции смотреть в "manager/assets/modext/core/modx.js"
	$hideTVs = "MODx.hideTVs([{$tohide}]);";
	$modx->regClientStartupHTMLBlock("<script>
			Ext.onReady(function(){
				$hideTVs
			});
		</script>");
}

Ну и предыдущую логику тоже придется немного переделать.
Саша Туманов
15 июля 2016, 15:24
0
Похоже, ограничение выборки для join, задача нетривиальная. С помощью подзапроса, можно ограничить выборку из левой таблицы, до присоединения правой. В моем случае, можно было бы сначала получить через modX::getChildIds, массив id дочерних документов, а потом делать по ним выборку с группировкой из таблицы msResourceFile. Но, опять же, ограничение выборки для каждой группы при GROUP BY, так же оказалось не очень простой задачей. Поэтому, решил не суетиться, а просто ограничить длину результирующего массива с картинками для каждого дочернего ресурса, благо — записей там немного.

$gallerylimit = $modx->getOption('gallerylimit', $scriptProperties, 8);

foreach($res as $gallery) {
	foreach($gallery as $key => $image) {
		if($key > $gallerylimit-1) break;
		$smallsrc = $imagesdir.$image['resource_id']."/{$thumb}/".$image['file'];
		$fullsrc = $imagesdir.$image['resource_id']."/{$fullsize}/".$image['file'];
		$rows .= $pdotools->getChunk($tplRow, array(
			'smallsrc' => $smallsrc,
			'fullsrc' => $fullsrc,
			'title' => $image['name'],
			'alt' => $image['alt']
		));
	}
	$output .= $pdotools->getChunk($tplOuter, array(
		'rows' => $rows,
		'pagetitle' => $gallery[0]['pagetitle'],
		'content' => $gallery[0]['content']
	));
	unset($rows);
}
Саша Туманов
14 июля 2016, 19:45
0
Спасибо большое, парни!
Саша Туманов
14 июля 2016, 17:55
0
Вот скрин таблицы с картинками:



Вот полный код сниппета:

/* Возвращает галереи ms2gallery дочерних, относительно текущего ресурса, ресурсов */
$modx->addPackage('ms2gallery', MODX_CORE_PATH . 'components/ms2gallery/model/');
$pdotools = $modx->getService('pdoTools');
$tplRow = $modx->getOption('tplRow', $scriptProperties);
$tplOuter = $modx->getOption('tplOuter', $scriptProperties);
$thumb = $modx->getOption('thumb', $scriptProperties, '120x90');
$fullsize = $modx->getOption('fullsize', $scriptProperties, '800x600');
$limit = $modx->getOption('limit', $scriptProperties, 16);
$imagesdir = '/assets/images/resources/';
$base = $modx->config['base_url'];

$res = array();
$rows = '';
$output = '';

$q = $modx->newQuery('modResource', array(
	'parent' => $modx->resource->id
));
$q->innerJoin('msResourceFile', 'files', "files.resource_id = modResource.id");
$q->sortby('files.resource_id', 'ASC');
$q->limit($limit);
$q->select('pagetitle,content,uri,files.resource_id,files.file,files.name,files.alt');
$q->where(array(
		'published' => 1,
		'files.type' => 'image',
		'files.path:LIKE' => "%/{$thumb}%",
		'files.active' => 1
	)
);

if($q->prepare() && $q->stmt->execute()) {
	while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
		$res[$row['resource_id']][] = $row;
	}
}
foreach($res as $gallery) {
	foreach($gallery as $image) {
		$smallsrc = $imagesdir.$image['resource_id']."/{$thumb}/".$image['file'];
		$fullsrc = $imagesdir.$image['resource_id']."/{$fullsize}/".$image['file'];
		$rows .= $pdotools->getChunk($tplRow, array(
			'smallsrc' => $smallsrc,
			'fullsrc' => $fullsrc,
			'title' => $image['name'],
			'alt' => $image['alt']
		));
	}
	$output .= $pdotools->getChunk($tplOuter, array(
		'rows' => $rows,
		'pagetitle' => $gallery[0]['pagetitle'],
		'content' => $gallery[0]['content']
	));
	unset($rows);
}

return $output;

//Вызов на странице "Галереи"
[[!getInnerGallery?
    &thumb=`280x210`
    &fullsize=`800x600`
    &limit=`30`
    &tplOuter=`@INLINE <div class='gallerypage bottom20'>
                        <h1 class="externalfont boldfont font150 bottom20">[[+pagetitle]]</h1>
                        <div class='clear left shadow outlinegreen lightgreenbg paperclip containingblock bottom20'>[[+content]]</div>
                        [[+rows]]<br class='clear'/>
                    </div>`
    &tplRow=`@INLINE <a href='[[+fullsrc]]' class='cols col-3 col-4-m col-4-s modal textcenter'>
                    <img src='[[+smallsrc]]' title='[[+title]]' alt='[[+alt]]' />
                </a>`
]]

В простом MySQL, это вроде как решается с помощью подзапроса. А в xpdo, вроде как можно использовать подзапросы. Но собрать это в кучу, пока не хватает мозгов (
Саша Туманов
14 июля 2016, 15:07
0
Хотя бы думать в какую сторону, подскажите? )
Саша Туманов
06 июля 2016, 00:09
0
Как вот, только, теперь задать чанк для пустой выборки, чтоб не обрабатывался парсером без нужды?
Саша Туманов
17 февраля 2016, 19:50
+1
Да, Babel. Делал, в основном, по Васиной инструкции.

Плагин переключающий контексты:
<?php
// Работаем только на фронтенде и только с friendly urls
if ($modx->event->name != 'OnHandleRequest' || $modx->context->key == 'mgr' || !$modx->getOption('friendly_urls')) {return;}

// Получаем запрашиваемый url
$alias = $modx->getOption('request_param_alias', null, 'alias', true);
$request = &$_REQUEST[$alias];

// Выбираем контексты с настройкой base_url
$q = $modx->newQuery('modContextSetting', array('key' => 'base_url', 'value:!=' => ''));
$q->select('context_key,value');

$contexts = array();
$tstart = microtime(true);
if ($q->prepare() && $q->stmt->execute()) {
	// Учитываем наш запрос в БД
	$modx->queryTime += microtime(true) - $tstart;
	$modx->executedQueries++;
	// Разбираем результаты
	while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
		$base_url = trim($row['value'], '/');
		$context = $row['context_key'];
		// Если запрос начинается с base_url какого-то контекста
		if (preg_match('/^('.$base_url.')\//i', $request)) {
			// То переключаемся на этот контекст
			// Web инициализируется в index.php - на него переключаться не нужно
			if ($context != 'web') {
				$modx->switchContext($context);
			}
			// Вырезаем base_url из запроса, чтобы MODX нашел ресурс по uri
			$request = preg_replace('/^'.$base_url.'\//', '', $request);
			// Дело сделано - выходим из цикла
			break;
		}
	}
}

Сниппет переключающий языки:
<?php
//error_reporting(E_ALL | E_STRICT);
//ini_set('display_errors', 1);
$class = $modx->getOption('class', $scriptProperties, '');
$divider = PHP_EOL;
$output = '';

function getLink($context = 'web') {
    global $modx;
	if ($modx->getOption('site_start') != $modx->resource->id && $modx->getCount('modResource', array('uri' => $modx->resource->uri, 'context_key' => $context))) {
		return $modx->resource->uri;
	}
	return '';
}

switch ($modx->context->key) {
    case 'en':
    	$output .= "<a class='".$class."' href='/".getLink('web')."'>RUS</a> {$divider}
    	            <a class='".$class."' href='kz/".getLink('kz')."'>KAZ</a>
    	            <span class='".$class."'>ENG</span> {$divider}";
        break;
    case 'kz':
    	$output .= "<a class='".$class."' href='/".getLink('web')."'>RUS</a> {$divider}
    	            <span class='".$class."'>KAZ</span>
    	            <a class='".$class."' href='en/".getLink('en')."'>ENG</a> {$divider}";
        break;
    default:
    	$output .= "<span class='".$class."'>RUS</span> {$divider}
    	            <a class='".$class."' href='kz/".getLink('kz')."'>KAZ</a>
    	            <a class='".$class."' href='en/".getLink('web')."'>ENG</a> {$divider}";
}

return $output;

Настройки контекстов:
en
base_url				base_url	/en/
Язык					cultureKey	en
http_host				http_host	rirme.kz
Главная страница сайта	site_start	2
site_url				site_url	http://rirme.kz/

kz
base_url				base_url	/kz/
Язык					cultureKey	kz
http_host				http_host	rirme.kz
Главная страница сайта	site_start	3
site_url				site_url	http://rirme.kz/

web
base_url				base_url	/
Язык					cultureKey	ru
http_host				http_host	rirme.kz
Главная страница сайта	site_start	1
site_url				site_url	http://rirme.kz/

Настройки системы -> Babel
babel.contextKeys		babel.contextKeys	web,en,kz

Тег base в начале странички:
<base href="[[++site_url]]" />
Саша Туманов
17 апреля 2015, 21:51
0
Тим, это ведь не компонент с инсталлятором, где нужно сразу учитывать все потенциальные нужды. Я думаю, что тут главное хорошо составленный запрос, а танцы вокруг него, выполняются по произвольной программе ;)
Саша Туманов
17 апреля 2015, 11:39
0
Поправил tagCloud, для вывода в статье тоже.
Саша Туманов
08 апреля 2015, 08:27
0
Уфф…
Прошу прощения, что то у меня тут, видимо
Саша Туманов
07 апреля 2015, 19:43
0
pdoResources перестал реагировать на
&scheme=`abs`
Создает ссылки, без учета контекста, после обновления pdoTools.
Саша Туманов
05 апреля 2015, 20:01
0
Вась, в TicketLatest email, между прочим, действительно не передается в вывод. Проверял для гостей, без авторизации. Там у тебя из TicketComment, без альяса селект, а в modUserProfile тоже поле email есть, наверное перекрывают друг друга. Если в 99-й строке альяс указать, то email в выводе появляется, но остальные значения ломаются.

А «d41d8cd98f00b204e9800998ecf8427e» — это хэш пустой строки, в md5, знакомая личность :))
Саша Туманов
05 апреля 2015, 09:39
0
Ты ведь хочешь граватар в TicketLatest вывести? Я правильно понял?
А откуда name@mail.ru хочешь брать?
Саша Туманов
04 апреля 2015, 23:57
0
Если для TicketLatest указать
[[!TicketLatest?
	&tpl=``
]]
то видно, что поле email, пустое приходит, хотя в таблице modx_tickets_comments есть значение. Баг видимо.
Саша Туманов
04 апреля 2015, 23:05
0
d41d8cd98f00b204e9800998ecf8427e значит, что в [[+email]] пусто
Саша Туманов
13 октября 2014, 00:30
0
Спасибо, сэкономил время