package ONO::ToolBox::Blog;
################################################################################
# COPYRIGHT / LICENSE #
################################################################################
#
# This file is part of the ONO Software Project.
#
# Copyright (C) 2000-2025 Jos KIRPS [ www.kirps.com | jos_AT_kirps_DOT_com ]
# and The Joopita Project [ www.joopita.org | contact_AT_joopita_DOT_com ]
#
# This file, as well as other parts of the ONO Software Project or related
# elements, are FREE SOFTWARE available under the ARTISTIC LICENSE 2.0.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# For the full license, see /ono/osr/license/LICENSE.txt, or write to
# jos_AT_kirps_DOT_com or contact_AT_joopita_DOT_com.
#
################################################################################
# END OF COPYRIGHT / LICENSE, HERE COMES THE CODE ... #
################################################################################
use strict;
use ONO::Lib::UI::MSG;
use ONO::Lib::UI::Page;
use ONO::Lib::UI::Tags;
use ONO::Lib::DateTime::ToolBox;
use ONO::Lib::SQL::IO;
use ONO::Lib::SQL::Quote;
use ONO::Lib::Web::SocialBookmarking;
use ONO::Lib::Text::Editor;
use ONO::Lib::Text::ForceBreak;
use ONO::Lib::Video::Object;
use ONO::Lib::Audio::Object;
use ONO::Lib::Code::RandomID;
use ONO::Lib::UI::Icon;
use ONO::ToolBox::Gallery;
use ONO::ToolBox::PipeLine;
use ONO::Ext::Morzino::ToolBox;
use ONO::FW::Web::ToolBox::Access;
use ONO::FW::User::Screen::Dashboard;
use ONO::DB;
use ONO::Core::Kernel;
use ONO::IO;
use ONO::Lib::UI::Help;
use ONO::Lib::Basic;
###############################################################################
# advanced screen (virclass etc...)
###############################################################################
sub screen {
my (
$self,
$db,
$community,
$author,
$lang,
$script_url,
$BLK_ref,
$vars_ref,
$sql_ref,
$switches,
$type_filter,
$max_items,
$target_page,
$virclass_target_page,
$max_files_per_entry,
) = @_;
my %vars = %$vars_ref;
my %sql = %$sql_ref;
my %BLK = %$BLK_ref;
#: This is the ONO blog display engine.
#:
#: Available switches:
#:
#: -a display teachers (used by AutoWebsite)
#: -A alternative table, if defined under $sql{'alt_sql_table'}
#: -b use blog as entry page (used by AutoWebsite)
#: -c comma list view
#: -d use dailyword as entry page (used by AutoWebsite)
#: -e editor mode
#: -f news feed (used by AutoWebsite)
#: -g grab app data (used by AutoWebsite)
#: -h allow help texts
#: -H smaller headers (used by website widgets)
#: -i make single images smaller
#: -I make single images even smaller
#: -l list view (1 entry per row)
#: -L large text
#: -m media & photos (used by AutoWebsite)
#: -M don't display the menu (used by AutoWebsite)
#: -w website (or schoolweb) mode (used by AutoWebsite)
#: -s use schedule as entry page (used by AutoWebsite)
#: -S no sidebar (used by AutoWebsite)
#: -t use texts as entry page (used by AutoWebsite)
#: -T don't show page titles (used by AutoWebsite)
#: -u display students (used by AutoWebsite)
#: -U user mode (ignore author, show all posts, but discard website posts etc)
#: -V virclass mode
#: -w website mode (?)
#: -W website mode (?)
#: -X virschool mode
#: -Y virclass multi mode (used by AutoWebsite)
#: -Z avoid single image in one row if possible
#:
#: Type switches:
#:
#: -b only blog
#: -n only news
#: -r only reviews
#: -x don't display at all
#:
#: Blog_widget_switches:
#:
#: -C allow registered users to write comments
#: -g show category
#: -i make single images smaller
#: -I make single images even smaller
#: -j single images align left
#: -J single images align right (reserved, but not implemented yet)
#: -s show source
#: -q show school
my @text = (
'write a news / blog post',
);
if ($lang eq "de") {
@text = (
'neuen Eintrag schreiben',
);
}
if ($lang eq "fr") {
@text = (
'écrire un nouveau message',
);
}
if ($lang eq "lu") {
@text = (
'e neie Message schreiwen',
);
}
my ($H2,$H3) = ('h2','h3');
if ($switches =~ /H/) {
($H2,$H3) = ('h3','h4');
}
if ($max_items < 1 || $max_items > 999) {
$max_items = 5;
}
my $write = $text[0];
my $Write = ucfirst $text[0];
$Write =~ s~^é~E~;
my $TABLE = "blog";
if ($switches =~ /A/ && $sql{'alt_sql_table'}) {
$TABLE = $sql{'alt_sql_table'};
}
my ($MAIN,$debug);
if (ONO::IO->devstation) {
$debug++;
}
if ($debug) {
$MAIN .= qq~<div class="pad10_2">DEBUG: username = '$vars{'username'}'<br>DEBUG: switches = '$switches'<br>DEBUG: author = $author</div>~;
}
# add_author (additional virclasses - step 1 of 2)
my $AUTHOR_ADD;
if ($author =~ s~^web:(.*?)#(.*)$~web:$1~) {
$AUTHOR_ADD = $2;
}
my $AUTHOR = qq~author_name = '#$author'~;
my $website_blog_post = "website_blog_post";
if ($switches =~ /w/) {
$AUTHOR = qq~author_name LIKE '#WEB#$author%'~;
$website_blog_post = "db_news_post";
}
if ($author =~ /^user:(.*?)$/) {
$AUTHOR = qq~author_name = '$1'~;
$website_blog_post = $vars{'mode'};
}
if ($switches =~ /Y/ && $author =~ /;/) {
$AUTHOR = "";
$author =~ s~[^0-9\;]~~gi;
foreach my $aut (split(/;/,$author)) {
if ($aut =~ /[0-9]/) {
$AUTHOR .= qq~author_name = '#$aut' OR ~;
}
}
$AUTHOR =~ s~ OR $~~;
}
if ($switches =~ /W/) {
if ($debug) {
$MAIN .= qq~<div class="pad10_2">DEBUG: website mode (W)</div>~;
}
$AUTHOR = "ERROR";
$author =~ s~[^A-Za-z0-9\,\:\#]~~g;
if ($author =~ /^(.*?),(.*?)$/) {
my $ONE = $1;
my $TWO = $2;
if ($debug) {
$MAIN .= qq~<div class="pad10_2">DEBUG: ONE = $ONE, TWO = $TWO</div>~;
}
if ($TWO =~ s~#(.*?)$~~) {
my $THREE = ",$1,";
my $VIRS_IN;
if ($debug) {
$MAIN .= qq~<div class="pad10_2">DEBUG: THREE = $THREE</div>~;
}
foreach my $vir (split(/,/,$THREE)) {
if ($vir =~ /[0-9]/) {
if ($vir =~ /^S(.*?)$/) {
# school:
$vir =~ s~^S~~;
foreach my $line2 (ONO::DB->select($db,"${community}_school_virschool_relationships","virschool = '$vir' AND (status = '1' OR status IS NULL)")) {
my @row2 = ONO::DB->readcols($line2);
$VIRS_IN .= qq~,'#$row2[1]'~;
}
} else {
if ($vir =~ /^G(.*?)$/) {
# group:
$vir =~ s~^G~~;
foreach my $line2 (ONO::DB->select($db,"${community}_school_virschool_groups_relationships","virgroup = '$vir' AND (status = '1' OR status IS NULL)")) {
my @row2 = ONO::DB->readcols($line2);
foreach my $line3 (ONO::DB->select($db,"${community}_school_virschool_relationships","virschool = '$row2[1]' AND (status = '1' OR status IS NULL)")) {
my @row3 = ONO::DB->readcols($line3);
foreach my $line4 (ONO::DB->select($db,"${community}_school_virclass","id = '$row3[1]' AND cat = '$row2[4]'")) {
my @row4 = ONO::DB->readcols($line4);
if ($row4[17] !~ /H/) {
$VIRS_IN .= qq~,'#$row4[0]'~;
}
}
}
}
} else {
$VIRS_IN .= qq~,'#$vir'~;
}
}
}
}
$AUTHOR = qq~(author_name LIKE '#WEB#$ONE%' OR author_name IN('#WEB#$ONE#$TWO'$VIRS_IN))~;
} else {
$AUTHOR = qq~(author_name LIKE '#WEB#$ONE%' OR author_name = '#WEB#$ONE#$TWO')~;
}
}
if ($author =~ s/^web://) {
$AUTHOR = qq~(author_name LIKE '#WEB#%' AND author_name LIKE '%#$author')~;
if ($AUTHOR_ADD =~ /vir:(.*)$/) {
my $OR_IN;
foreach my $vir (split(/,/,$1)) {
if ($vir =~ s~^S~~) {
foreach my $line2 (ONO::DB->select($db,"${community}_school_virschool_relationships","virschool = '$vir' AND (status = '1' OR status IS NULL)")) {
my @row2 = ONO::DB->readcols($line2);
$OR_IN .= qq~'#$row2[1]',~
}
} else {
if ($vir =~ /^G(.*?)$/) {
# group:
$vir =~ s~^G~~;
foreach my $line2 (ONO::DB->select($db,"${community}_school_virschool_groups_relationships","virgroup = '$vir' AND (status = '1' OR status IS NULL)")) {
my @row2 = ONO::DB->readcols($line2);
foreach my $line3 (ONO::DB->select($db,"${community}_school_virschool_relationships","virschool = '$row2[1]' AND (status = '1' OR status IS NULL)")) {
my @row3 = ONO::DB->readcols($line3);
foreach my $line4 (ONO::DB->select($db,"${community}_school_virclass","id = '$row3[1]' AND cat = '$row2[4]'")) {
my @row4 = ONO::DB->readcols($line4);
if ($row4[17] !~ /H/) {
$OR_IN .= qq~'#$row4[0]',~;
}
}
}
}
} else {
$OR_IN .= qq~'#vir',~
}
}
}
if ($OR_IN) {
$OR_IN =~ s~,$~~;
$AUTHOR = "($AUTHOR OR author_name IN($OR_IN))";
}
}
}
}
if ($switches =~ /V/) {
$AUTHOR = qq~author_name = '#$author'~;
}
if ($debug) {
$MAIN .= qq~<div class="pad10_2">DEBUG: author_name = '#$author'</div>~;
}
# add_author (additional virclasses - step 2 of 2)
if ($AUTHOR_ADD) {
my $AUTHOR_ADD_OR;
$AUTHOR_ADD =~ s~:~,~;
foreach my $vir (split(/\,/,$AUTHOR_ADD)) {
if ($vir =~ /[0-9]/) {
$AUTHOR_ADD_OR .= qq~ OR author_name = '#$vir'~;
}
}
$AUTHOR = "(($AUTHOR) $AUTHOR_ADD_OR)";
}
if ($switches =~ /U/) {
$AUTHOR = "author_name NOT LIKE '%#%'";
}
###################################################################
# MAIN SCREEN
###################################################################
if ($switches =~ /e/ && !$vars{'highlight_unpublished'}) {
my $hide_b = "";
my $hide_e = " hide";
if ($vars{'blog_message_title'} || $vars{'blog_message_text'} || $vars{'blog_message_add'}) {
$hide_b = " hide";
$hide_e = "";
}
my $HELP;
if ($switches =~ /h/ && $vars{'blog_help_message_new'}) {
$HELP = ONO::Lib::UI::Help->bulb($vars{'blog_help_message_new'},"b");
}
my $hide_pipe;
if (ONO::ToolBox::PipeLine->count($vars{'username'})) {
$hide_b = " hide";
$hide_e = "";
} else {
$hide_pipe = "width:0px;height:0px;overflow:hidden";
}
if ($vars{'option'} eq "addblogpost") {
$hide_b = " hide";
$hide_e = "";
}
my ($targets_ref,$target_selected,$blog_prefs) = ONO::ToolBox::PipeLine->targets($db,$community,$vars_ref,$sql_ref);
my $PIPE = ONO::ToolBox::PipeLine->pipeline(
$db,
$community,
$targets_ref,
$target_selected,
$lang,
$BLK_ref,
$vars_ref,
"BU",
$blog_prefs,
);
my $WRITE_BUTTON = qq~<a href="javascript:void(0);" class="button_green" onclick="onojs_block('blog_add_post');onojs_hide('blog_add_post_button');">$write</a>~;
if (ONO::IO->device ne "computer") {
$WRITE_BUTTON = qq~<a href="$script_url&blog_message_add=1" class="button_green">$write</a>~;
}
my $INPUT;
foreach my $key ('environment','website','virclass','school','community_screen') {
if ($vars{$key}) {
$INPUT .= qq~<input type="hidden" name="$key" value="$vars{$key}">~;
}
}
my @ICS = (
ONO::Lib::UI::Icon->button("/ono/osr/images/icons/crystal/32x32/mimetypes/image.png",24,"","","","$BLK{'images'}, $BLK{'docs'} & $BLK{'files'}","C"),
ONO::Lib::UI::Icon->button("/ono/osr/images/icons/crystal/32x32/mimetypes/pdf.png",24,"","","","$BLK{'images'}, $BLK{'docs'} & $BLK{'files'}","C"),
ONO::Lib::UI::Icon->button("/ono/osr/images/icons/crystal/32x32/mimetypes/video.png",24,"","","","YouTube / Vimeo","C"),
);
$MAIN .= qq~<div id="blog_add_post_button" class="box_green pad10_2 mt20 mb10$hide_b" onclick="onojs_block('blog_add_post');onojs_hide('blog_add_post_button');">
<div class="p2"><div class="inline">$WRITE_BUTTON</div></div>
</div>
<div id="blog_add_post" class="box_green mt20 mb10$hide_e">
<table class="default_table fr">
<tr>
<td style="padding:5px 0px 10px 15px;border-left:1px dotted #339933">
<a href="javascript:void(0);" onclick="onojs_setwidth('blog_upload_pipeline_div','100%');onojs_setheight('blog_upload_pipeline_div','auto')">
$ICS[0]
</a>
</td>
<td style="padding:5px 10px 10px 0px;border-right:1px dotted #339933">
<a href="javascript:void(0);" onclick="onojs_setwidth('blog_upload_pipeline_div','100%');onojs_setheight('blog_upload_pipeline_div','auto')">
$ICS[1]
</a>
</td>
<td style="padding:5px 10px 10px 10px;border-right:1px dotted #339933">
<a href="javascript:void(0);" onclick="onojs_block('blog_upload_video_div')">
$ICS[2]
</a>
</td>
<td>
<a href="javascript:void(0);" onclick="onojs_hide('blog_add_post');onojs_block('blog_add_post_button');">
<img class="close ml10" src="/ono/osr/images/icons/crystal/32x32/ono/close.png" alt="close button">
</a>
</td>
</tr>
</table>
<$H2 class="green">$Write</$H2>
<div class="box_paper rel">
$HELP
<form method="post" action="$ENV{'SCRIPT_NAME'}">
$INPUT
<input type="hidden" name="mode" value="$website_blog_post">
<input type="hidden" name="blog_message_posted" value="$website_blog_post">
<div class="inline w100">
<input type="text" id="blog_message_title_id" name="blog_message_title" value="$vars{'blog_message_title'}" placeholder="$BLK{'Title'}..." class="w98" required>
</div>
<div id="blog_upload_video_div" class="box_green abs hide" style="top:32px;left:32px;z-index:999">
<a href="javascript:void(0);" onclick="onojs_hide('blog_upload_video_div');"><img class="close" alt="close button"></a>
<h3 class="green">$BLK{'Add'}: $BLK{'video'}</h3>
<div class="box_paper">
<img class="block64 auto" src="/ono/osr/images/icons/crystal/64x64/mimetypes/video.png" alt="">
<table class="default_table mt10">
<tr>
<td>
<a href="javascript:void(0);" onclick="onojs_hide('blog_upload_video_div');
onojs_setwidth('blog_upload_pipeline_div','100%');
onojs_setheight('blog_upload_pipeline_div','auto')"
class="button_green">$BLK{'upload'}</a>
</td>
<td>
<a href="javascript:void(0);" onclick="onojs_hide('blog_upload_video_div');onojs_block('blog_upload_video_embed_div');"
class="button_green">$BLK{'embed'} (YouTube / Vimeo)</a>
</td>
</tr>
</table>
</div>
</div>
<div id="blog_upload_video_embed_div" class="hide mt10">
<table class="wide_table">
<tr>
<td><img class="block32 mr10" src="/ono/osr/images/icons/crystal/32x32/mimetypes/video.png" alt=""></td>
<td class="w100">
<input type="text" name="blog_message_video" value="$vars{'blog_message_video'}" class="w95"
placeholder="https://www.youtube.com/watch?v=... / https://player.vimeo.com/video/...">
</td>
</tr>
</table>
</div>
<div id="blog_upload_pipeline_div" class="mt10" style="$hide_pipe">
<div class="box_fabric w95">
$PIPE
</div>
</div>
<div class="inline w100 mt10 mb10">
<textarea id="blog_message_text" name="blog_message_text" class="w95 h150" placeholder="$BLK{'Text'}...">$vars{'blog_message_text'}</textarea>
</div>
<div class="inline">$BLK{'submit_add'}</div>
</form>
</div>
</div>
~;
$MAIN .= ONO::Lib::Text::Editor->edit("blog_message_text",$lang,200);
}
if ($vars{'highlight_unpublished'}) {
$MAIN .= qq~<div class="p5"></div>~;
}
my ($AND,$CLOSE);
if ($switches !~ /e/) {
$AND .= qq~AND published = '1' ~;
}
if ($switches =~ /e/ && $vars{'highlight_unpublished'}) {
$AND .= qq~AND published != '1' ~;
}
if ($ENV{'REQUEST_URI'} =~ m~/web/-/(.*?)/(.*?)/(.*?):(.*?)/~) {
my $PROJ = $1;
my $PAGE = $2;
my $REQ = $3;
$REQ =~ s~[^0-9]~~g;
if ($REQ) {
$AND .= qq~AND id = '$REQ' ~;
$CLOSE = qq~<a href="/web/-/$PROJ/$PAGE/"><img class="close" alt="close button"></a>~;
}
}
if (!$vars{'virclass_blog_flags'}) {
if ($type_filter eq "n" || $vars{'blog_message_type'} eq "n") {
$AND .= qq~AND (flags LIKE '%n%' OR (flags NOT LIKE '%n%' AND flags NOT LIKE '%b%' AND flags NOT LIKE '%r%')) ~;
}
if ($type_filter eq "b" || $vars{'blog_message_type'} eq "b") {
$AND .= qq~AND (flags LIKE '%b%' OR (flags NOT LIKE '%n%' AND flags NOT LIKE '%b%' AND flags NOT LIKE '%r%')) ~;
}
if ($type_filter eq "r" || $vars{'blog_message_type'} eq "r") {
$AND .= qq~AND flags LIKE '%r%' ~;
}
}
if ($vars{'menubar_query'}) {
my $query = $vars{'menubar_query'};
$query =~ s~[^A-Za-z0-9]~~g;
$AND = "AND title LIKE '%$query%' ";
}
# website / classroom logic
if ($community eq "school" && $vars{'virclass_blog_flags'} && $switches !~ /e/) {
$MAIN .= qq~\n<!-- ONOToolBoxBlog: EduMode-->\n~;
# website / portal mode:
if ($vars{'virclass_blog_flags_website'} && !$vars{'virclass_blog_flags_classroom'}) {
$MAIN .= qq~<!-- ONOToolBoxBlog: WebsiteMode (require_n) -->\n~;
$AND .= qq~AND (flags LIKE '%n%' OR (flags NOT LIKE '%b%' AND flags NOT LIKE '%n%')) ~;
}
# classroom / blog mode:
if ($vars{'virclass_blog_flags_classroom'} && !$vars{'virclass_blog_flags_website'}) {
$MAIN .= qq~<!-- ONOToolBoxBlog: ClassroomMode (require_b) -->\n~;
$AND .= qq~AND (flags LIKE '%b%' OR (flags NOT LIKE '%b%' AND flags NOT LIKE '%n%')) ~;
}
}
# filtering
if ($vars{'blog_widget_filter'}) {
$vars{'blog_widget_filter'} =~ s~(\'|\(|\)|\[|\])~~g;
foreach my $filter (split(/;/,$vars{'blog_widget_filter'})) {
my @fp = split(/:/,$filter);
my $ORS;
if ($fp[0] eq "cats") {
foreach my $cat (@fp) {
if ($cat =~ /[0-9]/) {
$ORS .= "category = '$cat' OR ";
}
}
$ORS =~ s~ OR $~~g;
}
if ($fp[0] eq "keys") {
shift @fp;
foreach my $key (@fp) {
if ($key =~ /[A-Za-z0-9]/) {
$ORS .= "title LIKE '%$key%' OR ";
}
}
$ORS =~ s~ OR $~~g;
}
if ($fp[0] eq "tags") {
shift @fp;
foreach my $key (@fp) {
if ($key =~ /[A-Za-z0-9]/) {
$ORS .= "tags LIKE '%$key%' OR ";
}
}
$ORS =~ s~ OR $~~g;
}
if ($ORS) {
$AND .= qq~ AND ($ORS)~;
}
}
$AND = ONO::DB->query_umlaut($AND);
}
# all query setups done...
my $offset = 0;
if ($vars{'page'}) {
$offset = $max_items * ($vars{'page'}-1);
}
my ($counter,%cache,@cats);
if (!$vars{'blog_focus'} && $ENV{'REQUEST_URI'} =~ /blog_focus/) {
if ($ENV{'REQUEST_URI'} =~ m~(\?|\&)blog_focus=(.*?)$~){
$vars{'blog_focus'} = $2;
}
if ($ENV{'REQUEST_URI'} =~ m~(\?|\&)blog_focus=(.*?)\&~){
$vars{'blog_focus'} = $2;
}
}
if ($vars{'virclass_categories'} && $vars{'blog_widget_switches'} =~ /g/) {
$vars{'virclass_categories'} = ";$vars{'virclass_categories'};";
foreach my $cat (split(/\;/,$vars{'virclass_categories'})) {
$cat =~ m~^(.*?):(.*?)$~;
$cats[$1] = $2;
}
}
if ($sql{'blog_category'}) {
$AND .= " AND category = '$sql{'blog_category'}'";
}
my $total = ONO::DB->count($db,"${community}_${TABLE}_messages","$AUTHOR AND flags NOT LIKE '%x%' $AND");
if ($debug) {
$MAIN .= qq~<div class="pad10_2">DEBUG: SELECT * FROM ${community}_${TABLE}_messages WHERE $AUTHOR $AND</div>~;
}
# select messages...
if ($vars{"administrator_$vars{'username'}"}) {
if ($vars{'publisher_action'} eq "editor") {
$MAIN .= qq~<!-- ONOToolBoxBlog: SQLDebugger: $AUTHOR $AND -->~;
}
# $MAIN .= qq~SQLDebugger: $AUTHOR $AND~;
}
my $autowidth_embed_pre = ONO::Lib::Video::Object->autowidth_embed_pre();
my $autowidth_embed_post = ONO::Lib::Video::Object->autowidth_embed_post();
foreach my $line (ONO::DB->select($db,"${community}_${TABLE}_messages","$AUTHOR AND flags NOT LIKE '%x%' $AND","date DESC, timestamp DESC","LIMIT $max_items OFFSET $offset")) {
my @col = ONO::DB->readcols($line);
$col[2] =~ s~(\n|\r|\t)~~g;
$col[2] = qq~<div class="dowrap">$col[2]</div>~;
# fix embedded youtube display:
$col[2] =~ s~\<iframe (.*?) src="https://www.youtube.com/embed/(.*?)"(.*?)\>\</iframe\>~${autowidth_embed_pre}https://www.youtube.com/embed/$2"${autowidth_embed_post}~g;
$counter++;
my $date = substr($col[6],6,2).". ".ONO::Lib::DateTime::ToolBox->month_name(substr($col[6],4,2),"",$lang)." ".substr($col[6],0,4);
$date =~ s~^0~~;
# image gallery
my ($IMG,$IMG_LEFT,$DOC,$VIDS,$VIDS_MORE,$AUDIO,$TEXTS,$img_count,$img_count_total,$vid_count,$vid_count_total);
if ($col[12] =~ m/[A-Za-z0-9]/) {
my $iswitch;
foreach my $sw ('i','I','K','Z') {
if ($vars{'blog_widget_switches'} =~ /$sw/) {
$iswitch .= $sw;
}
}
my (@images,@images_all,@vids,@docs,@audio,@texts);
$col[12] .= ":";
my @cp = split(/:/,$col[12]);
foreach my $img (@cp) {
if ($img =~ m/[A-Za-z0-9]/) {
if ($img =~ s~\*~~) {
foreach my $line (ONO::DB->select($db,"${community}_docs_dirs:doc_path","id_10 = '$img'")) {
my @row = ONO::DB->readcols($line);
foreach my $file (ONO::IO->dir($row[0])) {
if ($file !~ /^\./ && ONO::IO->image($file)) {
$img_count_total++;
if (!$max_files_per_entry || $img_count < $max_files_per_entry || $vars{'blog_focus'} == $col[0]) {
$img_count++;
@images = (@images,"/$row[0]/$file");
}
@images_all = (@images_all,"/$row[0]/$file");
}
if ($file !~ /^\./ && $file =~ /\.pdf$/i) {
@docs = (@docs,"/$row[0]/$file");
}
if ($file !~ /^\./ && $file =~ /\.mp4$/i) {
@vids = (@vids,"/$row[0]/$file");
}
if ($file !~ /^\./ && $file =~ /\.mp3$/i) {
@audio = (@audio,"/$row[0]/$file");
}
# if ($file !~ /^\./ && $file =~ /\.txt$/i) {
# @texts = (@texts,"/$row[0]/$file");
# }
}
}
} else {
foreach my $line (ONO::DB->select($db,"${community}_docs_files:doc_file,width,height","id_10 = '$img'")) {
my @row = ONO::DB->readcols($line);
if (ONO::IO->image($row[0])) {
$img_count_total++;
if (!$max_files_per_entry || $img_count < $max_files_per_entry || $vars{'blog_focus'} == $col[0]) {
$img_count++;
@images = (@images,"/$row[0]");
}
@images_all = (@images_all,"/$row[0]");
}
if ($row[0] =~ /\.pdf$/) {
@docs = (@docs,"/$row[0]");
}
if ($row[0] =~ /\.mp4$/i) {
@vids = (@vids,"/$row[0]");
}
if ($row[0] =~ /\.mp3$/i) {
@audio = (@audio,"/$row[0]");
}
# if ($row[0] =~ /\.txt$/i) {
# @texts = (@texts,"/$row[0]");
# }
}
if ($img =~ /^EMB-(YTB|VIM)-(.*)$/) {
my $vid = $2;
if ($1 eq "YTB") {
@vids = (@vids,"https://www.youtube.com/watch?v=$vid");
}
if ($1 eq "VIM") {
if ($vid =~ m~^(.*?)/(.*?)$~) {
@vids = (@vids,"https://www.vimeo.com/$1/$2\?copy=share");
} else {
@vids = (@vids,"https://www.vimeo.com/$vid");
}
}
}
if ($img =~ /^EMB-(TXT)-(.*)$/) {
my $txt = $2;
if ($1 eq "TXT") {
@texts = (@texts,$txt);
}
}
}
}
}
my $max_files = $max_files_per_entry;
if ($vars{'blog_focus'} == $col[0]) {
$max_files = "";
}
if ($vars{'blog_widget_gallery_firstrow'} == 2) {
$iswitch .= "y";
}
if ($vars{'blog_widget_gallery_firstrow'} == 3) {
$iswitch .= "Y";
}
if ($vars{'blog_widget_gallery_allrows'}) {
$iswitch .= $vars{'blog_widget_gallery_allrows'};
}
if ($switches =~ /e/) {
$iswitch .= "f";
}
# gallery editor access (for both editing and authenticated_browsing modes)
if ($vars{'username'} && $vars{'website'} && "$vars{'environment'}$vars{'school'}") {
my @logic = ("web","web","web");
if ($vars{'school'}) {
@logic = ("school_schoolweb","edu","schoolweb");
}
if (
ONO::FW::Web::ToolBox::Access->user_admin_of_website($db,$community,$logic[0],$vars{'username'},$vars{'website'}) ||
ONO::FW::Web::ToolBox::Access->user_admin_of_environment($db,$community,$logic[0],$logic[1],$logic[2],$vars{'username'},"$vars{'environment'}$vars{'school'}") ||
ONO::FW::Web::ToolBox::Access->user_teacher_in_virclass($db,$community,$vars{'username'},$col[3])
) {
$iswitch .= "f";
$MAIN .= qq~\n<!-- ONOToolBoxBlog: GalleryEditorAccess:Allowed -->\n~;
} else {
$MAIN .= qq~\n<!-- ONOToolBoxBlog: GalleryEditorAccess:Denied -->\n~;
}
}
if ($vars{'blog_widget_switches'} =~ /j/ && $img_count == 1) {
$IMG_LEFT .= ONO::ToolBox::Gallery->gallery(\@images,"RW$iswitch",\%vars,0,\@images_all);
} else {
$IMG .= ONO::ToolBox::Gallery->gallery(\@images,"RW$iswitch",\%vars,$max_files,\@images_all);
}
my $vid_count_total = @vids;
foreach my $vid (@vids) {
$vid_count++;
my ($vid,$status) = ONO::ToolBox::Gallery->protected($vid,"s");
if ($status) {
$VIDS .=qq~<div class="ml20">Video cannot be displayed here (password protected)</div>~;
} else {
if ($vid_count < 2) {
$VIDS .= qq~<div class="w100 auto">~;
$VIDS .= ONO::Lib::Video::Object->player($vid,"100%","auto","c");
$VIDS .= qq~</div>~;
} else {
$VIDS_MORE .= qq~<div class="w50 fl"><div class="p5">~;
$VIDS_MORE .= ONO::Lib::Video::Object->player($vid,"100%","auto","c");
$VIDS_MORE .= qq~</div></div>~;
}
}
}
if ($VIDS) {
$VIDS = qq~<div class="inline w100 p10 mb20">$VIDS</div>~;
}
if ($VIDS_MORE) {
$VIDS_MORE = qq~<div class="inline w100 mb20">$VIDS_MORE</div>~;
}
foreach my $aud (@audio) {
my $rand = ONO::Lib::Code::RandomID->make();
$AUDIO .= qq~<div class="w100 auto">~;
$AUDIO .= ONO::Lib::Audio::Object->player($rand,$aud,"");
$AUDIO .= qq~</div>~;
}
foreach my $doc (@docs) {
my $name = $doc;
$name =~ s~^(.*)/~~g;
$DOC .= qq~<tr>
<td><a href="$doc" target="_blank"><img class="block16" src="/ono/osr/images/icons/crystal/16x16/mimetypes/pdf.png" alt=""></a></td>
<td><a href="$doc" target="_blank">$name</a></td>
</tr>
~;
}
if ($DOC) {
$DOC = qq~<table class="default_table mb20">$DOC</table>~;
}
foreach my $txt (@texts) {
$txt =~ s~[^A-Za-z0-9]~~gi;
foreach my $line2 (ONO::DB->select($db,"${community}_docs_files","id_10 = '$txt'")) {
my @row2 = ONO::DB->readcols($line2);
$TEXTS .= qq~<div class="box_paper mb10"><h3>$row2[3]</h3>~;
$TEXTS .= ONO::IO->load($row2[2]);
$TEXTS .= qq~<div class="italic">$row2[8]</div></div>~;
}
}
}
my ($TXT,$ALL);
if ($img_count_total > $img_count && $vars{'blog_focus'} != $col[0]) {
my $LINK = "$ENV{'REQUEST_URI'}";
my $whilecounter;
while ($LINK =~ s~blog_focus=(.*?)\&~\&~ && $whilecounter < 256) {
$whilecounter++;
$LINK =~ s~blog_focus=(.*?)\&~\&~;
$LINK =~ s~\&\&~\&~;
}
$LINK =~ s~blog_focus=(.*?)$~~;
$LINK .= "&blog_focus=$col[0]";
if ($ENV{'REQUEST_URI'} !~ /\?/) {
$LINK = "$ENV{'REQUEST_URI'}?blog_focus=$col[0]";
}
my $BUTTON = qq~<a href="$LINK#blog_entry_$col[0]" class="button_green button_small">$BLK{'show_all'}</a>~;
$ALL = qq~<table class="default_table auto">
<tr>
<td class="pad10_2"><span class="bold">$img_count_total</span> $BLK{'images'}</td>
<td class="pad10_2">$BUTTON</td>
</tr>
</table>
~;
}
if ($IMG_LEFT) {
$TXT = qq~<div class="inline w100"><div class="fl w33">$IMG_LEFT</div>$col[2]</div>~;
if ($ALL) {
$TXT .= qq~<div class="inline w100"><div class="bt_light bb_light">$ALL</div></div>~;
}
} else {
if ($ALL) {
if ($img_count > 9) {
$IMG = qq~<div class="bt_light bb_light">$ALL</div>$IMG~;
}
$IMG .= qq~<div class="bt_light bb_light">$ALL</div>~;
}
$TXT = "$col[2]$IMG";
if ($col[2] =~ s~</p><p>~</p>$IMG<p>~) {
# $TXT = "<p>$col[2]</p>";
$TXT = $col[2];
}
}
$TXT .= $VIDS;
$TXT .= $VIDS_MORE;
$TXT .= $AUDIO;
$TXT .= $TEXTS;
$TXT .= $DOC;
if ($switches =~ /e/) {
my $color = "fabric";
my ($INFO,$INFO2,$ICON);
my $EDIT = qq~<a href="$script_url&blog_message_edit=1&blog_message_id=$col[0]"><img class="block16 fr ml5" src="/ono/osr/images/icons/ono/32x32/edit.png" alt=""></a>~;
my $MEDIA = qq~<a href="$script_url&blog_message_edit=1&blog_message_id=$col[0]&blog_message_edit_option=media">
<img class="block16 fr ml5" src="/ono/osr/images/icons/ono/32x32/image.png" alt="">
</a>
~;
if (!$col[8]) {
$color = "yellow";
$INFO = " - OFFLINE";
$EDIT = qq~<a href="$script_url&blog_message_edit=1&blog_message_id=$col[0]" class="button_yellow button_mini" style="float:right">$BLK{'publish'} / $BLK{'edit'}</a>~;
$MEDIA = "";
}
my $ARROW = qq~<img class="block16 fl rel" src="/ono/osr/images/icons/crystal/16x16/actions/agt_forward.png" style="top:3px;right:3px" alt="">~;
if ($community eq "school") {
$ICON = qq~<td><img class="block32 mr5" src="/ono/osr/images/icons/crystal/32x32/ono/classroom.png" alt=""></td>~;
if ($col[10] =~ /n/) {
if ($col[8]) {
$color = "blue";
}
$ICON = qq~<td><img class="block32 mr5" src="/ono/osr/images/icons/crystal/32x32/filesystems/network.png" alt=""></td>~;
$INFO2 .= qq~<div class="fr box_paper pad10_0 radius5 small mr5 ml10">$ARROW$BLK{'Website'} / $BLK{'Portal'}</div>~;
}
if ($col[10] =~ /b/) {
$INFO2 .= qq~<div class="fr box_paper pad10_0 radius5 small mr5 ml10">$ARROW$BLK{'Class'} / $BLK{'Blog'}</div>~;
}
if ($col[10] !~ /(n|b|r|x)/ || ($col[10] =~ /b/ && $col[10] =~ /n/)) {
if ($col[8]) {
$color = "blue";
}
$ICON = qq~<td><img class="block32 mr5" src="/ono/osr/images/icons/crystal/32x32/filesystems/network.png" alt=""></td>~;
$INFO2 = qq~<div class="fr box_paper pad10_0 radius5 small mr5 ml10">$ARROW$BLK{'Website'} & $BLK{'Class'}</div>~;
}
} else {
if ($col[10] =~ /n/) {
$INFO2 .= qq~<div class="fr box_paper pad10_0 radius5 small mr5 ml10">$ARROW$BLK{'News'}</div>~;
}
if ($col[10] =~ /b/) {
$INFO2 .= qq~<div class="fr box_paper pad10_0 radius5 small mr5 ml10">$ARROW$BLK{'Blog'}</div>~;
}
if ($col[10] =~ /r/) {
$INFO2 .= qq~<div class="fr box_paper pad10_0 radius5 small mr5 ml10">$ARROW$BLK{'Reviews'}</div>~;
}
if ($col[10] !~ /(n|b|r)/) {
$INFO2 .= qq~<div class="fr box_paper pad10_0 radius5 small mr5 ml10">$ARROW$BLK{'News'} & $BLK{'Blog'}</div>~;
}
}
if ($col[11]) {
my $CAT = ONO::DB->get($db,"title","${community}_${TABLE}_categories","id = '$col[11]'");
$INFO2 .= qq~<div class="fr box_paper pad10_0 radius5 small mr5">
<div class="inline" style="height:22px">
<img class="block16 fl rel" src="/ono/osr/images/icons/crystal/16x16/actions/agt_action_success.png" style="top:3px;right:3px" alt="">
$CAT
</div>
</div>
~;
}
my $COMM;
if ($vars{'blog_widget_switches'} =~ /C/ && $switches !~ /e/) {
$COMM .= &comments("",$db,$community,$TABLE,$col[0],$BLK_ref,$vars_ref,$sql_ref);
}
$MAIN .= qq~<div class="box_$color mt10">
<table class="wide_table mb5">
<tr class="vtop">
$ICON
<td class="w100">
$INFO2
<div class="lh125"><span class="large">$col[1]$INFO</span> <span class="smaxll">($date)</span></div>
</td>
<td class="p0 nowrap">
$EDIT
</td>
<td class="p0 nowrap">
$MEDIA
</td>
<td class="p0">
<a href="$script_url&blog_message_delete=1&blog_message_id=$col[0]">
<img class="block16 fr ml5" src="/ono/osr/images/icons/ono/32x32/delete.png" alt="">
</a>
</td>
</tr>
</table>
<div class="box_paper">
$TXT
$COMM
</div>
</div>
~;
} else {
my ($CLASS,$STYLE);
if ($counter > 1) {
$CLASS = " bt";
$STYLE = "padding-top:20px";
}
my $TITLE = qq~<$H2 class="m0">$col[1]</$H2>~;
my $STITLE = $col[1];
my $XTITLE = $col[1];
$XTITLE =~ s~[^A-Za-z0-9]~-~g;
$XTITLE = ONO::Lib::Basic->remove_doubles($XTITLE,"-",0,1);
my ($PERMALINK,$SOCIAL);
if ($ENV{'REQUEST_URI'} =~ m~/web/-/(.*?)/(.*?)/~) {
$PERMALINK = "http://$ENV{'SERVER_NAME'}/web/-/$1/$2/$col[0]:$XTITLE/";
} else {
if ($ENV{'REQUEST_URI'} =~ m~/web/-/(.*?)/~ && $vars{'publisher_page'}) {
$PERMALINK = "http://$ENV{'SERVER_NAME'}/web/-/$1/$vars{'publisher_page'}/$col[0]:$XTITLE/";
}
}
if ($target_page) {
$PERMALINK = "http://$ENV{'SERVER_NAME'}$target_page$col[0]:$XTITLE/";
}
if ($PERMALINK) {
$SOCIAL = ONO::Lib::Web::SocialBookmarking->blog_footer($PERMALINK,$col[1],"","X","mb");
$TITLE = qq~<a href="$PERMALINK">$TITLE</a>~;
$STITLE = qq~<a href="$PERMALINK">$STITLE</a>~;
}
my $TAGS = ONO::Lib::UI::Tags->tags($col[9]);
my $SOURCE;
if ($vars{'blog_widget_switches'} =~ /s/ && $col[3] =~ /^#/) {
my $virclass = $col[3];
$virclass =~ s~^#~~;
my $use = $virclass;
$use =~ s~[^0-9]~~g;
if ($use eq $virclass) {
if ($use && !$cache{$use}) {
my ($name,$cat) = ONO::DB->get($db,"fullname,cat","${community}_school_virclass","id = '$use'");
$cache{$use} = $name;
if ($cats[$cat]) {
$cache{$use} .= " ($cats[$cat])";
}
if ($vars{'blog_widget_switches'} =~ /q/) {
my $SCHOOL = ONO::DB->get($db,"virschool","${community}_school_virschool_relationships","virclass = '$use'");
if ($cache{"virschool_$SCHOOL"}) {
$SCHOOL = $cache{"virschool_$SCHOOL"};
} else {
$SCHOOL = ONO::DB->get($db,"fullname","${community}_school_virschool","id = '$SCHOOL'");
$cache{"virschool_$SCHOOL"} = $SCHOOL;
}
if ($SCHOOL =~ /[A-Za-z0-9]/ && $cache{$use} ne $SCHOOL) {
$cache{$use} .= " - $SCHOOL";
}
}
}
$SOURCE = qq~<div class="box_highlight radius5 small fr" style="padding:0px 10px 0px 10px">$cache{$use}</div>~;
if ($virclass_target_page) {
if (
ONO::IO->exists(ONO::Ext::Morzino::ToolBox->virclass_dir($virclass)."data/autoweb.txt") &&
!ONO::IO->exists(ONO::Ext::Morzino::ToolBox->virclass_dir($virclass)."data/autoweb_disabled.txt")
) {
my $VIR = "?virclass=$virclass";
if ($virclass_target_page =~ /\?/) {
$VIR = "&virclass=$virclass";
}
$SOURCE = qq~<a href="$virclass_target_page$VIR">$SOURCE</a>~;
} else {
$SOURCE = qq~<div class="trans50">$SOURCE</div>~;
}
}
}
}
my $EDITOR;
if ($vars{'username'} && $vars{'publisher_action'}) {
if ($vars{'username'} eq $col[3]) {
# link to the private blog -- not implemented yet
}
if ($col[3] =~ /^#WEB#(.*?)#/ && $vars{'blog_widget_editor_url'} && $vars{'website'} && "$vars{'environment'}$vars{'school'}") {
# link to the website manager if user is owner or admin of this environment
my @logic = ("web","web","web");
if ($vars{'school'}) {
@logic = ("school_schoolweb","edu","schoolweb");
}
if (
ONO::FW::Web::ToolBox::Access->user_admin_of_website($db,$community,$logic[0],$vars{'username'},$vars{'website'}) ||
ONO::FW::Web::ToolBox::Access->user_admin_of_environment($db,$community,$logic[0],$logic[1],$logic[2],$vars{'username'},"$vars{'environment'}$vars{'school'}")
) {
$EDITOR .= "$vars{'blog_widget_editor_url'}?";
foreach my $opt ('environment','school','website') {
if ($vars{$opt}) {
$EDITOR .= "$opt=$vars{$opt}&";
}
}
$EDITOR .= "mode=db_news&blog_message_id";
}
}
if ($col[3] =~ /^#([0-9]+)$/) {
# link to the website manager if user is owner of member of this classroom
my $virclass = $1;
if (ONO::Ext::Morzino::ToolBox->virclass_relationship($db,$community,$vars{'username'},$virclass)) {
$EDITOR = "/bin/virclass/?virclass=$virclass&mode=website&blog_message_edit=1&blog_message_id";
}
}
}
if ($EDITOR) {
$EDITOR = qq~<a href="$EDITOR=$col[0]&blog_message_delete=1"><img class="block20 ml5 fr" src="/ono/osr/images/icons/ono/32x32/delete.png" alt=""></a>
<a href="$EDITOR=$col[0]&blog_message_edit=1"><img class="block20 ml5 fr" src="/ono/osr/images/icons/ono/32x32/edit.png" alt=""></a>
~;
}
if ($switches =~ /L/) {
$TXT = qq~<div class="large">$TXT</div>~;
}
if ($col[3] !~ /#/) {
$date .= ", $BLK{'by'} $col[3]";
}
my $ENTRY = qq~<a id="blog_entry_$col[0]"></a>
<div class="$CLASS" style="$STYLE">
$CLOSE
$EDITOR
$SOURCE
$TITLE
<div class="small"><$H3 class="m0">$date</$H3></div>
<div class="inline w100">$TXT</div>
<div class="inline mb10">$TAGS</div>
$SOCIAL
</div>
~;
if ($switches =~ /l/) {
$ENTRY = qq~<div class="inline w100 bt"><div class="pad10_2">$STITLE</div></div>~;
}
if ($switches =~ /c/) {
$ENTRY = qq~$STITLE, ~;
}
$MAIN .= $ENTRY;
}
if ($vars{'blog_widget_switches'} =~ /C/ && $switches !~ /e/) {
$MAIN .= &comments("",$db,$community,$TABLE,$col[0],$BLK_ref,$vars_ref,$sql_ref);
}
}
if ($switches =~ /l/) {
$MAIN .= qq~<div class="bt"></div>~;
}
if ($switches =~ /c/) {
$MAIN =~ s~, $~~;
}
if ($total > $max_items) {
my $VARS;
foreach my $var ('class','filter','query','publisher_action','school','environment') {
if ($vars{$var}) {
$VARS .= qq~$var=$vars{$var}&~;
}
}
if ($vars{'website'} && $script_url !~ m~/-/$vars{'website'}/~) {
$VARS .= qq~website=$vars{'website'}&~;
}
if ($vars{'publisher_page'} && $script_url !~ m~/$vars{'publisher_page'}/~) {
$VARS .= qq~publisher_page=$vars{'publisher_page'}&~;
}
my $LINK = qq~$script_url?${VARS}page=~;
if ($script_url =~ /\?/) {
$LINK = qq~$script_url&${VARS}page=~;
}
$MAIN .= qq~<div class="mt10">~;
$MAIN .= ONO::Lib::UI::Page->nav(
1,
$vars{'page'},
1+int(($total-1)/$max_items),
$LINK,
);
$MAIN .= qq~</div>~;
}
return qq~\n\n<!-- ONOToolBoxBlog:Start -->\n\n$MAIN\n\n<!-- ONOToolBoxBlog:End-->\n\n~;
}
sub resize {
#: This is probably DEPRECATED
my ($w_max,$h_max,$w,$h) = @_;
if ($w > $w_max) {
my $ratio = $w/$h;
$w = $w_max;
$h = int($w_max/$ratio);
}
if ($h > $h_max) {
my $ratio = $w/$h;
$w = int($h_max*$ratio);
$h = $h_max;
}
return ($w,$h);
}
sub comments {
#: Display comments within a blog.
my (
$self,
$db,
$community,
$TABLE,
$id,
$BLK_ref,
$vars_ref,
$sql_ref,
) = @_;
my %vars = %$vars_ref;
my %conf;
my @opts = ('page','environment','school','website','virclass','class','publisher_page');
$id = ONO::Lib::Basic->add_leading_zeroes($id,10);
$conf{'dashboard_mode'} = "blog";
$conf{'dashboard_blog_table'} = $TABLE;
$conf{'dashboard_blog_id'} = $id;
$conf{'dashboard_form'} = qq~<input type="hidden" name="blog_message_id" value="$id">~;
if ($vars{'virclass'}) {
@opts = ('virclass','mode');
}
foreach my $key (@opts) {
if ($vars{$key}) {
$conf{'dashboard_form'} .= qq~<input type="hidden" name="$key" value="$vars{$key}">~;
}
}
my ($FEED,$UNUSED) = ONO::FW::User::Screen::Dashboard->screen($db,$community,"","",\%conf,$BLK_ref,$vars_ref,$sql_ref);
return $FEED;
}
sub view {
#: This feature has been deprecated since July 2021
return "";
}
###############################################################################
# end of script
###############################################################################
1;
__END__