package ONO::ToolBox::PipeLine;
################################################################################
# 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::IO;
use ONO::Lib::DateTime::ToolBox;
use ONO::ToolBox::BlogEdit;
use ONO::ToolBox::Docs;
use ONO::ToolBox::Upload;
use ONO::Lib::Web::Upload;
use ONO::DB;
###############################################################################
# pipeline
###############################################################################
#: The ONO pipeline feature allows to upload files in an asynchronic way on a
#: static page.
sub count {
#: Count the number of files waiting in a user's pipeline.
my $count;
foreach my $file (ONO::IO->dir("media/users/".ONO::IO->deepdir($_[1])."/$_[1]/pipeline")) {
if ($file =~ /\./ && $file !~ /^\./) {
$count++;
}
}
return $count;
}
sub pipeline_click {
#: Generate JS code required to display a user pipeline.
my $ID = $_[1];
my $community = $_[2];
return qq~onojs_setwidth('${ID}_box','100%');onojs_setheight('${ID}_box','auto');onojs_ajax_load('/cgi-bin/local/perl/$community/ajax/exec.pl?mode=pipeline_display','${ID}_pipeline')~;
}
sub pipeline_wrapper {
my (
$self,
$ID,
$UPLOAD,
$lang
) = @_;
#: Generate the pipeline screen module launcher.
my @txt = (
"please wait",
"Don't forget to press the 'Upload' button after adding your files!",
);
if ($lang eq "de") {
@txt = (
"bitte warten",
"Vergiss nicht, die 'Upload'-Taste zu drücken, nachdem du deine Dateien ausgewählt hast!",
);
}
if ($lang eq "lu") {
@txt = (
"waarden w.e.g.",
"Vergiess net den 'Upload' Knäppchen ze drécken, nodeems du deng Dateien ausgewielt hues!",
);
}
if ($lang eq "fr") {
@txt = (
"veuillez attendre",
"N'oubliez pas d'appuyer sur le bouton 'Upload' après avoir sélectionné vos fichiers!",
);
}
return qq~<div id="${ID}_box" style="width:0px;height:0px;overflow:hidden">
<div id="${ID}_pipeline" class="flat_bottom">$txt[0]...</div>
<div id="${ID}_upload" class="flat_all">
$UPLOAD
</div>
<div class="box_red flat_top red mb10">$txt[1]</div>
</div>
~;
}
sub pipeline {
my (
$self,
$db,
$community,
$targets_ref,
$target_selected,
$lang,
$BLK_ref,
$vars_ref,
$switches,
$custom_prefs_ref,
) = @_;
#: Display the actual pipeline.
#:
#: -f flat bottom
#: -B no (save) button
#: -U upload tool
#:
#: custom_prefs:
#:
#: flag_C = 1 reserved (blog comments)
#: flag_D = 1 hide dir selector by default
my (@targets,%BLK,%custom_prefs);
if ($targets_ref) {
@targets = @$targets_ref;
}
if ($BLK_ref) {
%BLK = %$BLK_ref;
}
if ($custom_prefs_ref) {
%custom_prefs = %$custom_prefs_ref;
}
my %vars = %$vars_ref;
my @texts = (
"Select a target folder",
"will be created",
);
if ($lang eq "de") {
@texts = (
"Wähle einen Zielordner",
"wird erstellt werden",
);
}
if ($lang eq "lu") {
@texts = (
"Wiel en Zil-Verzeechnis",
"gëtt erschaf",
);
}
if ($lang eq "fr") {
@texts = (
"Sélectionnez un dossier cible",
"sera créé",
);
}
my $BASE = ONO::IO->base;
my $DIR = "media/users/".ONO::IO->deepdir($vars{'username'})."/$vars{'username'}/pipeline";
my ($PIPE,$counter);
my $total = 0;
my @files = ONO::IO->ls($DIR);
foreach my $file (@files) {
if ($file =~ /\./ && $file !~ /^\./) {
$total++;
}
}
foreach my $file (@files) {
if ($file =~ /\./ && $file !~ /^\./) {
$counter++;
my $ICON = ONO::ToolBox::Docs->mimetype_icon($file,128);
$ICON = qq~<div class="block100"><img class="block100" src="$ICON" alt=""></div>~;
if (ONO::IO->image($file)) {
$ICON = ONO::IO->getimage("/$DIR/$file",100,100);
$ICON = qq~<div class="block100 radius10" style="background-color:#333333;background-image:url('$BASE$ICON');background-size:cover;background-position:center"></div>~;
}
$PIPE .= qq~<div id="pipeline_file_$counter" class="fl mr10 mb10 rel"
onmouseover="onojs_class('pipeline_file_del_$counter','abs');"
onmouseout="onojs_class('pipeline_file_del_$counter','abs hide');">
<div id="pipeline_file_del_$counter" class="abs hide" style="top:0px;left:0px">
<a href="javascript:void(0);" onclick="onojs_hide('pipeline_file_$counter');
onojs_setvalue('pipeline_file_sel_${counter}_id','0');
onojs_pipeline_count('$total');
onojs_ajax_load('$BASE/cgi-bin/local/perl/$community/ajax/exec.pl?mode=pipeline_delete&file=$file');">
<img class="block16" src="$BASE/ono/osr/images/icons/ono/32x32/delete.png" alt="">
</a>
</div>
<img id="pipeline_file_chk_$counter" class="block32 abs" src="$BASE/ono/osr/images/icons/ono/32x32/checked.png" style="top:80px;left:80px" alt="">
<a href="javascript:void(0);" onclick="onojs_toggle('pipeline_file_sel_${counter}_id');onojs_pipeline_select('$counter','$total');">$ICON</a>
</div>
<input type="hidden" id="pipeline_file_sel_${counter}_id" name="pipeline_file_sel_$counter" value="1">
<input type="hidden" name="pipeline_filename_$counter" value="$file">
~;
}
}
my ($UPLOAD,$CLASS);
if ($switches =~ /U/) {
$UPLOAD .= qq~<div id="pipeline_upload_button" class="inline w100">
<a href="javascript:void(0);" onclick="onojs_hide('pipeline_upload_button');onojs_setwidth('pipeline_upload_tool','100%');onojs_setheight('pipeline_upload_tool','auto');"
class="button_green mt10">$BLK{'add'} / $BLK{'upload'}</a>
</div>
<div id="pipeline_upload_tool" style="width:0px;height:0px;overflow:hidden">
~;
my $http = ONO::IO->http;
my $UPLOAD_URL = "$http://$ENV{'SERVER_NAME'}$BASE".ONO::IO->upload_url($community)."mode=plupload&area=pipeline";
$UPLOAD .= ONO::Lib::Web::Upload->window(
"",
"onojs_ajax_load('$BASE/cgi-bin/local/perl/$community/ajax/exec.pl?mode=pipeline_display','pipeline_items')",
$UPLOAD_URL,"",ONO::ToolBox::Upload->file_extensions("A"),ONO::Lib::Web::Upload->max_file_size(),920,920,90,\%vars,$lang,$BLK_ref,"pP"
);
$UPLOAD .= qq~</div>~;
}
if ($switches =~ /f/) {
$CLASS .= " flat_bottom";
}
$PIPE = qq~<div class="box_paper$CLASS">
<div id="pipeline_items">
<table class="default_table fr">
<tr>
<td class="p0">
<a href="javascript:void(0);" onclick="onojs_pipeline_select_all('$total');"
class="button_green button_mini button_left">$BLK{'all'}</a>
</td>
<td class="p0">
<a href="javascript:void(0);" onclick="onojs_pipeline_select_none('$total');"
class="button_orange button_mini button_right">$BLK{'none'}</a>
</td>
</tr>
</table>
<h3>$BLK{'Files'} <span class="small">(<span id="pipeline_file_selcount">$total</span> $BLK{'selected'})</span></h3>
<div class="inline w100">
$PIPE
</div>
</div>
$UPLOAD
</div>
~;
my ($TARGETS,$targets,$TARGET_DIRS,$TARGET_DESEL,%used,$target_selected_num,$fav_subdir,$TARGETS_SHOW);
foreach my $target (@targets) {
$target =~ s~\'~~g;
my @tp = split(/:/,$target);
$tp[1] =~ s~[^A-Za-z0-9]~~;
if ($tp[0] && $tp[1] && $tp[2] && !$used{"$tp[0]:$tp[1]"} && $targets < 256) {
$used{"$tp[0]:$tp[1]"}++;
$targets++;
if (!$target_selected) {
$target_selected = $target;
}
my $color = "paper";
my $hide_dirs = " hide";
if ($target eq $target_selected) {
$color = "black";
$hide_dirs = "";
$target_selected_num = $targets;
}
my $IMG = "/ono/osr/images/icons/crystal/32x32/kdm/user_male.png";
my $DIR = "media/users/".ONO::IO->deepdir($vars{'username'})."/$vars{'username'}/public";
my @FAVS;
if ($tp[0] eq "user") {
@FAVS = ONO::IO->list("media/users/".ONO::IO->deepdir($vars{'username'})."/$vars{'username'}/favorites.txt");;
}
if ($tp[0] eq "virclass") {
$IMG = "/ono/osr/images/icons/crystal/32x32/ono/classroom.png";
$DIR = "media/virclass/$tp[1]/public";
@FAVS = ONO::IO->list("media/virclass/$tp[1]/favorites.txt");
foreach my $line (ONO::DB->select($db,"${community}_school_virschool_relationships","virclass = '$tp[1]'")) {
my @row = ONO::DB->readcols($line);
@FAVS = (@FAVS,ONO::IO->list("community/portal/school/$row[2]/docs/global_favorites.txt"));
if (ONO::IO->exists("community/portal/school/$row[2]/docs/global_favorites_subdir.txt")) {
$fav_subdir = ONO::IO->load("community/portal/school/$row[2]/docs/global_favorites_subdir.txt");
}
if (ONO::IO->exists("community/portal/school/$row[2]/docs/global_disable_subdir_selector.txt")) {
$custom_prefs{'flag_D'}++;
}
}
}
if ($tp[0] eq "schoolweb") {
$IMG = "/ono/osr/images/icons/crystal/32x32/filesystems/network.png";
$DIR = "schoolweb/".ONO::IO->deepdir($tp[1])."/$tp[1]/media";
@FAVS = ONO::IO->list("schoolweb/".ONO::IO->deepdir($tp[1])."/$tp[1]/favorites.txt");;
}
if ($tp[0] eq "web") {
$IMG = "/ono/osr/images/icons/crystal/32x32/filesystems/network.png";
$DIR = "web/".ONO::IO->deepdir($tp[1])."/$tp[1]/media";
@FAVS = ONO::IO->list("web/".ONO::IO->deepdir($tp[1])."/$tp[1]/favorites.txt");;
}
my ($DIRS,$DIRS_WARN,$TARGET_FAVS,$dircount,%used_dirs,$counter,$first);
foreach my $opt (ONO::ToolBox::BlogEdit->media_targets($db,$community,$tp[1],$vars_ref,1)) {
$counter++;
my @op = split(/:/,$opt);
$op[0] =~ s~/$~~;
my $NAME = $op[0];
$NAME =~ s~^(.*)/~~;
$DIRS .= qq~<option value="path:$op[0]">$NAME</option>~;
my $ICON;
if ($op[1] && $op[1] ne "folder") {
$ICON = qq~<img class="block32 abs" src="/ono/osr/images/icons/crystal/128x128/filesystems/$op[1].png" style="top:25px;left:5px" alt="">~;
}
my $color2 = "paper";
if (!$first) {
$first++;
$color2 = "black";
}
my $status = qq~<span class="lightred">$texts[1]</span>~;
if (ONO::IO->exists($op[0])) {
$status = qq~<span class="lightgreen">$BLK{'found'}</span>~;
}
$TARGET_FAVS .= qq~<div id="pipeline_target_favbox_${targets}_$counter" class="box_$color2 box_fabric_hover radius10 fl mr10 mb10"
onclick="pipeline_target_favbox_select('$targets','$counter','$op[0]','$custom_prefs{'flag_D'}');">
<div class="block64 auto rel">
<img class="block64" src="/ono/osr/images/icons/crystal/128x128/filesystems/folder.png" alt="">
$ICON
</div>
<div class="lh125 center">
$NAME
<div class="xsmall col9">$op[0]</div>
<div class="small">$status</div>
</div>
</div>
~;
$TARGET_DESEL .= qq~onojs_class('pipeline_target_favbox_${targets}_$counter','box_paper box_fabric_hover radius10 fl mr10 mb10');~;
}
if ($DIRS) {
$DIRS .= qq~<option value="">----</option>~;
}
my $SCHOOLYEAR;
if ($community eq "school") {
$SCHOOLYEAR = ONO::Lib::DateTime::ToolBox->schoolyear();
}
foreach my $fav (sort @FAVS) {
$fav =~ s~_schoolyear_~$SCHOOLYEAR~g;
my @fp = split(/\^/,$fav);
if (!$fp[1]) {
$fp[1] = $fp[0];
$fp[1] =~ s~^(.*)/~~;
}
if ($fp[0] !~ m~\/\*\/$~) {
$DIRS .= qq~<option value="path:$fp[0]">$fp[1]</option>~;
}
}
if ($DIRS) {
$DIRS .= qq~<option value="">----</option>~;
}
foreach my $dir (ONO::IO->dir($DIR,"","","","RX")) {
$dircount++;
if ($dir !~ /\./ && $dir !~ /^_/ && $dircount < 101 && !$used_dirs{$dir}) {
$used_dirs{$dir}++;
$DIRS .= qq~<option value="dir:$dir">$dir</option>~;
}
}
if ($DIRS) {
if ($dircount > 100) {
$DIRS_WARN = qq~<div class="box_red radius5 pad5_2 ml5 lightred">too many directories...</div>~;
}
my $color2 = "paper";
if (!$first) {
$color2 = "black";
}
my $TARGET_DIRS_MORE_BUTTON;
my $hide_dir_sel;
my $hide_dir_sel_status = 1;
if ($custom_prefs{'flag_D'} && $TARGET_FAVS) {
$hide_dir_sel = " hide";
$hide_dir_sel_status = 0;
$TARGET_DIRS_MORE_BUTTON = qq~<a href="javascript:void(0);" onclick="onojs_block('pipeline_target_favbox_${targets}_0');
onojs_setvalue('pipeline_target_favbox_${targets}_0_status_id','1');
onojs_hide('pipeline_target_favbox_${targets}_0_button');">
<div id="pipeline_target_favbox_${targets}_0_button" class="box_paper radius5 pad5_2 fl">
<table class="default_table">
<tr>
<td><img class="block24" src="/ono/osr/images/icons/crystal/32x32/actions/agt_forward.png" alt=""></td>
<td>$BLK{'more'}...</td>
</tr>
</table>
</div>
</a>
~;
}
$TARGET_DIRS .= qq~<div id="pipeline_target_dirs_$targets" class="$hide_dirs">
$TARGET_FAVS
<div id="pipeline_target_favbox_${targets}_0" class="box_$color2 box_fabric_hover radius10 fl mr10 mb10$hide_dir_sel"
onclick="pipeline_target_favbox_select('$targets','0','','$custom_prefs{'flag_D'}');">
<img class="block64 auto" src="/ono/osr/images/icons/crystal/128x128/filesystems/folder.png" alt="">
<div class="mb5 center">$BLK{'select'}...</div>
<div class="inline">
<div class="select"><select id="pipeline_target_dir_${targets}_id" name="pipeline_target_dir_$targets">$DIRS</select></div>
$DIRS_WARN
</div>
</div>
$TARGET_DIRS_MORE_BUTTON
<input type="hidden" id="pipeline_target_favbox_${targets}_0_status_id" name="pipeline_target_favbox_${targets}_0_status" value="$hide_dir_sel_status">
</div>
~;
my $hide;
if ($targets > 3 && $target_selected_num && !$vars{'website'}) {
$hide = " hide";
$TARGETS_SHOW .= qq~onojs_inline('pipeline_target_$targets');~;
}
$TARGETS .= qq~<a href="javascript:void(0);"
onclick="onojs_setvalue('pipeline_target_id','$target');onojs_setvalue('pipeline_target_num_id','$targets');onojs_pipeline_target_select('$targets');">
<div id="pipeline_target_$targets" class="box_$color pad10_2 radius5 fl mr5 mb5$hide">
<table class="default_table">
<tr>
<td><img class="block24" src="$IMG" alt=""></td>
<td>$tp[2]</td>
</tr>
</table>
</div>
</a>
~;
}
}
}
if ($targets > 3) {
$TARGETS .= qq~<a href="javascript:void(0);" onclick="$TARGETS_SHOW;onojs_hide('pipeline_target_more');">
<div id="pipeline_target_more" class="box_paper pad10_2 radius5 fl mr5 mb5">
<table class="default_table">
<tr>
<td><img class="block24" src="/ono/osr/images/icons/crystal/32x32/actions/agt_forward.png" alt=""></td>
<td>$BLK{'more'}...</td>
</tr>
</table>
</div>
</a>
~;
}
if ($TARGETS && $targets) {
my $SAVE;
if ($switches !~ /B/) {
$SAVE = qq~<div class="inline">$BLK{'submit_save'}</div>~;
}
my $DATE = ONO::Lib::DateTime::ToolBox->select_date(
"pipeline_target_subdir_date",
ONO::Lib::DateTime::ToolBox->get("","","y")-5,
ONO::Lib::DateTime::ToolBox->get("","","y")+5,
ONO::Lib::DateTime::ToolBox->get("","","S"),
$lang,
"mTPj",
);
my %sel;
my @hide = ('hide','hide');
if ($fav_subdir) {
$sel{$fav_subdir} = " selected";
if ($fav_subdir eq "name") {
$hide[0] = "";
}
if ($fav_subdir eq "date") {
$hide[1] = "";
}
}
$PIPE .= qq~<div id="pipeline_targets" class="box_paper mt10">
<h3>$BLK{'Target'}</h3>
<div class="inline w100">$TARGETS</div>
<div class="p5"></div>
<h4>$texts[0]:</h4>
<div class="inline w100">$TARGET_DIRS</div>
<div class="p5"></div>
<h4>$BLK{'Subdirectory'} ($BLK{'optional'}, $BLK{'but'} $BLK{'recommended'}):</h4>
<input type="hidden" id="pipeline_target_id" name="pipeline_target" value="$target_selected">
<input type="hidden" id="pipeline_target_num_id" name="pipeline_target_num" value="$target_selected_num">
<div class="box_black pad5_2 radius5 mt5">
<table class="default_table">
<tr>
<td class="hide720 p0"><img class="block24" src="/ono/osr/images/icons/crystal/32x32/filesystems/folder.png" alt=""></td>
<td>
<div class="select"><select id="pipeline_target_subdir_type_id" name="pipeline_target_subdir_type" onchange="onojs_pipeline_target_subdir_update();">
<option value=""></option>
<option value="">----</option>
<option value="name"$sel{'name'}>$BLK{'name'}</option>
<option value="date"$sel{'date'}>$BLK{'date'}</option>
</select></div>
</td>
<td class="hide720 p0"></td>
<td id="pipeline_target_subdir_name_id" class="$hide[0]"><input type="text" name="pipeline_target_subdir_name" style="width:220px"></td>
<td id="pipeline_target_subdir_date_id" class="$hide[1]">$DATE</td>
</tr>
</table>
</div>
$SAVE
</div>
<script>
function pipeline_target_favbox_select(targets,box,dir,hide_sel) {
onojs_class('pipeline_target_favbox_'+targets+'_0','box_paper box_fabric_hover radius10 fl mr10 mb10');
if (hide_sel > 0 && onojs_getvalue('pipeline_target_favbox_'+targets+'_0_status_id') < 1) {
onojs_class('pipeline_target_favbox_'+targets+'_0','box_paper box_fabric_hover radius10 fl mr10 mb10 hide');
}
$TARGET_DESEL
onojs_class('pipeline_target_favbox_'+targets+'_'+box,'box_black box_fabric_hover radius10 fl mr10 mb10');
if (box > 0) {
onojs_setvalue('pipeline_target_dir_'+targets+'_id','path:'+dir);
}
}
</script>
~;
}
return $PIPE;
}
sub targets {
my (
$self,
$db,
$community,
$vars_ref,
$sql_ref,
) = @_;
#: Detect possible targets for files that shall leave the pipeline.
my %vars = %$vars_ref;
my %sql = %$sql_ref;
my $target_selected = "user:$vars{'username'}:$vars{'username'}";
my @targets = ($target_selected);
my %blog_prefs;
if ($community eq "school" && $vars{'class'} && $vars{'virclass_auth'} eq "teacher") {
my $virclass = $vars{'class'};
$virclass =~ s~[^0-9]~~g;
my $virname = ONO::DB->get($db,"fullname","${community}_school_virclass","id = '$virclass'");
$target_selected = "virclass:$virclass:$virname";
@targets = (@targets,$target_selected);
foreach my $line (ONO::DB->select($db,"${community}_school_schoolweb_sites","edu_owner = '$vars{'username'}'")) {
my @row = ONO::DB->readcols($line);
@targets = (@targets,"schoolweb:$row[1]:$row[6]");
}
foreach my $line (ONO::DB->select($db,"${community}_school_schoolweb_admins_sites","admin = '$vars{'username'}'")) {
my @row = ONO::DB->readcols($line);
my $schoolname = ONO::DB->get($db,"fullname", "${community}_school_schoolweb_sites","id_10 = '$row[2]'");
if ($schoolname) {
@targets = (@targets,"schoolweb:$row[2]:$schoolname");
}
}
foreach my $line (ONO::IO->list(ONO::Ext::Morzino::ToolBox->virclass_dir($virclass)."data/blog_prefs.txt")) {
$line =~ s~(\n|\r|\t)~~g;
my @lp = split(/:/,$line);
$blog_prefs{$lp[0]} = $lp[1];
}
}
if ($vars{'website'} && ($vars{'school'} || $vars{'environment'})) {
my $TABLE = "${community}_school_schoolweb_sites";
my $WHERE = "school = '$sql{'school'}'";
foreach my $line (ONO::DB->select($db,$TABLE,$WHERE)) {
my @row = ONO::DB->readcols($line);
@targets = (@targets,"schoolweb:$row[1]:$row[6]");
}
}
return (\@targets,$target_selected,\%blog_prefs);
}
###############################################################################
# end of script
###############################################################################
1;
__END__