Post recenti - modifiche, anteprima allegati e performance

Aperto da Flavio93Zena, Lunedì - 25 Dicembre 2017 - 04:04

0 Utenti e 1 Visitatore stanno visualizzando questa discussione.

Flavio93Zena

Per prima cosa buon Natale :P

La pagina http://www.italiansmf.net/forum/index.php?action=recent , ovvero quella dei post recenti, ha un limite di 100 post. Avendo fatto parecchie ricerche senza trovare molto (oltre al fatto che ovviamente fosse per problemi di performance https://www.simplemachines.org/community/index.php?topic=557839.msg3953049#msg3953049 )... Ebbene questo valore non è configurabile facilmente, se non da codice.
Maneggiando un po' con Recent.php sono riuscito a portarlo a 500 - sì sono a conoscenza del fatto che sia un incremento *enorme* e che ci possano essere problemi di performance.
La prima domanda è: si possono quantificare in qualche modo questi problemi di performance? Quanto grave potrebbe essere? (Ovviamente fino a server crash ma... Quando?)

Il secondo argomento riguarda gli allegati. Anche qui probabilmente per motivi legati alle prestazioni non sono visualizzate le anteprime degli stessi. L'unica cosa che ci si avvicina (ma mostra solo il titolo dell'allegato) è questa: https://custom.simplemachines.org/mods/index.php?mod=4090
A quanto ho capito dovrei importare banalmente il codice degli allegati visualizzati nei topic (più relativa query, se non erro) e schiaffarlo nel relativo template, ma sorgono due domande. Come esattamente? E ancora, che effetto avrà sulle prestazioni? Presumo pessimo vero? :-\

Allego il mio Recent.php modificato e ringrazio in anticipo, ci sarà potenzialmente un regalo per la soluzione :)

P.S.: da notare che gli allegati che sono in-line grazie all'ILA (in-line attachments di Spuds, non più disponibile sul sito ufficiale, che viene allegata dopo aver constatato che è permesso dalla licenza annessa) funzionano, probabilmente perchè l'anteprima viene creata dentro il messaggio e non nella parte "attachments" che viene dopo il "post".

emanuele

Citazione di: Flavio93Zena il Lunedì - 25 Dicembre 2017 - 04:04
Per prima cosa buon Natale :P
Buon Natale ^-^

Citazione di: Flavio93Zena il Lunedì - 25 Dicembre 2017 - 04:04
La prima domanda è: si possono quantificare in qualche modo questi problemi di performance? Quanto grave potrebbe essere? (Ovviamente fino a server crash ma... Quando?)
Così senza ricordarmi le specifiche direi che dipende da:
0) com'è configurato il server (in particolare mysql),
1) quanti post ha il forum,
2) quante board ha il forum,
3) come è configurata la visibilità delle  board,
4) quanto frequentata è la pagina.
Onestamente, anche se avessi questi dati, difficilmente potrei darti dei numeri.
Ho notato problemi abbastanza rilevanti su WCRPG (parliamo di 20 milioni di post e circa un migliaio di board), tanto da dover ricorrere a qualche trucco di caching, ma ovviamente parliamo di condizioni estreme e di query da 20 secondi a qualche minuto.
Non è tanto un problema di crash, ma di query che finiscono per protrarsi per tanto tempo. Il punto più critico, comunque, è la query che determina il numero di pagine (dato che deve comunque recuperare tutte le righe per fare il conto di quanti elementi esistono), le altre possono essere quasi trascurabili (a confronto), ad eccezione di quando vengono richieste le pagine "centrali" (che devono recuperare il maggior numero di righe).

Citazione di: Flavio93Zena il Lunedì - 25 Dicembre 2017 - 04:04
Come esattamente?
Ti servirà il pezzo  di codice che in Display.php riempie $context['loaded_attachments'] e poi presumibilmente loadAttachmentContext (credo).

