update
This commit is contained in:
@@ -358,7 +358,7 @@ class Clients
|
||||
|
||||
$deleted_select = self::clients_has_deleted_column() ? 'COALESCE(deleted, 0) AS deleted' : '0 AS deleted';
|
||||
$client = $mdb -> query(
|
||||
"SELECT id, COALESCE(active, 0) AS active, " . $deleted_select . ", google_ads_customer_id, google_merchant_account_id, facebook_ads_account_id
|
||||
"SELECT id, COALESCE(active, 0) AS active, " . $deleted_select . ", google_ads_customer_id, google_merchant_account_id, facebook_ads_account_id, xml_feed_url
|
||||
FROM clients
|
||||
WHERE id = :id
|
||||
LIMIT 1",
|
||||
@@ -440,6 +440,33 @@ class Clients
|
||||
exit;
|
||||
}
|
||||
}
|
||||
else if ( $pipeline === 'xml_feed' )
|
||||
{
|
||||
$xml_feed_url = trim( (string) ( $client['xml_feed_url'] ?? '' ) );
|
||||
if ( $xml_feed_url === '' )
|
||||
{
|
||||
echo json_encode( [ 'success' => false, 'message' => 'Klient nie ma ustawionego XML Feed URL.' ] );
|
||||
exit;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$report = \services\XmlFeedImporter::import_for_client( $id );
|
||||
echo json_encode( [
|
||||
'success' => empty( $report['errors'] ),
|
||||
'pipeline' => 'xml_feed',
|
||||
'immediate' => true,
|
||||
'report' => $report,
|
||||
'message' => !empty( $report['errors'] ) ? implode( '; ', array_slice( (array) $report['errors'], 0, 3 ) ) : ''
|
||||
] );
|
||||
exit;
|
||||
}
|
||||
catch ( \Throwable $e )
|
||||
{
|
||||
echo json_encode( [ 'success' => false, 'message' => 'Blad importu XML feed: ' . $e -> getMessage() ] );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Domyslny reset (wszystkie pipeline oparte o cron_sync_status).
|
||||
|
||||
@@ -132,23 +132,6 @@ class Cron
|
||||
$products_temp_rows_total += (int) self::rebuild_products_temp_for_client( (int) $client['id'] );
|
||||
}
|
||||
|
||||
$xml_feed_report = null;
|
||||
if ( !empty( $client['xml_feed_url'] ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
$xml_feed_report = \services\XmlFeedImporter::import_for_client( (int) $client['id'] );
|
||||
if ( !empty( $xml_feed_report['errors'] ) )
|
||||
{
|
||||
$products_errors = array_merge( $products_errors, (array) $xml_feed_report['errors'] );
|
||||
}
|
||||
}
|
||||
catch ( \Throwable $e )
|
||||
{
|
||||
$products_errors[] = 'XML feed import: ' . $e -> getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
$errors = array_merge( $campaign_errors, $products_errors );
|
||||
|
||||
self::output_cron_response( [
|
||||
@@ -169,7 +152,6 @@ class Cron
|
||||
'products_fetch_skipped_reasons' => array_keys( $products_fetch_skipped_reasons ),
|
||||
'history_30_products' => $history_30_products_total,
|
||||
'products_temp_rows' => $products_temp_rows_total,
|
||||
'xml_feed' => $xml_feed_report,
|
||||
'errors' => $errors
|
||||
] );
|
||||
}
|
||||
@@ -567,6 +549,87 @@ class Cron
|
||||
] );
|
||||
}
|
||||
|
||||
static public function cron_xml_feed_import()
|
||||
{
|
||||
global $mdb;
|
||||
|
||||
self::$current_cron_action = __FUNCTION__;
|
||||
self::touch_cron_invocation( __FUNCTION__ );
|
||||
|
||||
$clients_not_deleted_sql_c = self::sql_clients_not_deleted( 'c' );
|
||||
$client_id = (int) \S::get( 'client_id' );
|
||||
$debug_offer_id = trim( (string) \S::get( 'debug_offer_id' ) );
|
||||
if ( $debug_offer_id === '' )
|
||||
{
|
||||
$debug_offer_id = trim( (string) \S::get( 'offer_id' ) );
|
||||
}
|
||||
|
||||
$params = [];
|
||||
$where_client = '';
|
||||
if ( $client_id > 0 )
|
||||
{
|
||||
$where_client = 'AND c.id = :client_id';
|
||||
$params[':client_id'] = $client_id;
|
||||
}
|
||||
|
||||
$client = $mdb -> query(
|
||||
"SELECT c.id, c.name, c.xml_feed_url, c.xml_feed_last_sync_at
|
||||
FROM clients c
|
||||
WHERE " . $clients_not_deleted_sql_c . "
|
||||
AND COALESCE(c.active, 0) = 1
|
||||
AND TRIM(COALESCE(c.xml_feed_url, '')) <> ''
|
||||
" . $where_client . "
|
||||
ORDER BY CASE WHEN c.xml_feed_last_sync_at IS NULL THEN 0 ELSE 1 END ASC,
|
||||
c.xml_feed_last_sync_at ASC,
|
||||
c.id ASC
|
||||
LIMIT 1",
|
||||
$params
|
||||
) -> fetch( \PDO::FETCH_ASSOC );
|
||||
|
||||
if ( !$client )
|
||||
{
|
||||
self::output_cron_response( [
|
||||
'result' => $client_id > 0 ? 'Nie znaleziono aktywnego klienta z ustawionym XML Feed URL.' : 'Brak aktywnych klientow z ustawionym XML Feed URL.',
|
||||
'client_id' => $client_id ?: null,
|
||||
'errors' => []
|
||||
] );
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$report = \services\XmlFeedImporter::import_for_client(
|
||||
(int) $client['id'],
|
||||
[ 'debug_offer_id' => $debug_offer_id ]
|
||||
);
|
||||
}
|
||||
catch ( \Throwable $e )
|
||||
{
|
||||
self::output_cron_response( [
|
||||
'result' => 'Import XML feed zakonczony bledem.',
|
||||
'client_id' => (int) $client['id'],
|
||||
'client_name' => (string) ( $client['name'] ?? '' ),
|
||||
'feed_url' => (string) ( $client['xml_feed_url'] ?? '' ),
|
||||
'errors' => [ $e -> getMessage() ]
|
||||
] );
|
||||
}
|
||||
|
||||
$errors = (array) ( $report['errors'] ?? [] );
|
||||
self::output_cron_response( [
|
||||
'result' => empty( $errors ) ? 'Import XML feed zakonczony.' : 'Import XML feed zakonczony z bledami.',
|
||||
'client_id' => (int) $client['id'],
|
||||
'client_name' => (string) ( $client['name'] ?? '' ),
|
||||
'feed_url' => (string) ( $report['feed_url'] ?? ( $client['xml_feed_url'] ?? '' ) ),
|
||||
'fetched' => (int) ( $report['fetched'] ?? 0 ),
|
||||
'updated' => (int) ( $report['updated'] ?? 0 ),
|
||||
'inserted' => (int) ( $report['inserted'] ?? 0 ),
|
||||
'skipped' => (int) ( $report['skipped'] ?? 0 ),
|
||||
'peak_memory_mb' => (float) ( $report['peak_memory_mb'] ?? 0 ),
|
||||
'duration_ms' => (int) ( $report['duration_ms'] ?? 0 ),
|
||||
'debug_offer' => $report['debug_offer'] ?? null,
|
||||
'errors' => $errors
|
||||
] );
|
||||
}
|
||||
|
||||
static public function cron_products_urls()
|
||||
{
|
||||
global $mdb, $settings;
|
||||
|
||||
@@ -376,6 +376,7 @@ class Users
|
||||
$cron_endpoints = [
|
||||
[ 'name' => 'Legacy CRON', 'path' => '/cron.php', 'action' => 'cron_legacy', 'plan' => '' ],
|
||||
[ 'name' => 'Cron uniwersalny (Google Ads)', 'path' => '/cron/cron_universal', 'action' => 'cron_universal', 'plan' => 'Co 1 min: kampanie (wczoraj) + frazy/produkty (7 dni wstecz) + Merchant URL + supplemental feed (raz dziennie)' ],
|
||||
[ 'name' => 'Cron XML Feed produktow', 'path' => '/cron/cron_xml_feed_import', 'action' => 'cron_xml_feed_import', 'plan' => 'Co 5-15 min: jeden aktywny klient z XML Feed URL, niezaleznie od Google Ads' ],
|
||||
[ 'name' => 'Cron alertow kampanii (Merchant)', 'path' => '/cron/cron_campaigns_product_alerts_merchant', 'action' => 'cron_campaigns_product_alerts_merchant', 'plan' => 'Co 15 min: alerty produktowe z Google Merchant' ],
|
||||
[ 'name' => 'Cron URL produktów (Merchant)', 'path' => '/cron/cron_products_urls', 'action' => 'cron_products_urls', 'plan' => '' ],
|
||||
[ 'name' => 'Cron Facebook Ads', 'path' => '/cron/cron_facebook_ads', 'action' => 'cron_facebook_ads', 'plan' => 'Co 5 min: 30 dni wstecz od wczoraj, blokada ponownego pobrania w tym samym dniu' ],
|
||||
|
||||
@@ -18,11 +18,12 @@ class XmlFeedImporter
|
||||
* @param int $client_id
|
||||
* @return array raport z polami: feed_url, fetched, updated, inserted, skipped, errors, peak_memory_mb, duration_ms
|
||||
*/
|
||||
static public function import_for_client( $client_id )
|
||||
static public function import_for_client( $client_id, array $options = [] )
|
||||
{
|
||||
global $mdb;
|
||||
|
||||
$client_id = (int) $client_id;
|
||||
$debug_offer_id = trim( (string) ( $options['debug_offer_id'] ?? '' ) );
|
||||
$report = [
|
||||
'feed_url' => '',
|
||||
'fetched' => 0,
|
||||
@@ -33,6 +34,18 @@ class XmlFeedImporter
|
||||
'peak_memory_mb' => 0,
|
||||
'duration_ms' => 0,
|
||||
];
|
||||
if ( $debug_offer_id !== '' )
|
||||
{
|
||||
$report['debug_offer'] = [
|
||||
'offer_id' => $debug_offer_id,
|
||||
'found_in_feed' => false,
|
||||
'custom_label_1_raw_present' => false,
|
||||
'custom_label_1_value' => '',
|
||||
'title_present' => false,
|
||||
'matched_existing_rows' => 0,
|
||||
'updated_rows' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
if ( $client_id <= 0 )
|
||||
{
|
||||
@@ -105,6 +118,22 @@ class XmlFeedImporter
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $debug_offer_id !== '' && (string) $item['offer_id'] === $debug_offer_id )
|
||||
{
|
||||
$report['debug_offer']['found_in_feed'] = true;
|
||||
$report['debug_offer']['custom_label_1_raw_present'] = !empty( $item['custom_label_1_raw_present'] );
|
||||
$report['debug_offer']['custom_label_1_value'] = (string) ( $item['custom_label_1'] ?? '' );
|
||||
$report['debug_offer']['title_present'] = trim( (string) ( $item['title'] ?? '' ) ) !== '';
|
||||
if ( !$report['debug_offer']['custom_label_1_raw_present'] )
|
||||
{
|
||||
$report['debug_offer']['missing_reason'] = 'custom_label_1_missing_in_feed';
|
||||
}
|
||||
else if ( trim( (string) $item['custom_label_1'] ) === '' )
|
||||
{
|
||||
$report['debug_offer']['missing_reason'] = 'custom_label_1_empty_in_feed';
|
||||
}
|
||||
}
|
||||
|
||||
$report['fetched']++;
|
||||
$batch[] = $item;
|
||||
|
||||
@@ -134,6 +163,11 @@ class XmlFeedImporter
|
||||
$reader -> close();
|
||||
@unlink( $tmp_file );
|
||||
|
||||
if ( $debug_offer_id !== '' && empty( $report['debug_offer']['found_in_feed'] ) )
|
||||
{
|
||||
$report['debug_offer']['missing_reason'] = 'offer_id_missing_in_feed';
|
||||
}
|
||||
|
||||
$mdb -> update( 'clients', [ 'xml_feed_last_sync_at' => date( 'Y-m-d H:i:s' ) ], [ 'id' => $client_id ] );
|
||||
|
||||
$report['peak_memory_mb'] = round( memory_get_peak_usage( true ) / 1024 / 1024, 1 );
|
||||
@@ -233,7 +267,22 @@ class XmlFeedImporter
|
||||
$description = trim( (string) $sxe -> description );
|
||||
}
|
||||
|
||||
$custom_label_1 = isset( $g -> custom_label_1 ) ? trim( (string) $g -> custom_label_1 ) : '';
|
||||
$custom_label_1_raw_present = isset( $g -> custom_label_1 );
|
||||
$custom_label_1 = $custom_label_1_raw_present ? trim( (string) $g -> custom_label_1 ) : '';
|
||||
if ( !$custom_label_1_raw_present && isset( $sxe -> custom_label_1 ) )
|
||||
{
|
||||
$custom_label_1_raw_present = true;
|
||||
$custom_label_1 = trim( (string) $sxe -> custom_label_1 );
|
||||
}
|
||||
if ( !$custom_label_1_raw_present )
|
||||
{
|
||||
$custom_label_1_fallback = self::get_text_by_local_name( $doc, 'custom_label_1' );
|
||||
if ( $custom_label_1_fallback !== null )
|
||||
{
|
||||
$custom_label_1_raw_present = true;
|
||||
$custom_label_1 = trim( (string) $custom_label_1_fallback );
|
||||
}
|
||||
}
|
||||
|
||||
$price = null;
|
||||
if ( isset( $g -> price ) )
|
||||
@@ -251,10 +300,25 @@ class XmlFeedImporter
|
||||
'title' => self::truncate( $title, 255 ),
|
||||
'description' => $description,
|
||||
'custom_label_1' => self::truncate( $custom_label_1, 255 ),
|
||||
'custom_label_1_raw_present' => $custom_label_1_raw_present,
|
||||
'price' => $price,
|
||||
];
|
||||
}
|
||||
|
||||
static private function get_text_by_local_name( \DOMDocument $doc, $local_name )
|
||||
{
|
||||
$local_name = (string) $local_name;
|
||||
foreach ( $doc -> getElementsByTagName( '*' ) as $node )
|
||||
{
|
||||
if ( $node -> localName === $local_name )
|
||||
{
|
||||
return $node -> textContent;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static private function parse_price( $raw )
|
||||
{
|
||||
if ( $raw === '' )
|
||||
@@ -341,15 +405,22 @@ class XmlFeedImporter
|
||||
$updated_count = 0;
|
||||
$inserted_count = 0;
|
||||
|
||||
$debug_offer_id = (string) ( $report['debug_offer']['offer_id'] ?? '' );
|
||||
|
||||
foreach ( $batch as $item )
|
||||
{
|
||||
$title = $item['title'] !== '' ? $item['title'] : null;
|
||||
$desc = $item['description'] !== '' ? $item['description'] : null;
|
||||
$cl1 = $item['custom_label_1'] !== '' ? $item['custom_label_1'] : null;
|
||||
$price = $item['price'];
|
||||
$is_debug_offer = $debug_offer_id !== '' && (string) $item['offer_id'] === $debug_offer_id;
|
||||
|
||||
if ( !empty( $existing[ $item['offer_id'] ] ) )
|
||||
{
|
||||
if ( $is_debug_offer )
|
||||
{
|
||||
$report['debug_offer']['matched_existing_rows'] = count( $existing[ $item['offer_id'] ] );
|
||||
}
|
||||
// aktualizujemy WSZYSTKIE legacy duplikaty (utrzymujemy spojnosc danych)
|
||||
foreach ( $existing[ $item['offer_id'] ] as $row_id )
|
||||
{
|
||||
@@ -361,6 +432,10 @@ class XmlFeedImporter
|
||||
':id' => $row_id,
|
||||
] );
|
||||
$updated_count++;
|
||||
if ( $is_debug_offer )
|
||||
{
|
||||
$report['debug_offer']['updated_rows']++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -374,6 +449,10 @@ class XmlFeedImporter
|
||||
':price' => $price,
|
||||
] );
|
||||
$inserted_count++;
|
||||
if ( $is_debug_offer )
|
||||
{
|
||||
$report['debug_offer']['inserted'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user