Files
adsPRO/autoload/controls/class.Products.php
Jacek Pyziak f5db5263ab feat: Add Google Taxonomy integration and product editing enhancements
- Implemented Google Taxonomy loading via AJAX in main_view.php, allowing users to select categories for products.
- Enhanced product editing modal to include fields for product title, description, and Google category selection.
- Updated AJAX calls to save product data, including custom title, description, and selected Google category.
- Added character count validation for product title input.
- Integrated Select2 for improved category selection UI.
- Created google-taxonomy.php to fetch and cache Google Taxonomy data, ensuring efficient retrieval and fallback mechanisms.
- Removed outdated custom feed XML file.
- Updated layout-logged.php to include necessary Select2 styles and scripts.
2025-11-20 23:46:21 +01:00

354 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace controls;
class Products
{
static public function get_client_bestseller_min_roas() {
$client_id = \S::get( 'client_id' );
$min_roas = \factory\Products::get_client_bestseller_min_roas( $client_id );
if ( $min_roas )
{
echo json_encode( [ 'status' => 'ok', 'min_roas' => $min_roas ] );
}
else
echo json_encode( [ 'status' => 'error' ] );
exit;
}
static public function save_client_bestseller_min_roas() {
$client_id = \S::get( 'client_id' );
$min_roas = \S::get( 'min_roas' );
if ( \factory\Products::save_client_bestseller_min_roas( $client_id, $min_roas ) )
{
echo json_encode( [ 'status' => 'ok' ] );
}
else
echo json_encode( [ 'status' => 'error' ] );
exit;
}
static public function main_view()
{
return \Tpl::view( 'products/main_view', [
'clients' => \factory\Campaigns::get_clients(),
] );
}
static public function comment_add()
{
$product_id = \S::get( 'product_id' );
$date = \S::get( 'date' );
$comment = \S::get( 'comment' );
if ( \factory\Products::add_product_comment( $product_id, $comment, $date ) )
{
echo json_encode( [ 'status' => 'ok' ] );
}
else
echo json_encode( [ 'status' => 'error' ] );
exit;
}
static public function get_product_data() {
$product_id = \S::get( 'product_id' );
$product_title = \factory\Products::get_product_data( $product_id, 'title' );
$product_description = \factory\Products::get_product_data( $product_id, 'description' );
echo json_encode( [ 'status' => 'ok', 'product_details' => [ 'title' => $product_title, 'description' => $product_description ] ] );
exit;
}
static public function get_products()
{
$client_id = \S::get( 'client_id' );
$limit = \S::get( 'length' ) ? \S::get( 'length' ) : 10;
$start = \S::get( 'start' ) ? \S::get( 'start' ) : 0;
$order_dir = $_POST['order'][0]['dir'] ? strtoupper( $_POST['order'][0]['dir'] ) : 'DESC';
$order_name = $_POST['order'][0]['name'] ? $_POST['order'][0]['name'] : 'clicks';
$search = $_POST['search']['value'];
// ➊ MIN/MAX ROAS dla kontekstu klienta (opcjonalnie z filtrem search)
$bounds = \factory\Products::get_roas_bounds( $client_id, $search );
$roas_min = (float)$bounds['min'];
$roas_max = (float)$bounds['max'];
// zabezpieczenie przed dzieleniem przez 0
if ($roas_min === $roas_max) {
$roas_max = $roas_min + 0.000001;
}
// ➋ Helper do paska performance (lokalna funkcja)
$renderPerfBar = function (float $value, float $min, float $max): string
{
// normalizacja 0..1
$t = ($value - $min) / ($max - $min);
if ($t < 0) $t = 0;
if ($t > 1) $t = 1;
// szerokości
$minPx = 20; // minimalna długość paska
$maxPx = 120; // szerokość „toru”
$fill = (int)round($minPx + $t * ($maxPx - $minPx));
// kolor od #E74C3C (czerwony) do #2ECC71 (zielony)
$from = [231, 76, 60];
$to = [ 46,204,113];
$r = (int)round($from[0] + ($to[0] - $from[0]) * $t);
$g = (int)round($from[1] + ($to[1] - $from[1]) * $t);
$b = (int)round($from[2] + ($to[2] - $from[2]) * $t);
$hex = sprintf('#%02X%02X%02X', $r, $g, $b);
// prosty pasek (tor + wypełnienie)
return '<div class="roas-perf-wrap" title="Min: '.number_format($min,2).' | Max: '.number_format($max,2).'" style="margin-top:4px;width:'.$maxPx.'px;height:8px;background:#eee;border-radius:4px;overflow:hidden;">
<div class="roas-perf-fill" style="height:100%;width:'.$fill.'px;background:'.$hex.';"></div>
</div>';
};
$db_results = \factory\Products::get_products( $client_id, $search, $limit, $start, $order_name, $order_dir );
$recordsTotal = \factory\Products::get_records_total_products( $client_id, $search );
$data['draw'] = \S::get( 'draw' );
$data['recordsTotal'] = $recordsTotal;
$data['recordsFiltered'] = $recordsTotal;
foreach ( $db_results as $row )
{
$custom_class = '';
$custom_label_4 = \factory\Products::get_product_data( $row['product_id'], 'custom_label_4' );
$custom_name = \factory\Products::get_product_data( $row['product_id'], 'title' );
if ( $custom_name )
{
$row['name'] = $custom_name;
$custom_class = 'custom_name';
}
if ( $custom_label_4 == 'deleted' )
$custom_class = 'text-danger';
$custom_label_4_color = '';
if ( $custom_label_4 == 'bestseller' )
$custom_label_4_color = 'background-color:rgb(96, 119, 102); color: #FFF;';
else if ( $custom_label_4 == 'deleted' )
$custom_label_4_color = 'background-color:rgb(255, 0, 0); color: #FFF;';
else if ( $custom_label_4 == 'zombie' )
$custom_label_4_color = 'background-color:rgb(58, 58, 58); color: #FFF;';
else if ( $custom_label_4 == 'pla_single' )
$custom_label_4_color = 'background-color:rgb(49, 184, 9); color: #FFF;';
else if ( $custom_label_4 == 'pla' )
$custom_label_4_color = 'background-color:rgb(74, 63, 136); color: #FFF;';
else if ( $custom_label_4 == 'paused' )
$custom_label_4_color = 'background-color:rgb(143, 143, 143); color: #FFF;';
// ➌ ROAS liczba + pasek performance
$roasValue = (float)$row['roas'];
$roasNumeric = ($roasValue <= (float)$row['min_roas'])
? '<span class="text-danger text-bold">'.($roasValue).'</span>'
: $roasValue;
$roasPerfBar = $renderPerfBar($roasValue, $roas_min, $roas_max);
$roasCellHtml = '<div class="roas-cell">'.$roasNumeric.$roasPerfBar.'</div>';
$data['data'][] = [
$row['product_id'],
$row['offer_id'],
'<div class="table-product-title" product_id="' . $row['product_id'] . '">
<a href="/products/product_history/client_id=' . $client_id . '&product_id=' . $row['product_id'] . '" target="_blank" class="' . $custom_class . '">
' . $row['name'] . '
</a>
<span class="edit-product-title" product_id="' . $row['product_id'] . '">
<i class="fa fa-pencil"></i>
</span>
</div>',
$row['impressions'],
$row['impressions_30'],
'<span style="color: ' . ( $row['clicks'] > 200 ? ( $row['clicks'] > 400 ? '#0047ccff' : '#57b951' ) : '' ) . '">' . $row['clicks'] . '</span>',
$row['clicks_30'],
round( $row['ctr'], 2 ) . '%',
\S::number_display( $row['cost'] ),
\S::number_display( $row['cpc'] ),
round( $row['conversions'], 2 ),
\S::number_display( $row['conversions_value'] ),
$roasCellHtml,
'<input type="text" class="form-control min_roas" product_id="' . $row['product_id'] . '" value="' . $row['min_roas'] . '" style="width: 100px;">',
'',
'<input type="text" class="form-control custom_label_4" product_id="' . $row['product_id'] . '" value="' . $custom_label_4 . '" style="' . $custom_label_4_color . '">'
];
}
echo json_encode( $data );
exit;
}
static public function save_min_roas()
{
$product_id = \S::get( 'product_id' );
$min_roas = \S::get( 'min_roas' );
if ( \factory\Products::save_min_roas( $product_id, $min_roas ) )
{
echo json_encode( [ 'status' => 'ok' ] );
}
else
echo json_encode( [ 'status' => 'error' ] );
exit;
}
static public function save_custom_label_4()
{
$product_id = \S::get( 'product_id' );
$custom_label_4 = \S::get( 'custom_label_4' );
if ( \factory\Products::set_product_data( $product_id, 'custom_label_4', $custom_label_4 ) )
{
\factory\Products::add_product_comment( $product_id, 'Zmiana etykiety 4 na: ' . $custom_label_4 );
echo json_encode( [ 'status' => 'ok' ] );
}
else
echo json_encode( [ 'status' => 'error' ] );
exit;
}
static public function product_history()
{
$client_id = \S::get( 'client_id' );
$product_id = \S::get( 'product_id' );
return \Tpl::view( 'products/product_history', [
'client_id' => $client_id,
'product_id' => $product_id,
'min_roas' => \factory\Products::get_min_roas( $product_id )
] );
}
static public function get_product_history_table()
{
$client_id= \S::get( 'client_id' );
$product_id = \S::get( 'product_id' );
$start = \S::get( 'start' ) ? \S::get( 'start' ) : 0;
$limit = \S::get( 'length' ) ? \S::get( 'length' ) : 10;
$db_results = \factory\Products::get_product_history( $client_id, $product_id, $start, $limit );
$recordsTotal = \factory\Products::get_records_total_product_history( $client_id, $product_id );
$data['draw'] = \S::get( 'draw' );
$data['recordsTotal'] = $recordsTotal;
$data['recordsFiltered'] = $recordsTotal;
foreach ( $db_results as $row )
{
$roas_value = ( $row['cost'] > 0) ? ( $row['conversions_value'] / $row['cost'] ) * 100 : 0;
$roas = number_format( $roas_value, 0, '.', '' ) . '%';
$data['data'][] = [
$row['id'],
$row['impressions'],
$row['clicks'],
round( $row['ctr'], 2 ) . '%',
\S::number_display( $row['cost'] ),
$row['conversions'],
\S::number_display( $row['conversions_value'] ),
$roas,
$row['date_add'],
];
}
echo json_encode( $data );
exit;
}
static public function get_product_history_table_chart()
{
$client_id = \S::get( 'client_id' );
$product_id = \S::get( 'product_id' );
$limit = \S::get( 'length' ) ? \S::get( 'length' ) : 360;
$start = \S::get( 'start' ) ? \S::get( 'start' ) : 0;
$db_results = \factory\Products::get_product_history_30( $client_id, $product_id, $start, $limit );
$impressions = [];
$clicks = [];
$cost = [];
$conversions = [];
$conversions_value = [];
$roas = [];
$dates = [];
foreach ( $db_results as $row )
{
$impressions[] = (int)$row['impressions'];
$clicks[] = (int)$row['clicks'];
$ctr[] = (float)$row['ctr'];
$cost[] = (float)$row['cost'];
$conversions[] = (int)$row['conversions'];
$conversions_value[] = (float)$row['conversions_value'];
$roas[] = (float)$row['roas_all_time'];
$dates[] = $row['date_add'];
}
$chart_data = [
[
'name' => 'Wyświetlenia',
'data' => $impressions,
'visible' => false
], [
'name' => 'Kliknięcia',
'data' => $clicks,
'visible' => false
], [
'name' => 'CTR',
'data' => $ctr,
'visible' => false
], [
'name' => 'Koszt',
'data' => $cost,
'visible' => false
], [
'name' => 'Konwersje',
'data' => $conversions,
'visible' => false
], [
'name' => 'Wartość konwersji',
'data' => $conversions_value,
'visible' => false
], [
'name' => 'ROAS',
'data' => $roas
]
];
echo json_encode([
'chart_data' => $chart_data,
'dates' => $dates,
'comments' => \factory\Products::get_product_comments( $product_id ),
]);
exit;
}
static public function save_product_data()
{
$product_id = \S::get( 'product_id' );
$custom_title = \S::get( 'custom_title' );
$custom_description = \S::get( 'custom_description' );
$google_product_category = \S::get( 'google_product_category' );
if ( $product_id and $custom_title )
\factory\Products::set_product_data( $product_id, 'title', $custom_title );
if ( $product_id and $custom_description )
\factory\Products::set_product_data( $product_id, 'description', $custom_description );
if ( $product_id and $google_product_category )
\factory\Products::set_product_data( $product_id, 'google_product_category', $google_product_category );
\factory\Products::add_product_comment( $product_id, 'Zmiana tytułu i opisu produktu.' );
echo json_encode( [ 'status' => 'ok' ] );
exit;
}
}