Citazione di: Flavio93Zena il Lunedì - 25 Dicembre 2017 - 04:04
E ancora, che effetto avrà sulle prestazioni? Presumo pessimo vero? :-\
bah... non saprei. Un overhead marginale perché tanto la query richiede l'id del messaggio che suppongo sia indicizzato. Quindi difficili da stabilire, ma non incommensurabile.
C'è da tenere conto anche dell'overhead dovuto al fatto di aprire l'immagine via php, ma (ancora) a meno di non avere una moltitudine di visitatori su quella pagina che "picchiano" richieste una dopo l'altra, dovrebbe essere gestibile.

Flavio93Zena

Gnn quasi fanc... Aiutandomi anche con https://custom.simplemachines.org/mods/index.php?mod=4090 sono riuscito a mostrare un link per avere gli allegati ma senza anteprima. Ho provato ad aggiungere un pezzo di codice che avrei successivamente sostituito al link per avere l'anteprima ma per qualche motivo che non capisco mi mostra solo l'icona di allegato, e se la clicco nemmeno il link funziona :(

emanuele


Flavio93Zena

Io ho aggiunto dal chiaro //begin a //end
if (!empty($post['attachments']))
{
echo '
<div class="content smalltext"><p style="vertical-align: bottom; ">' , $txt['airp_attachments'], ': ';
$first = true;
foreach ($post['attachments'] as $attach)
{
if (!$first)
echo ', ';
echo '<a href="', $attach['href'], '">', $attach['filename'], '</a>';
}

echo '</p></div>';
// Show a special box for unapproved attachments...  begin
if ($attachment['is_approved'] != $last_approved_state)
{
$last_approved_state = 0;
echo '
<fieldset>
<legend>', $txt['attach_awaiting_approve'];

if ($context['can_approve'])
echo '&nbsp;[<a href="', $scripturl, '?action=attachapprove;sa=all;mid=', $message['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $txt['approve_all'], '</a>]';

echo '</legend>';
}

if ($attachment['is_image'])
{
if ($attachment['thumbnail']['has_thumb'])
echo '
<a href="', $attachment['href'], ';image" id="link_', $attachment['id'], '" onclick="', $attachment['thumbnail']['javascript'], '"><img src="', $attachment['thumbnail']['href'], '" alt="" id="thumb_', $attachment['id'], '" /></a><br />';
else
echo '
<img src="' . $attachment['href'] . ';image" alt="" width="' . $attachment['width'] . '" height="' . $attachment['height'] . '"/><br />';
}
if (!$attachment['is_image']) echo '
<a href="' . $attachment['href'] . '"><img src="' . $settings['images_url'] . '/icons/clip.gif" align="middle" alt="*" />&nbsp;' . $attachment['name'] . '</a> ';

if (!$attachment['is_approved'] && $context['can_approve'])
echo '
[<a href="', $scripturl, '?action=attachapprove;sa=approve;aid=', $attachment['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $txt['approve'], '</a>]&nbsp;|&nbsp;[<a href="', $scripturl, '?action=attachapprove;sa=reject;aid=', $attachment['id'], ';', $context['session_var'], '=', $context['session_id'], '">', $txt['delete'], '</a>] ';
if (!$attachment['is_image']) echo '
(', $attachment['size'], ($attachment['is_image'] ? ', ' . $attachment['real_width'] . 'x' . $attachment['real_height'] . ' - ' . $txt['attach_viewed'] : ' - ' . $txt['attach_downloaded']) . ' ' . $attachment['downloads'] . ' ' . $txt['attach_times'] . '.)<br />';
//end
}
echo '
</div>
<span class="botslice clear"><span></span></span>
</div>';

}

emanuele

Questo cos'è, un copy&paste da dove?
Display.template.php?

Flavio93Zena

Sì mi pare di sì, dovrebbe essere quello il codice che mostra gli allegati nei messaggi normali, per cui...

emanuele



emanuele

Allora dovresti imparare qualche altro rudimento di php. :P

