From 4107a759c0c8245ee626f34399b8d495b0ed97d3 Mon Sep 17 00:00:00 2001 From: Riccardo Di Dato Date: Mon, 19 Sep 2022 21:08:49 +0200 Subject: [PATCH] #4 - Rework stat banner --- app/private/bin/convertStats.php | 25 ++- app/private/lib/BannerHelper.php | 231 ++++++++++++++++++++- app/private/lib/PipelineHelper.php | 53 +++-- app/private/lib/gui/GUIHandler.php | 17 +- app/private/lib/gui/GUIHandlerMobile.php | 13 +- app/private/lib/gui/html.inclusion.php | 5 + app/public/admin/statCustom.php | 2 +- app/public/admin/statSito.php | 2 +- app/public/articolo.php | 6 +- app/public/categorySummary.php | 6 +- app/public/getBanner.php | 1 + app/public/getImage.php | 2 +- app/public/js/banner.js | 70 +++++++ app/public/mobile/articolo.php | 12 +- app/public/mobile/categorySummary.php | 16 +- app/public/mobile/getBanner.php | 1 + app/public/stats/bannerImpression.php | 2 +- app/public/stats/bannerMultiImpression.php | 44 ++++ scripts/core.sh | 6 + 19 files changed, 442 insertions(+), 72 deletions(-) create mode 100644 app/public/js/banner.js create mode 100644 app/public/stats/bannerMultiImpression.php diff --git a/app/private/bin/convertStats.php b/app/private/bin/convertStats.php index b2bca81..16567ae 100755 --- a/app/private/bin/convertStats.php +++ b/app/private/bin/convertStats.php @@ -16,12 +16,16 @@ function getModels() { $ret = GlobalVariables::get("dao")->query( StatisticModel::class, - [], + [ + 'transfered' => [ + '$ne' => true + ] + ], [ 'sort' => [ 'date' => 1 ], - 'skip' => $iteration * $size, + // 'skip' => $iteration * $size, 'limit' => $size ] ); @@ -58,13 +62,13 @@ while (sizeof($models)>0) { } else if ($model->statType == StatisticModel::STAT_TYPE_PAGE) { AnalyticsHelper::pageImpression( - $model->content->notizia, + $model->content, date("d", $ts), date("m", $ts), date("Y", $ts), - !array_key_exists($model->user->id, $userDay), - !array_key_exists($model->user->id, $userMonth), - $model->user->isNew + is_null($model->user) || !array_key_exists($model->user->id, $userDay), + is_null($model->user) || !array_key_exists($model->user->id, $userMonth), + is_null($model->user) || $model->user->isNew ); } else if ($model->statType == StatisticModel::STAT_TYPE_BANNER_CLICK) { @@ -84,8 +88,13 @@ while (sizeof($models)>0) { ); } - $userDay[ $model->user->id ] = 1; - $userMonth[ $model->user->id ] = 1; + if (!is_null($model->user)) { + $userDay[ $model->user->id ] = 1; + $userMonth[ $model->user->id ] = 1; + } + + $model->transfered = true; + GlobalVariables::get("dao")->save($model); } echo "Completed iteration $iteration", PHP_EOL; diff --git a/app/private/lib/BannerHelper.php b/app/private/lib/BannerHelper.php index 670ebdb..09bb54f 100644 --- a/app/private/lib/BannerHelper.php +++ b/app/private/lib/BannerHelper.php @@ -4,24 +4,241 @@ Author: Riccardo Di Dato Creation Date: 11/mar/2016 */ -class BannerHelper{ +class BannerHelper { + private static $useCategory = null; private static $INTERNAL_COUNT = 1; + + private static $positions = []; + + public static function setCategory($category) { + self::$useCategory = $category; + } + + private static function getCategory() { + return is_null((self::$useCategory)) ? BannerModel::GENERAL_CATEGORY : self::$useCategory; + } - public static function printBanner($position = BannerModel::POSITION_HEAD, $category = null){ - if (is_null($category)){ - $category = BannerModel::GENERAL_CATEGORY; - } + public static function printBanner($position = BannerModel::POSITION_HEAD){ + $category = BannerModel::GENERAL_CATEGORY; $cur = self::getPlaceholderId(); + + if (!array_key_exists($position, self::$positions)) { + self::$positions[$position] = []; + } + self::$positions[$position][] = $cur; ?> -
+
+
0) { + echo ''; + } + } + + + private static function getBannerMapWithViews() { + $bannerMap = self::getActiveBannersMap(); + $stats = self::getBannerImpressions(self::getAllBannerIds($bannerMap)); + + foreach ($bannerMap as &$list) { + foreach ($list['banners']['prio'] as &$bann ) { + $id = strval($bann['id']); + $bann['views'] = array_key_exists($id, $stats) ? $stats[ $id ] : 0; + } + foreach ($list['banners']['generic'] as &$bann ) { + $id = strval($bann['id']); + $bann['views'] = array_key_exists($id, $stats) ? $stats[ $id ] : 0; + } + } + return $bannerMap; + } + + + private static function getBannerImpressions($bannerIds) { + $stats = GlobalVariables::get("dao")->query( + BannerStatsModel::class, + [ + '_id' => [ + '$in' => array_map( + function($banner) { + return new \MongoDB\BSON\ObjectID($banner); + }, + $bannerIds + ) + ], + ] + ); + $rval = array_reduce( + $bannerIds, + function ($carry, $cur) { + $carry[$cur] = 0; + return $carry; + }, + [] + ); + foreach ($stats as $stat) { + $rval[strval($stat->id)] = intval($stat->views); + } + return $rval; + } + + + private static function getAllBannerIds($bannerMap) { + $rval = []; + foreach ($bannerMap as $type => $list) { + foreach ($list['banners']['prio'] as $k => $bann ) { + $rval[$bann['id']] = $bann['id']; + } + foreach ($list['banners']['generic'] as $k => $bann ) { + $rval[$bann['id']] = $bann['id']; + } + } + return array_keys($rval); + } + + private static function getActiveBannersMap() { + if (sizeof(self::$positions) > 0) { + return array_reduce( + array_keys(self::$positions), + function ($carry, $pos) { + $cur = self::$positions[$pos]; + + $carry[$pos] = [ + 'placeholders' => $cur, + 'banners' => self::getActiveBanners($pos) + ]; + return $carry; + }, + [] + ); + } + else { + return []; + } + } + + + private static function getActiveBanners(int $position) { + $categoryMode = self::getCategory() !== BannerModel::GENERAL_CATEGORY; + $catQuery = [ + BannerModel::GENERAL_CATEGORY + ]; + if ($categoryMode) { + $catQuery = [ + '$elemMatch' => [ + '$in' => [ + self::getCategory(), + BannerModel::GENERAL_CATEGORY + ] + ] + ]; + } + $banners = GlobalVariables::get("dao")->query( + BannerModel::class, + [ + 'position' => $position, + 'categories' => $catQuery, + 'start' => [ + '$lte' => new MongoDB\BSON\UTCDateTime( strtotime("today") * 1000 ) + ], + 'end' => [ + '$gte' => new MongoDB\BSON\UTCDateTime( strtotime("tomorrow") * 1000 ) + ] + ], + [ + 'limit' => 20 + ] + ); + $medias = self::fetchBannerMedias($banners); + if ($categoryMode) { + return array_reduce( + $banners, + function ($carry, $cur) use ($medias) { + $key = 'generic'; + $info = self::simplifyBannerInfo($cur, $medias); + if (in_array(self::getCategory(), $cur->categories) ) { + $key = 'prio'; + } + if (array_key_exists('media', $info)) { + $carry[$key][] = $info; + } + return $carry; + }, + [ + 'prio' => [], + 'generic' => [] + ] + ); + } + else { + return [ + 'prio' => [], + 'generic' => + array_filter( + array_map( + function ($elem) use ($medias) { + return self::simplifyBannerInfo($elem, $medias); + }, + $banners + ), + function ($ele) { + return array_key_exists('media', $ele); + } + ) + ]; + } + } + + /** + * @param BannerModel[] $banners + */ + private static function fetchBannerMedias(array $banners) { + $medias = GlobalVariables::get("dao")->query( + MediaModel::class, + [ + '_id' => [ + '$in' => array_map( + function($banner) { + return new \MongoDB\BSON\ObjectID($banner->mainMedia); + }, + $banners + ) + ], + ] + ); + return array_reduce( + $medias, + function ($carry, $cur) { + $carry[strval($cur->id)] = $cur; + return $carry; + }, + [] + ); + } + + + private static function simplifyBannerInfo($banner, $medias) { + + $rval = [ + 'id' => strval($banner->id), + 'link' => $banner->link + ]; + + if (array_key_exists($banner->mainMedia, $medias)) { + $rval['media'] = $medias[$banner->mainMedia]->asText(); + } + + return $rval; + } } ?> \ No newline at end of file diff --git a/app/private/lib/PipelineHelper.php b/app/private/lib/PipelineHelper.php index 73e3841..d06669f 100644 --- a/app/private/lib/PipelineHelper.php +++ b/app/private/lib/PipelineHelper.php @@ -84,17 +84,22 @@ class PipelineHelper { ] ], [ - '$addFields' => [ - "visualizzazioni" => '$views', - "unici" => '$absNewVisitors', - "visitatori" => '$dayNewVisitors' + '$group' => [ + '_id' => [ + 'y' => '$y', + 'm' => '$m', + 'd' => '$d' + ], + 'visualizzazioni' => ['$sum' => '$views'], + 'unici' => ['$sum' => '$absNewVisitors'], + 'visitatori' => ['$sum' => '$dayNewVisitors'], ] ], [ '$sort' => [ - "y"=>1, - "m"=>1, - "d"=>1 + "_id.y"=>1, + "_id.m"=>1, + "_id.d"=>1 ] ] ]; @@ -111,17 +116,28 @@ class PipelineHelper { ] ], [ - '$addFields' => [ - "visualizzazioni" => '$views', - "unici" => '$absNewVisitors', - "visitatori" => '$dayNewVisitors' + '$group' => [ + "_id" => [ + 'y' => '$y', + 'm' => '$m', + 'd' => '$d' + ], + "visualizzazioni" => [ + '$sum' => '$views' + ], + "unici" => [ + '$sum' => '$absNewVisitors' + ], + "visitatori" => [ + '$sum' => '$dayNewVisitors' + ], ] ], [ '$sort' => [ - "y"=>1, - "m"=>1, - "d"=>1 + "_id.y"=>1, + "_id.m"=>1, + "_id.d"=>1 ] ] ]; @@ -149,17 +165,10 @@ class PipelineHelper { '$sum' => '$absNewVisitors' ], "visitatori" => [ - '$sum' => '$absNewVisitors' + '$sum' => '$monthNewVisitors' ], ] ], - [ - '$addFields' => [ - "visualizzazioni" => '$views', - "unici" => '$absNewVisitors', - "visitatori" => '$monthNewVisitors' - ] - ], [ '$sort' => [ "_id.y"=>1, diff --git a/app/private/lib/gui/GUIHandler.php b/app/private/lib/gui/GUIHandler.php index 4c57ceb..17c453f 100644 --- a/app/private/lib/gui/GUIHandler.php +++ b/app/private/lib/gui/GUIHandler.php @@ -175,7 +175,7 @@ class GUIHandler { self::$onLoadEvents[] = $script; } - public static function generateHeadPublic($bannerCategory = BannerModel::GENERAL_CATEGORY){ + public static function generateHeadPublic(){ $mesi = array(1=>'Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre','Dicembre'); @@ -215,11 +215,11 @@ class GUIHandler {
- +
- +
@@ -349,6 +349,7 @@ class GUIHandler { aggregate( ArticleStatsModel::class, @@ -411,8 +412,8 @@ class GUIHandler { ?>
-
-
+
+
@@ -435,8 +436,8 @@ class GUIHandler {
-
-
+
+
'Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre','Dicembre'); @@ -377,6 +377,7 @@ class GUIHandlerMobile { aggregate( ArticleStatsModel::class, PipelineHelper::getMostViewedOfLastDays(strtotime("-7 days"),5) @@ -436,8 +437,8 @@ class GUIHandlerMobile { ?>
-
-
+
+
@@ -460,8 +461,8 @@ class GUIHandlerMobile {
-
-
+
+
aggregate( ); for ($i=0; $i
diff --git a/app/public/articolo.php b/app/public/articolo.php index ed37ae1..8f3dc23 100644 --- a/app/public/articolo.php +++ b/app/public/articolo.php @@ -113,6 +113,8 @@ try { $sendComment = true; } } + + BannerHelper::setCategory($articolo->category); }catch(GUIException $ex){ $error = $ex->getMessage(); @@ -132,7 +134,7 @@ GUIHandler::generateHtmlHeaders(array("additionalMetadata"=>$additionalHeaders,"
category); + GUIHandler::generateHeadPublic(); GUIHandler::generateMenu(); ?>
@@ -319,7 +321,7 @@ GUIHandler::generateHtmlHeaders(array("additionalMetadata"=>$additionalHeaders,"
- category);?> +
query("NotiziaModel", // array("status"=>NotiziaModel::STATUS_ACCEPTED,"category"=>$category,"about.data"=>array('$lte'=>new MongoDate())), @@ -58,7 +60,7 @@ try{ ?>
- +
getFirst("MediaModel",array("id"=>$_GET['id'])); - if (!is_null($img)){ + if (!is_null($img) && file_exists($basepath."/".$img->id.".".$img->extension)){ $basepath = GlobalVariables::get("config")->paths->media; $toMime = $basepath."/".$img->id.".".$img->extension; $thumb = new Imagick($basepath."/".$img->id.".".$img->extension); diff --git a/app/public/js/banner.js b/app/public/js/banner.js new file mode 100644 index 0000000..6e8e95c --- /dev/null +++ b/app/public/js/banner.js @@ -0,0 +1,70 @@ +const MAX_EXECUTIONS = 12; +const ROTATION_INTERVAL = 30000; + +const executions = {}; + +function banner(mapping) { + + Object.keys(mapping).forEach( + (cur) => { + bannerGroup(mapping[cur], cur); + } + ); +} + +function bannerGroup(group, grpName) { + resortGroup(group); + executions[grpName] = executions[grpName] ? executions[grpName] + 1 : 1; + + const amount = group.placeholders.length; + const rval = group.banners.prio.slice(0, amount); + if (rval.length < amount) { + rval.push( + ...group.banners.generic.slice(0, amount - rval.length) + ); + } + if (rval.length > 0) { + $.ajax({ + url: "stats/bannerMultiImpression.php", + method: "POST", + data: { + banners: rval.map(e => e.id).join(","), + source: document.URL + }, + dataType: "html" + }); + rval.forEach(v => { + v.views++; + }); + const enough = rval.length == amount; + group.placeholders.forEach( + (target) => { + if (rval.length > 0) { + const ele = rval.shift(); + $('#'+target).html(ele.media); + } + } + ); + + if (enough && executions[grpName] <= MAX_EXECUTIONS) { + setTimeout( + () => { + bannerGroup(group, grpName); + }, + ROTATION_INTERVAL + ); + } + + } + +} + + +function resortGroup(group) { + group.banners.prio.sort(compareEle) + group.banners.generic.sort(compareEle) +} + +function compareEle(a, b) { + return a.views >= b.views; +} \ No newline at end of file diff --git a/app/public/mobile/articolo.php b/app/public/mobile/articolo.php index c8151a8..ef2b26b 100644 --- a/app/public/mobile/articolo.php +++ b/app/public/mobile/articolo.php @@ -136,8 +136,8 @@ GUIHandlerMobile::generateHtmlHeaders(array("additionalMetadata"=>$additionalHea
-
-
+
+
;"> category]["label"]);?> @@ -198,8 +198,8 @@ GUIHandlerMobile::generateHtmlHeaders(array("additionalMetadata"=>$additionalHea
-
-
+
+
testo;?>
@@ -217,8 +217,8 @@ GUIHandlerMobile::generateHtmlHeaders(array("additionalMetadata"=>$additionalHea
-
-
+
+
diff --git a/app/public/mobile/categorySummary.php b/app/public/mobile/categorySummary.php index bf91193..78e1788 100644 --- a/app/public/mobile/categorySummary.php +++ b/app/public/mobile/categorySummary.php @@ -29,6 +29,8 @@ try{ // $category = NotiziaModel::CATEGORY_CRONACA; $category = intval($category); + + BannerHelper::setCategory($category); // $notizie = GlobalVariables::get("dao")->query("NotiziaModel", // array("status"=>NotiziaModel::STATUS_ACCEPTED,"category"=>$category,"about.data"=>array('$lte'=>new MongoDate())), @@ -60,12 +62,12 @@ try{ ?>
-
-
+
+
0){ @@ -88,16 +90,16 @@ try{ if($i==3 || $i==sizeof($notizie)){ ?>
-
-
+
+
-
-
+
+
log(LoggingFacility::$LEVEL_INFO,"Dropped statistical data coming from referer '".$host."'"); + } + } + else { + LoggingFacilityManager::getLogger("gui")->log(LoggingFacility::$LEVEL_INFO,"Dropped statistical data coming from null referer. Related ip '".$_SERVER['REMOTE_ADDR']."'"); + } +} +catch (Exception $ex){ + LoggingFacilityManager::getLogger("gui")->log(LoggingFacility::$LEVEL_INFO,"Error while logging statistical data. Message: '".$ex->getMessage()."'"); +} + +?> \ No newline at end of file diff --git a/scripts/core.sh b/scripts/core.sh index da3dfc5..0a62872 100755 --- a/scripts/core.sh +++ b/scripts/core.sh @@ -120,4 +120,10 @@ if [[ $DEBUG_MODE -eq 1 ]]; then cd "$OUT_FOLDER" docker-compose up -d + + set -a + source $OUT_FOLDER/environments/local/webserver.env + set +a + + xdg-open "$DDNINJA_PUBLIC_URL" fi