Gli allegati li hai nella variabile $post['attachments'], ed hai un loop foreach che passa tra tutti gli allegati di un certo post assegnandoli a $attach, ma tu hai 2 errori:
1) hai messo il codice fuori dal loop,
2) usi $attachment come nome della variabile.
Il primo errore fa si che se sei fortunato solo l'ultimo allegato della lista sia mostrato.
Il secondo fa si che nessun allegato sia mostrato correttamente nel codice che hai aggiunto tu.

Il codice per mostrare gli allegati deve andare nel loop:
foreach ($post['attachments'] as $attach)
{
if (!$first)
echo ', ';
echo '<a href="', $attach['href'], '">', $attach['filename'], '</a>';
// diciamo qui <==================
}


E il codice da aggiungere (dopo aver corretto i nomi delle variabili dovrebbe essere più o meno:
if ($attachment['is_approved'] == false)
{
    continue;
}
if ($attachment['is_image'])
{
if ($attachment['thumbnail']['has_thumb'])
echo '
<a href="', $attachment['href'], ';image" id="link_', $attachment['id'], '" onclick="', $attachment['thumbnail']['javascript'], '"><img src="', $attachment['thumbnail']['href'], '" alt="" id="thumb_', $attachment['id'], '" /></a><br />';
else
echo '
<img src="' . $attachment['href'] . ';image" alt="" width="' . $attachment['width'] . '" height="' . $attachment['height'] . '"/><br />';
}
if (!$attachment['is_image']) echo '
<a href="' . $attachment['href'] . '"><img src="' . $settings['images_url'] . '/icons/clip.gif" align="middle" alt="*" />&nbsp;' . $attachment['name'] . '</a> ';

if (!$attachment['is_image']) echo '
(', $attachment['size'], ($attachment['is_image'] ? ', ' . $attachment['real_width'] . 'x' . $attachment['real_height'] . ' - ' . $txt['attach_viewed'] : ' - ' . $txt['attach_downloaded']) . ' ' . $attachment['downloads'] . ' ' . $txt['attach_times'] . '.)<br />';
//end


Inoltre, tieni presente che se vi sono degli allegati non approvati, questo mod ne mostra il nome e il link. Il link apre una pagina "non sei autorizzato", ma comunque viene esposto il fatto che un post ha allegati non approvati (ho già mandato il relativo security report).

Flavio93Zena

Citazione di: emanuele il Sabato - 06 Gennaio 2018 - 14:37
Allora dovresti imparare qualche altro rudimento di php. :P
Ci sto lavorando.

Citazione di: emanuele il Sabato - 06 Gennaio 2018 - 14:37
Gli allegati li hai nella variabile $post['attachments'], ed hai un loop foreach che passa tra tutti gli allegati di un certo post assegnandoli a $attach, ma tu hai 2 errori:
1) hai messo il codice fuori dal loop,
Ci ero arrivato in realtà, ma quando ho provato a metterlo lì mi dava invalid argument supplied for foreach, per cui avevo un qualcosa di sbagliato :/

Citazione di: emanuele il Sabato - 06 Gennaio 2018 - 14:37
Il primo errore fa si che se sei fortunato solo l'ultimo allegato della lista sia mostrato.
Sì volevo almeno testare.

Citazione di: emanuele il Sabato - 06 Gennaio 2018 - 14:37
Il secondo fa si che nessun allegato sia mostrato correttamente nel codice che hai aggiunto tu.
xD

Citazione di: emanuele il Sabato - 06 Gennaio 2018 - 14:37
Il codice per mostrare gli allegati deve andare nel loop:
foreach ($post['attachments'] as $attach)
{
if (!$first)
echo ', ';
echo '<a href="', $attach['href'], '">', $attach['filename'], '</a>';
// diciamo qui <==================
}
Ha senso.

Citazione di: emanuele il Sabato - 06 Gennaio 2018 - 14:37
2) usi $attachment come nome della variabile.
Citazione di: emanuele il Sabato - 06 Gennaio 2018 - 14:37
E il codice da aggiungere (dopo aver corretto i nomi delle variabili dovrebbe essere più o meno:
if ($attachment['is_approved'] == false)
{
    continue;
}
if ($attachment['is_image'])
{
if ($attachment['thumbnail']['has_thumb'])
echo '
<a href="', $attachment['href'], ';image" id="link_', $attachment['id'], '" onclick="', $attachment['thumbnail']['javascript'], '"><img src="', $attachment['thumbnail']['href'], '" alt="" id="thumb_', $attachment['id'], '" /></a><br />';
else
echo '
<img src="' . $attachment['href'] . ';image" alt="" width="' . $attachment['width'] . '" height="' . $attachment['height'] . '"/><br />';
}
if (!$attachment['is_image']) echo '
<a href="' . $attachment['href'] . '"><img src="' . $settings['images_url'] . '/icons/clip.gif" align="middle" alt="*" />&nbsp;' . $attachment['name'] . '</a> ';

if (!$attachment['is_image']) echo '
(', $attachment['size'], ($attachment['is_image'] ? ', ' . $attachment['real_width'] . 'x' . $attachment['real_height'] . ' - ' . $txt['attach_viewed'] : ' - ' . $txt['attach_downloaded']) . ' ' . $attachment['downloads'] . ' ' . $txt['attach_times'] . '.)<br />';
//end
Per cui
// Show a special box for unapproved attachments...  begin
if ($attach['is_approved'] == false)
{
    continue;
}
if ($attach['is_image'])
{
if ($attach['thumbnail']['has_thumb'])
echo '
<a href="', $attach['href'], ';image" id="link_', $attach['id'], '" onclick="', $attach['thumbnail']['javascript'], '"><img src="', $attach['thumbnail']['href'], '" alt="" id="thumb_', $attach['id'], '" /></a><br />';
else
echo '
<img src="' . $attach['href'] . ';image" alt="" width="' . $attach['width'] . '" height="' . $attach['height'] . '"/><br />';
}
if (!$attach['is_image']) echo '
<a href="' . $attach['href'] . '"><img src="' . $settings['images_url'] . '/icons/clip.gif" align="middle" alt="*" />&nbsp;' . $attach['name'] . '</a> ';

if (!$attach['is_image']) echo '
(', $attach['size'], ($attach['is_image'] ? ', ' . $attach['real_width'] . 'x' . $attach['real_height'] . ' - ' . $txt['attach_viewed'] : ' - ' . $txt['attach_downloaded']) . ' ' . $attach['downloads'] . ' ' . $txt['attach_times'] . '.)<br />';
//end

dal momento che vengono assegnati ad $attach, giusto? O non ho capito una mazza?
Ad ogni modo non mi mostra l'anteprima, il link viene mostrato e se lo clicco prova a scaricare l'immagine corretta, ma anteprima nada :-[ E nel registro errori is_approved è undefined :/

Citazione di: emanuele il Sabato - 06 Gennaio 2018 - 14:37
Inoltre, tieni presente che se vi sono degli allegati non approvati, questo mod ne mostra il nome e il link. Il link apre una pagina "non sei autorizzato", ma comunque viene esposto il fatto che un post ha allegati non approvati (ho già mandato il relativo security report).
Pensavo ma non ne ero sicuro, non volevo dire una stupidaggine ;D

E... Grazie :)

emanuele

Citazionedal momento che vengono assegnati ad $attach, giusto? O non ho capito una mazza?
Yep, corretto.

CitazioneE nel registro errori is_approved è undefined :/
Questo perché is_approved di $attach['is_approved'] non è assegnato per via del bug che ho menzionato prima.
Nel mod mi pare di ricordare ci sia una sola query, alla fine del where, aggiungici un and a.approved = 1 poi togli if ($attach['is_approved'] == false)
{
    continue;
}

dal codice sopra.

Flavio93Zena

#12
Urgh, peggio ;D
is_image, downloads, size e name sono undefined ora xD

function template_main()
{
global $context, $settings, $options, $txt, $scripturl;

echo '
<div id="recent" class="main_section">
<div class="cat_bar">
<h3 class="catbg">
<span class="ie6_header floatleft"><img src="', $settings['images_url'], '/post/xx.gif" alt="" class="icon" />',$txt['recent_posts'],'</span>
</h3>
</div>
<div class="pagesection">
<span>', $txt['pages'], ': ', $context['page_index'], '</span>
</div>';

foreach ($context['posts'] as $post)
{
echo '
<div class="', $post['alternate'] == 0 ? 'windowbg' : 'windowbg2', ' core_posts">
<span class="topslice"><span></span></span>
<div class="content">
<div class="counter">', $post['counter'], '</div>
<div class="topic_details">
<h5>', $post['board']['link'], ' / ', $post['link'], '</h5>
<span class="smalltext">«&nbsp;', $txt['last_post'], ' ', $txt['by'], ' <strong>', $post['poster']['link'], ' </strong> ', $txt['on'], '<em> ', $post['time'], '</em>&nbsp;»</span>
</div>
<div class="list_posts">', $post['message'], '</div>
</div>';

if ($post['can_reply'] || $post['can_mark_notify'] || $post['can_delete'])
echo '
<div class="quickbuttons_wrap">
<ul class="reset smalltext quickbuttons">';

// If they *can* reply?
if ($post['can_reply'])
echo '
<li class="reply_button"><a href="', $scripturl, '?action=post;topic=', $post['topic'], '.', $post['start'], '"><span>', $txt['reply'], '</span></a></li>';

// If they *can* quote?
if ($post['can_quote'])
echo '
<li class="quote_button"><a href="', $scripturl, '?action=post;topic=', $post['topic'], '.', $post['start'], ';quote=', $post['id'], '"><span>', $txt['quote'], '</span></a></li>';

// Can we request notification of topics?
if ($post['can_mark_notify'])
echo '
<li class="notify_button"><a href="', $scripturl, '?action=notify;topic=', $post['topic'], '.', $post['start'], '"><span>', $txt['notify'], '</span></a></li>';

// How about... even... remove it entirely?!
if ($post['can_delete'])
echo '
<li class="remove_button"><a href="', $scripturl, '?action=deletemsg;msg=', $post['id'], ';topic=', $post['topic'], ';recent;', $context['session_var'], '=', $context['session_id'], '" onclick="return confirm(\'', $txt['remove_message'], '?\');"><span>', $txt['remove'], '</span></a></li>';

if ($post['can_reply'] || $post['can_mark_notify'] || $post['can_delete'])
echo '
</ul>';

if (!empty($post['attachments']))
{
echo '
<div class="content smalltext"><p style="vertical-align: bottom; ">' , $txt['airp_attachments'], ': ';
$first = true;
foreach ($post['attachments'] as $attach)
{
if (!$first)
echo ', ';
echo '<a href="', $attach['href'], '">', $attach['filename'], '</a>';
// Show a special box for unapproved attachments...  begin
if ($attach['is_image'])
{
if ($attach['thumbnail']['has_thumb'])
echo '
<a href="', $attach['href'], ';image" id="link_', $attach['id'], '" onclick="', $attach['thumbnail']['javascript'], '"><img src="', $attach['thumbnail']['href'], '" alt="" id="thumb_', $attach['id'], '" /></a><br />';
else
echo '
<img src="' . $attach['href'] . ';image" alt="" width="' . $attach['width'] . '" height="' . $attach['height'] . '"/><br />';
}
if (!$attach['is_image']) echo '
<a href="' . $attach['href'] . '"><img src="' . $settings['images_url'] . '/icons/clip.gif" align="middle" alt="*" />&nbsp;' . $attach['name'] . '</a> ';

if (!$attach['is_image']) echo '
(', $attach['size'], ($attach['is_image'] ? ', ' . $attach['real_width'] . 'x' . $attach['real_height'] . ' - ' . $txt['attach_viewed'] : ' - ' . $txt['attach_downloaded']) . ' ' . $attach['downloads'] . ' ' . $txt['attach_times'] . '.)<br />';
//end
}

echo '</p></div>';
}
echo '
</div>
<span class="botslice clear"><span></span></span>
</div>';

}

echo '
<div class="pagesection">
<span>', $txt['pages'], ': ', $context['page_index'], '</span>
</div>
</div>';
}

L'intera funzione.

SELECT
a.id_attach, a.id_msg, a.filename, b.id_board
FROM {db_prefix}attachments AS a
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)
INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
WHERE a.id_msg IN ({array_int:posts})
AND a.attachment_type = 0
AND a.id_member = 0
AND a.approved = 1',
array(
'posts' => $posts,
)
);

E la query.

emanuele

Normale, perché ora effettivamente inizia a funzionare.
is_image effettivamente serve, non ricordo come sia impostata.
downloads dubito ti interessi il numero di download, io lo toglierei.
name dovrebbe essere più o meno:
'name' => preg_replace('~&amp;#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', htmlspecialchars($attachment['filename'])),

Flavio93Zena

Citazione di: emanuele il Mercoledì - 10 Gennaio 2018 - 16:37
Normale, perché ora effettivamente inizia a funzionare.
xD
Citazione di: emanuele il Mercoledì - 10 Gennaio 2018 - 16:37
is_image effettivamente serve, non ricordo come sia impostata.
Più di questo non ho trovato https://support.simplemachines.org/function_db/index.php?action=view_function;id=450 e non dice nulla che già sappiamo - ritorna un vero/falso, ovviamente.
Citazione di: emanuele il Mercoledì - 10 Gennaio 2018 - 16:37
downloads dubito ti interessi il numero di download, io lo toglierei.
Hmm già ;D
Citazione di: emanuele il Mercoledì - 10 Gennaio 2018 - 16:37
name dovrebbe essere più o meno:
'name' => preg_replace('~&amp;#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', htmlspecialchars($attachment['filename'])),
??? qui ti ho perso, il nome dell'allegato viene visualizzato correttamente, non ho idea di dove infilare il preg_replace e anche se fosse servirebbe in callback perchè gira su php 5.5 (che peraltro potrei portare a 5.6...)
E il nome funziona da qui, nel recent.php
// Get any attachments of these posts.
if (!empty($modSettings['attachmentEnable']) && !empty($context['posts']))
{
$posts = array_keys($context['posts']);
$query = $smcFunc['db_query']('', '
SELECT
a.id_attach, a.id_msg, a.filename, b.id_board
FROM {db_prefix}attachments AS a
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)
INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
WHERE a.id_msg IN ({array_int:posts})
AND a.attachment_type = 0
AND a.id_member = 0
AND a.approved = 1',
array(
'posts' => $posts,
)
);
$view_attach = array();
while ($row = $smcFunc['db_fetch_assoc']($query))
{
// Do we have permission to view attachments in this board:
if (!isset($view_attach[$row['id_board']]))
$view_attach[$row['id_board']] = allowedTo('view_attachments', $row['id_board']);
if (empty($view_attach[$row['id_board']]))
continue;

// Capture the attachment:
$context['posts'][$row['id_msg']]['attachments'][] = array(
'filename' => $row['filename'],
'href' => $scripturl . '?action=dlattach;topic=' . $context['posts'][$row['id_msg']]['topic'] . '.0;attach=' . $row['id_attach'],
);
}
$smcFunc['db_free_result']($query);
}

'filename' => $row['filename'] :)
* Ti ho messo l'intero codice così non mi chiedi cosa ci sia prima/dopo :P In allegato come si vedono gli allegati.

Discussioni simili (3)