|
|
|
|
@@ -7,6 +7,11 @@ use ROITheme\Admin\Infrastructure\Ui\AdminDashboardRenderer;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* FormBuilder para AdSense Placement y Google Analytics
|
|
|
|
|
*
|
|
|
|
|
* Panel reorganizado con:
|
|
|
|
|
* - Diagrama visual de ubicaciones
|
|
|
|
|
* - Secciones colapsables
|
|
|
|
|
* - In-content ads configurables (1-8 random)
|
|
|
|
|
*/
|
|
|
|
|
final class AdsensePlacementFormBuilder
|
|
|
|
|
{
|
|
|
|
|
@@ -27,7 +32,7 @@ final class AdsensePlacementFormBuilder
|
|
|
|
|
$html .= ' AdSense y Analytics';
|
|
|
|
|
$html .= ' </h3>';
|
|
|
|
|
$html .= ' <p class="mb-0 small" style="opacity: 0.85;">';
|
|
|
|
|
$html .= ' Configura Google AdSense y Google Analytics';
|
|
|
|
|
$html .= ' Configura Google AdSense y Analytics con ubicaciones visuales';
|
|
|
|
|
$html .= ' </p>';
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
@@ -36,18 +41,19 @@ final class AdsensePlacementFormBuilder
|
|
|
|
|
// LAYOUT 2 COLUMNAS
|
|
|
|
|
$html .= '<div class="row g-3">';
|
|
|
|
|
|
|
|
|
|
// COLUMNA IZQUIERDA
|
|
|
|
|
$html .= ' <div class="col-lg-6">';
|
|
|
|
|
// COLUMNA IZQUIERDA (7 cols)
|
|
|
|
|
$html .= ' <div class="col-lg-7">';
|
|
|
|
|
$html .= $this->buildVisibilityGroup($componentId);
|
|
|
|
|
$html .= $this->buildAnalyticsGroup($componentId);
|
|
|
|
|
$html .= $this->buildCredentialsGroup($componentId);
|
|
|
|
|
$html .= $this->buildDiagramSection();
|
|
|
|
|
$html .= $this->buildPostLocationsGroup($componentId);
|
|
|
|
|
$html .= $this->buildInContentAdsGroup($componentId);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
|
|
|
|
|
// COLUMNA DERECHA
|
|
|
|
|
$html .= ' <div class="col-lg-6">';
|
|
|
|
|
// COLUMNA DERECHA (5 cols)
|
|
|
|
|
$html .= ' <div class="col-lg-5">';
|
|
|
|
|
$html .= $this->buildCredentialsGroup($componentId);
|
|
|
|
|
$html .= $this->buildAnalyticsGroup($componentId);
|
|
|
|
|
$html .= $this->buildRailAdsGroup($componentId);
|
|
|
|
|
$html .= $this->buildArchiveLocationsGroup($componentId);
|
|
|
|
|
$html .= $this->buildExclusionsGroup($componentId);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
|
|
|
|
|
@@ -58,24 +64,27 @@ final class AdsensePlacementFormBuilder
|
|
|
|
|
|
|
|
|
|
private function buildVisibilityGroup(string $cid): string
|
|
|
|
|
{
|
|
|
|
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">';
|
|
|
|
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #28a745;">';
|
|
|
|
|
$html .= ' <div class="card-body">';
|
|
|
|
|
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
|
|
|
|
$html .= ' <i class="bi bi-toggle-on me-2" style="color: #FF8600;"></i>';
|
|
|
|
|
$html .= ' Activacion AdSense';
|
|
|
|
|
$html .= ' <i class="bi bi-power me-2" style="color: #28a745;"></i>';
|
|
|
|
|
$html .= ' Activacion Global';
|
|
|
|
|
$html .= ' </h5>';
|
|
|
|
|
|
|
|
|
|
// Switch: Enabled
|
|
|
|
|
$html .= '<div class="row g-3">';
|
|
|
|
|
$html .= ' <div class="col-md-4">';
|
|
|
|
|
$enabled = $this->renderer->getFieldValue($cid, 'visibility', 'is_enabled', false);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'Enabled', 'Activar AdSense', $enabled, 'bi-power');
|
|
|
|
|
|
|
|
|
|
// Switch: Show on Mobile
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-md-4">';
|
|
|
|
|
$showMobile = $this->renderer->getFieldValue($cid, 'visibility', 'show_on_mobile', true);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'ShowOnMobile', 'Mostrar en movil', $showMobile, 'bi-phone');
|
|
|
|
|
|
|
|
|
|
// Switch: Show on Desktop
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-md-4">';
|
|
|
|
|
$showDesktop = $this->renderer->getFieldValue($cid, 'visibility', 'show_on_desktop', true);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'ShowOnDesktop', 'Mostrar en escritorio', $showDesktop, 'bi-display');
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
@@ -83,32 +92,261 @@ final class AdsensePlacementFormBuilder
|
|
|
|
|
return $html;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function buildAnalyticsGroup(string $cid): string
|
|
|
|
|
/**
|
|
|
|
|
* Diagrama visual de ubicaciones de anuncios
|
|
|
|
|
*/
|
|
|
|
|
private function buildDiagramSection(): string
|
|
|
|
|
{
|
|
|
|
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">';
|
|
|
|
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #6f42c1;">';
|
|
|
|
|
$html .= ' <div class="card-body">';
|
|
|
|
|
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
|
|
|
|
$html .= ' <i class="bi bi-graph-up me-2" style="color: #FF8600;"></i>';
|
|
|
|
|
$html .= ' Google Analytics';
|
|
|
|
|
$html .= ' <i class="bi bi-layout-text-window-reverse me-2" style="color: #6f42c1;"></i>';
|
|
|
|
|
$html .= ' Mapa de Ubicaciones';
|
|
|
|
|
$html .= ' </h5>';
|
|
|
|
|
|
|
|
|
|
// Switch: Analytics Enabled
|
|
|
|
|
$analyticsEnabled = $this->renderer->getFieldValue($cid, 'analytics', 'analytics_enabled', false);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'AnalyticsEnabled', 'Activar Analytics', $analyticsEnabled, 'bi-power');
|
|
|
|
|
// Diagrama visual del layout
|
|
|
|
|
$html .= '<div class="border rounded p-3" style="background: #f8f9fa; font-family: monospace; font-size: 11px;">';
|
|
|
|
|
|
|
|
|
|
// Tracking ID
|
|
|
|
|
$gaTrackingId = $this->renderer->getFieldValue($cid, 'analytics', 'ga_tracking_id', '');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'GaTrackingId', 'Google Analytics ID', $gaTrackingId, 'G-XXXXXXXXXX');
|
|
|
|
|
$html .= '<div class="form-text small mb-2">Formato: G-XXXXXXXXXX o UA-XXXXXXXX-X</div>';
|
|
|
|
|
// Header
|
|
|
|
|
$html .= '<div class="text-center p-2 mb-1 rounded" style="background: #e9ecef; border: 1px dashed #6c757d;">';
|
|
|
|
|
$html .= ' <strong>HEADER</strong>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// Anonymize IP
|
|
|
|
|
$gaAnonymizeIp = $this->renderer->getFieldValue($cid, 'analytics', 'ga_anonymize_ip', true);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'GaAnonymizeIp', 'Anonimizar IP (GDPR)', $gaAnonymizeIp, 'bi-shield-check');
|
|
|
|
|
// Hero / Featured Image
|
|
|
|
|
$html .= '<div class="text-center p-2 mb-1 rounded" style="background: #d1e7dd; border: 1px solid #198754;">';
|
|
|
|
|
$html .= ' <i class="bi bi-image"></i> Featured Image / Hero';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= ' <div class="alert alert-warning small mb-0 mt-2">';
|
|
|
|
|
$html .= ' <i class="bi bi-exclamation-triangle me-1"></i>';
|
|
|
|
|
$html .= ' Recomendado activar para cumplir con GDPR/RGPD';
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
// Ad: Post Top
|
|
|
|
|
$html .= '<div class="text-center p-2 mb-1 rounded" style="background: #fff3cd; border: 2px solid #ffc107;">';
|
|
|
|
|
$html .= ' <i class="bi bi-megaphone"></i> <strong>📍 POST-TOP</strong> (Despues de imagen)';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// Content container
|
|
|
|
|
$html .= '<div class="p-2 mb-1 rounded" style="background: #fff; border: 1px solid #dee2e6;">';
|
|
|
|
|
$html .= ' <div class="mb-1 small text-muted text-center">📝 CONTENIDO DEL POST</div>';
|
|
|
|
|
$html .= ' <div class="p-1 rounded mb-1" style="background: #e7f1ff; font-size: 10px;">Parrafo 1...</div>';
|
|
|
|
|
$html .= ' <div class="p-1 rounded mb-1" style="background: #e7f1ff; font-size: 10px;">Parrafo 2...</div>';
|
|
|
|
|
$html .= ' <div class="p-1 rounded mb-1" style="background: #e7f1ff; font-size: 10px;">Parrafo 3...</div>';
|
|
|
|
|
|
|
|
|
|
// In-content ad
|
|
|
|
|
$html .= ' <div class="text-center p-1 mb-1 rounded" style="background: #fff3cd; border: 2px dashed #ffc107; font-size: 10px;">';
|
|
|
|
|
$html .= ' <i class="bi bi-megaphone"></i> <strong>📍 IN-CONTENT #1</strong>';
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
|
|
|
|
|
$html .= ' <div class="p-1 rounded mb-1" style="background: #e7f1ff; font-size: 10px;">Parrafo 4...</div>';
|
|
|
|
|
$html .= ' <div class="p-1 rounded mb-1" style="background: #e7f1ff; font-size: 10px;">Parrafo 5...</div>';
|
|
|
|
|
$html .= ' <div class="p-1 rounded mb-1" style="background: #e7f1ff; font-size: 10px;">Parrafo 6...</div>';
|
|
|
|
|
|
|
|
|
|
// In-content ad 2
|
|
|
|
|
$html .= ' <div class="text-center p-1 mb-1 rounded" style="background: #fff3cd; border: 2px dashed #ffc107; font-size: 10px;">';
|
|
|
|
|
$html .= ' <i class="bi bi-megaphone"></i> <strong>📍 IN-CONTENT #2</strong> (random)';
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
|
|
|
|
|
$html .= ' <div class="p-1 rounded" style="background: #e7f1ff; font-size: 10px;">Mas parrafos...</div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// Ad: Post Bottom
|
|
|
|
|
$html .= '<div class="text-center p-2 mb-1 rounded" style="background: #fff3cd; border: 2px solid #ffc107;">';
|
|
|
|
|
$html .= ' <i class="bi bi-megaphone"></i> <strong>📍 POST-BOTTOM</strong> (Despues del contenido)';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// Related Posts
|
|
|
|
|
$html .= '<div class="text-center p-2 mb-1 rounded" style="background: #cfe2ff; border: 1px solid #0d6efd;">';
|
|
|
|
|
$html .= ' <i class="bi bi-grid-3x2"></i> Related Posts';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// Ad: After Related
|
|
|
|
|
$html .= '<div class="text-center p-2 mb-1 rounded" style="background: #fff3cd; border: 2px solid #ffc107;">';
|
|
|
|
|
$html .= ' <i class="bi bi-megaphone"></i> <strong>📍 AFTER-RELATED</strong>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// Footer
|
|
|
|
|
$html .= '<div class="text-center p-2 rounded" style="background: #e9ecef; border: 1px dashed #6c757d;">';
|
|
|
|
|
$html .= ' <strong>FOOTER</strong>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// Rail Ads (laterales)
|
|
|
|
|
$html .= '<div class="mt-2 d-flex justify-content-between">';
|
|
|
|
|
$html .= ' <div class="p-2 rounded text-center" style="width: 45%; background: #f8d7da; border: 2px solid #dc3545; font-size: 10px;">';
|
|
|
|
|
$html .= ' <strong>📍 RAIL IZQ</strong><br><small>(160x600)</small>';
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="p-2 rounded text-center" style="width: 45%; background: #f8d7da; border: 2px solid #dc3545; font-size: 10px;">';
|
|
|
|
|
$html .= ' <strong>📍 RAIL DER</strong><br><small>(160x600)</small>';
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= '<div class="mt-2 small text-muted">';
|
|
|
|
|
$html .= ' <i class="bi bi-info-circle"></i> Los anuncios <span class="badge bg-warning text-dark">amarillos</span> son configurables abajo.';
|
|
|
|
|
$html .= ' Los <span class="badge bg-danger">rojos</span> solo aparecen en pantallas >1600px.';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
return $html;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function buildPostLocationsGroup(string $cid): string
|
|
|
|
|
{
|
|
|
|
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #ffc107;">';
|
|
|
|
|
$html .= ' <div class="card-body">';
|
|
|
|
|
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
|
|
|
|
$html .= ' <i class="bi bi-geo-alt me-2" style="color: #ffc107;"></i>';
|
|
|
|
|
$html .= ' Ubicaciones en Posts';
|
|
|
|
|
$html .= ' </h5>';
|
|
|
|
|
|
|
|
|
|
// === POST-TOP ===
|
|
|
|
|
$html .= '<div class="border rounded p-3 mb-3" style="background: #fffbeb;">';
|
|
|
|
|
$html .= '<div class="d-flex align-items-center gap-2 mb-2">';
|
|
|
|
|
$html .= ' <span class="badge bg-warning text-dark">POST-TOP</span>';
|
|
|
|
|
$html .= ' <small class="text-muted">Despues de la imagen destacada</small>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= '<div class="row g-2">';
|
|
|
|
|
$html .= ' <div class="col-md-6">';
|
|
|
|
|
$postTopEnabled = $this->renderer->getFieldValue($cid, 'behavior', 'post_top_enabled', true);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'PostTopEnabled', 'Activar', $postTopEnabled);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-md-6">';
|
|
|
|
|
$html .= $this->buildSelect($cid . 'PostTopFormat', 'Formato',
|
|
|
|
|
$this->renderer->getFieldValue($cid, 'behavior', 'post_top_format', 'auto'),
|
|
|
|
|
[
|
|
|
|
|
'auto' => 'Auto (responsive)',
|
|
|
|
|
'in-article' => 'In-Article (fluid)',
|
|
|
|
|
'display' => 'Display (728x90)',
|
|
|
|
|
'display-large' => 'Display Large (970x250)'
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// === POST-BOTTOM ===
|
|
|
|
|
$html .= '<div class="border rounded p-3 mb-3" style="background: #fffbeb;">';
|
|
|
|
|
$html .= '<div class="d-flex align-items-center gap-2 mb-2">';
|
|
|
|
|
$html .= ' <span class="badge bg-warning text-dark">POST-BOTTOM</span>';
|
|
|
|
|
$html .= ' <small class="text-muted">Despues del contenido, antes de Related</small>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= '<div class="row g-2">';
|
|
|
|
|
$html .= ' <div class="col-md-6">';
|
|
|
|
|
$postBottomEnabled = $this->renderer->getFieldValue($cid, 'behavior', 'post_bottom_enabled', true);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'PostBottomEnabled', 'Activar', $postBottomEnabled);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-md-6">';
|
|
|
|
|
$html .= $this->buildSelect($cid . 'PostBottomFormat', 'Formato',
|
|
|
|
|
$this->renderer->getFieldValue($cid, 'behavior', 'post_bottom_format', 'auto'),
|
|
|
|
|
['auto' => 'Auto', 'in-article' => 'In-Article', 'display' => 'Display']
|
|
|
|
|
);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// === AFTER-RELATED ===
|
|
|
|
|
$html .= '<div class="border rounded p-3" style="background: #fffbeb;">';
|
|
|
|
|
$html .= '<div class="d-flex align-items-center gap-2 mb-2">';
|
|
|
|
|
$html .= ' <span class="badge bg-warning text-dark">AFTER-RELATED</span>';
|
|
|
|
|
$html .= ' <small class="text-muted">Despues de Related Posts</small>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= '<div class="row g-2">';
|
|
|
|
|
$html .= ' <div class="col-md-6">';
|
|
|
|
|
$afterRelatedEnabled = $this->renderer->getFieldValue($cid, 'behavior', 'after_related_enabled', false);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'AfterRelatedEnabled', 'Activar', $afterRelatedEnabled);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-md-6">';
|
|
|
|
|
$html .= $this->buildSelect($cid . 'AfterRelatedFormat', 'Formato',
|
|
|
|
|
$this->renderer->getFieldValue($cid, 'behavior', 'after_related_format', 'autorelaxed'),
|
|
|
|
|
['autorelaxed' => 'Autorelaxed (feed)', 'auto' => 'Auto']
|
|
|
|
|
);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
return $html;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Seccion especial para in-content ads con configuracion de 1-8 random
|
|
|
|
|
*/
|
|
|
|
|
private function buildInContentAdsGroup(string $cid): string
|
|
|
|
|
{
|
|
|
|
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #0d6efd;">';
|
|
|
|
|
$html .= ' <div class="card-body">';
|
|
|
|
|
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
|
|
|
|
$html .= ' <i class="bi bi-body-text me-2" style="color: #0d6efd;"></i>';
|
|
|
|
|
$html .= ' Anuncios Dentro del Contenido';
|
|
|
|
|
$html .= ' <span class="badge bg-primary ms-2">1-8 ads</span>';
|
|
|
|
|
$html .= ' </h5>';
|
|
|
|
|
|
|
|
|
|
$html .= '<div class="alert alert-info small mb-3">';
|
|
|
|
|
$html .= ' <i class="bi bi-lightbulb me-1"></i>';
|
|
|
|
|
$html .= ' <strong>Modo Random:</strong> Inserta entre 1 y 8 anuncios en posiciones aleatorias entre parrafos.';
|
|
|
|
|
$html .= ' Mejor UX al variar la posicion en cada visita.';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// Master switch
|
|
|
|
|
$postContentEnabled = $this->renderer->getFieldValue($cid, 'behavior', 'post_content_enabled', false);
|
|
|
|
|
$html .= '<div class="mb-3">';
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'PostContentEnabled', 'Activar In-Content Ads', $postContentEnabled, 'bi-power');
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// Configuracion de cantidad
|
|
|
|
|
$html .= '<div class="row g-2 mb-3">';
|
|
|
|
|
$html .= ' <div class="col-md-6">';
|
|
|
|
|
$minAdsValue = $this->renderer->getFieldValue($cid, 'behavior', 'post_content_min_ads', '1');
|
|
|
|
|
$html .= $this->buildSelect($cid . 'PostContentMinAds', 'Minimo de anuncios',
|
|
|
|
|
is_string($minAdsValue) ? $minAdsValue : '1',
|
|
|
|
|
['1' => '1 anuncio', '2' => '2 anuncios', '3' => '3 anuncios', '4' => '4 anuncios']
|
|
|
|
|
);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-md-6">';
|
|
|
|
|
$maxAdsValue = $this->renderer->getFieldValue($cid, 'behavior', 'post_content_max_ads', '3');
|
|
|
|
|
$html .= $this->buildSelect($cid . 'PostContentMaxAds', 'Maximo de anuncios',
|
|
|
|
|
is_string($maxAdsValue) ? $maxAdsValue : '3',
|
|
|
|
|
[
|
|
|
|
|
'1' => '1 anuncio', '2' => '2 anuncios', '3' => '3 anuncios', '4' => '4 anuncios',
|
|
|
|
|
'5' => '5 anuncios', '6' => '6 anuncios', '7' => '7 anuncios', '8' => '8 anuncios'
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// Configuracion de posicionamiento
|
|
|
|
|
$html .= '<div class="row g-2 mb-3">';
|
|
|
|
|
$html .= ' <div class="col-md-6">';
|
|
|
|
|
$afterPara = $this->renderer->getFieldValue($cid, 'behavior', 'post_content_after_paragraphs', '3');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'PostContentAfterParagraphs', 'Primer ad despues del parrafo #', (string)$afterPara, '3');
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-md-6">';
|
|
|
|
|
$minBetweenValue = $this->renderer->getFieldValue($cid, 'behavior', 'post_content_min_paragraphs_between', '4');
|
|
|
|
|
$html .= $this->buildSelect($cid . 'PostContentMinParagraphsBetween', 'Parrafos entre ads',
|
|
|
|
|
is_string($minBetweenValue) ? $minBetweenValue : '4',
|
|
|
|
|
['2' => '2 parrafos', '3' => '3 parrafos', '4' => '4 parrafos', '5' => '5 parrafos', '6' => '6 parrafos']
|
|
|
|
|
);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// Modo y formato
|
|
|
|
|
$html .= '<div class="row g-2">';
|
|
|
|
|
$html .= ' <div class="col-md-6">';
|
|
|
|
|
$randomMode = $this->renderer->getFieldValue($cid, 'behavior', 'post_content_random_mode', true);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'PostContentRandomMode', 'Posiciones aleatorias', $randomMode, 'bi-shuffle');
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-md-6">';
|
|
|
|
|
$formatValue = $this->renderer->getFieldValue($cid, 'behavior', 'post_content_format', 'in-article');
|
|
|
|
|
$html .= $this->buildSelect($cid . 'PostContentFormat', 'Formato de ads',
|
|
|
|
|
is_string($formatValue) ? $formatValue : 'in-article',
|
|
|
|
|
['in-article' => 'In-Article (fluid)', 'auto' => 'Auto (responsive)']
|
|
|
|
|
);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
@@ -129,28 +367,38 @@ final class AdsensePlacementFormBuilder
|
|
|
|
|
$pubId = $this->renderer->getFieldValue($cid, 'content', 'publisher_id', 'ca-pub-8476420265998726');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'PublisherId', 'Publisher ID', $pubId, 'ca-pub-XXXXX');
|
|
|
|
|
|
|
|
|
|
// Slots (grid 2 columnas)
|
|
|
|
|
$html .= '<div class="row g-2 mt-2">';
|
|
|
|
|
$html .= ' <div class="col-6">';
|
|
|
|
|
$slotDisplay = $this->renderer->getFieldValue($cid, 'content', 'slot_display', '2873062302');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'SlotDisplay', 'Slot Display', $slotDisplay);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-6">';
|
|
|
|
|
$html .= '<hr class="my-3">';
|
|
|
|
|
$html .= '<p class="small text-muted mb-2"><i class="bi bi-info-circle me-1"></i> Slots por tipo de anuncio:</p>';
|
|
|
|
|
|
|
|
|
|
// Slots con descripciones claras
|
|
|
|
|
$html .= '<div class="mb-2">';
|
|
|
|
|
$slotAuto = $this->renderer->getFieldValue($cid, 'content', 'slot_auto', '8471732096');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'SlotAuto', 'Slot Auto', $slotAuto);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-6">';
|
|
|
|
|
$slotRelaxed = $this->renderer->getFieldValue($cid, 'content', 'slot_autorelaxed', '9205569855');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'SlotAutorelaxed', 'Slot Autorelaxed', $slotRelaxed);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-6">';
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'SlotAuto', '📱 Auto (responsive)', $slotAuto);
|
|
|
|
|
$html .= '<div class="form-text small" style="margin-top:-10px;">Para: Post-Top, Post-Bottom, globales</div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= '<div class="mb-2">';
|
|
|
|
|
$slotInArticle = $this->renderer->getFieldValue($cid, 'content', 'slot_inarticle', '7285187368');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'SlotInarticle', 'Slot In-Article', $slotInArticle);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-6">';
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'SlotInarticle', '📝 In-Article (fluid)', $slotInArticle);
|
|
|
|
|
$html .= '<div class="form-text small" style="margin-top:-10px;">Para: In-Content (dentro del texto)</div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= '<div class="mb-2">';
|
|
|
|
|
$slotDisplay = $this->renderer->getFieldValue($cid, 'content', 'slot_display', '2873062302');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'SlotDisplay', '🖥️ Display (fijo)', $slotDisplay);
|
|
|
|
|
$html .= '<div class="form-text small" style="margin-top:-10px;">Para: 728x90, 970x250 (opcional)</div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= '<div class="mb-2">';
|
|
|
|
|
$slotRelaxed = $this->renderer->getFieldValue($cid, 'content', 'slot_autorelaxed', '9205569855');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'SlotAutorelaxed', '📋 Autorelaxed (feed)', $slotRelaxed);
|
|
|
|
|
$html .= '<div class="form-text small" style="margin-top:-10px;">Para: After-Related, archives</div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= '<div class="mb-2">';
|
|
|
|
|
$slotSkyscraper = $this->renderer->getFieldValue($cid, 'content', 'slot_skyscraper', '');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'SlotSkyscraper', 'Slot Skyscraper (Rail Ads)', $slotSkyscraper);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'SlotSkyscraper', '🏢 Skyscraper (tall)', $slotSkyscraper);
|
|
|
|
|
$html .= '<div class="form-text small" style="margin-top:-10px;">Para: Rail Ads laterales (160x600)</div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
@@ -159,59 +407,27 @@ final class AdsensePlacementFormBuilder
|
|
|
|
|
return $html;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function buildPostLocationsGroup(string $cid): string
|
|
|
|
|
private function buildAnalyticsGroup(string $cid): string
|
|
|
|
|
{
|
|
|
|
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">';
|
|
|
|
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #4285f4;">';
|
|
|
|
|
$html .= ' <div class="card-body">';
|
|
|
|
|
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
|
|
|
|
$html .= ' <i class="bi bi-file-text me-2" style="color: #FF8600;"></i>';
|
|
|
|
|
$html .= ' Ubicaciones en Posts';
|
|
|
|
|
$html .= ' <i class="bi bi-graph-up me-2" style="color: #4285f4;"></i>';
|
|
|
|
|
$html .= ' Google Analytics';
|
|
|
|
|
$html .= ' </h5>';
|
|
|
|
|
|
|
|
|
|
// Post Top
|
|
|
|
|
$postTopEnabled = $this->renderer->getFieldValue($cid, 'behavior', 'post_top_enabled', true);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'PostTopEnabled', 'Despues de Featured Image', $postTopEnabled);
|
|
|
|
|
$html .= $this->buildSelect($cid . 'PostTopFormat', 'Formato',
|
|
|
|
|
$this->renderer->getFieldValue($cid, 'behavior', 'post_top_format', 'auto'),
|
|
|
|
|
['auto' => 'Auto (responsive)', 'in-article' => 'In-Article', 'display' => 'Display (728x90)', 'display-large' => 'Display Large (970x250)']
|
|
|
|
|
);
|
|
|
|
|
// Switch: Analytics Enabled
|
|
|
|
|
$analyticsEnabled = $this->renderer->getFieldValue($cid, 'analytics', 'analytics_enabled', false);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'AnalyticsEnabled', 'Activar Analytics', $analyticsEnabled, 'bi-power');
|
|
|
|
|
|
|
|
|
|
// Post Content
|
|
|
|
|
$postContentEnabled = $this->renderer->getFieldValue($cid, 'behavior', 'post_content_enabled', false);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'PostContentEnabled', 'Insertar dentro del contenido', $postContentEnabled);
|
|
|
|
|
// Tracking ID
|
|
|
|
|
$gaTrackingId = $this->renderer->getFieldValue($cid, 'analytics', 'ga_tracking_id', '');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'GaTrackingId', 'Google Analytics ID', $gaTrackingId, 'G-XXXXXXXXXX');
|
|
|
|
|
$html .= '<div class="form-text small mb-2">Formato: G-XXXXXXXXXX (GA4) o UA-XXXXXXXX-X</div>';
|
|
|
|
|
|
|
|
|
|
$html .= '<div class="row g-2">';
|
|
|
|
|
$html .= ' <div class="col-4">';
|
|
|
|
|
$afterPara = $this->renderer->getFieldValue($cid, 'behavior', 'post_content_after_paragraphs', '3');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'PostContentAfterParagraphs', 'Despues parrafo #', $afterPara);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-4">';
|
|
|
|
|
$maxAds = $this->renderer->getFieldValue($cid, 'behavior', 'post_content_max_ads', '2');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'PostContentMaxAds', 'Max ads', $maxAds);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' <div class="col-4">';
|
|
|
|
|
$html .= $this->buildSelect($cid . 'PostContentFormat', 'Formato',
|
|
|
|
|
$this->renderer->getFieldValue($cid, 'behavior', 'post_content_format', 'in-article'),
|
|
|
|
|
['in-article' => 'In-Article', 'auto' => 'Auto']
|
|
|
|
|
);
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
// Post Bottom
|
|
|
|
|
$postBottomEnabled = $this->renderer->getFieldValue($cid, 'behavior', 'post_bottom_enabled', true);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'PostBottomEnabled', 'Despues del contenido', $postBottomEnabled);
|
|
|
|
|
$html .= $this->buildSelect($cid . 'PostBottomFormat', 'Formato',
|
|
|
|
|
$this->renderer->getFieldValue($cid, 'behavior', 'post_bottom_format', 'auto'),
|
|
|
|
|
['auto' => 'Auto', 'in-article' => 'In-Article', 'display' => 'Display']
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// After Related
|
|
|
|
|
$afterRelatedEnabled = $this->renderer->getFieldValue($cid, 'behavior', 'after_related_enabled', false);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'AfterRelatedEnabled', 'Despues de Related Posts', $afterRelatedEnabled);
|
|
|
|
|
$html .= $this->buildSelect($cid . 'AfterRelatedFormat', 'Formato',
|
|
|
|
|
$this->renderer->getFieldValue($cid, 'behavior', 'after_related_format', 'autorelaxed'),
|
|
|
|
|
['autorelaxed' => 'Autorelaxed', 'auto' => 'Auto']
|
|
|
|
|
);
|
|
|
|
|
// Anonymize IP
|
|
|
|
|
$gaAnonymizeIp = $this->renderer->getFieldValue($cid, 'analytics', 'ga_anonymize_ip', true);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'GaAnonymizeIp', 'Anonimizar IP (GDPR)', $gaAnonymizeIp, 'bi-shield-check');
|
|
|
|
|
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
@@ -221,13 +437,14 @@ final class AdsensePlacementFormBuilder
|
|
|
|
|
|
|
|
|
|
private function buildRailAdsGroup(string $cid): string
|
|
|
|
|
{
|
|
|
|
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">';
|
|
|
|
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #dc3545;">';
|
|
|
|
|
$html .= ' <div class="card-body">';
|
|
|
|
|
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
|
|
|
|
$html .= ' <i class="bi bi-layout-sidebar me-2" style="color: #FF8600;"></i>';
|
|
|
|
|
$html .= ' Rail Ads (Margenes Laterales)';
|
|
|
|
|
$html .= ' <i class="bi bi-layout-sidebar me-2" style="color: #dc3545;"></i>';
|
|
|
|
|
$html .= ' Rail Ads (Laterales)';
|
|
|
|
|
$html .= ' <span class="badge bg-secondary ms-2">>1600px</span>';
|
|
|
|
|
$html .= ' </h5>';
|
|
|
|
|
$html .= ' <p class="small text-muted mb-3">Anuncios fijos en los espacios laterales del viewport. Solo visibles en pantallas >= 1600px.</p>';
|
|
|
|
|
$html .= ' <p class="small text-muted mb-3">Anuncios fijos en los margenes del viewport. Solo en pantallas muy anchas.</p>';
|
|
|
|
|
|
|
|
|
|
// Master switch
|
|
|
|
|
$railEnabled = $this->renderer->getFieldValue($cid, 'behavior', 'rail_ads_enabled', false);
|
|
|
|
|
@@ -262,66 +479,28 @@ final class AdsensePlacementFormBuilder
|
|
|
|
|
return $html;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function buildArchiveLocationsGroup(string $cid): string
|
|
|
|
|
{
|
|
|
|
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">';
|
|
|
|
|
$html .= ' <div class="card-body">';
|
|
|
|
|
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
|
|
|
|
$html .= ' <i class="bi bi-grid me-2" style="color: #FF8600;"></i>';
|
|
|
|
|
$html .= ' Ubicaciones Archives/Globales';
|
|
|
|
|
$html .= ' </h5>';
|
|
|
|
|
|
|
|
|
|
// Archive locations
|
|
|
|
|
$archiveTopEnabled = $this->renderer->getFieldValue($cid, 'layout', 'archive_top_enabled', false);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'ArchiveTopEnabled', 'Arriba del listado', $archiveTopEnabled);
|
|
|
|
|
|
|
|
|
|
$archiveBetweenEnabled = $this->renderer->getFieldValue($cid, 'layout', 'archive_between_enabled', false);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'ArchiveBetweenEnabled', 'Entre posts del listado', $archiveBetweenEnabled);
|
|
|
|
|
|
|
|
|
|
$archiveEvery = $this->renderer->getFieldValue($cid, 'layout', 'archive_between_every', '4');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'ArchiveBetweenEvery', 'Mostrar cada X posts', $archiveEvery);
|
|
|
|
|
|
|
|
|
|
$archiveBottomEnabled = $this->renderer->getFieldValue($cid, 'layout', 'archive_bottom_enabled', false);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'ArchiveBottomEnabled', 'Abajo del listado', $archiveBottomEnabled);
|
|
|
|
|
|
|
|
|
|
// Archive format (aplica a todas las ubicaciones archive)
|
|
|
|
|
$html .= $this->buildSelect($cid . 'ArchiveFormat', 'Formato para archives',
|
|
|
|
|
$this->renderer->getFieldValue($cid, 'layout', 'archive_format', 'autorelaxed'),
|
|
|
|
|
['autorelaxed' => 'Autorelaxed', 'auto' => 'Auto']
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$html .= '<hr class="my-3">';
|
|
|
|
|
$html .= '<p class="small text-muted mb-2"><strong>Ubicaciones Globales</strong></p>';
|
|
|
|
|
|
|
|
|
|
// Global locations
|
|
|
|
|
$headerBelowEnabled = $this->renderer->getFieldValue($cid, 'layout', 'header_below_enabled', false);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'HeaderBelowEnabled', 'Debajo del header (global)', $headerBelowEnabled);
|
|
|
|
|
|
|
|
|
|
$footerAboveEnabled = $this->renderer->getFieldValue($cid, 'layout', 'footer_above_enabled', false);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'FooterAboveEnabled', 'Arriba del footer (global)', $footerAboveEnabled);
|
|
|
|
|
|
|
|
|
|
// Global format
|
|
|
|
|
$html .= $this->buildSelect($cid . 'GlobalFormat', 'Formato para globales',
|
|
|
|
|
$this->renderer->getFieldValue($cid, 'layout', 'global_format', 'auto'),
|
|
|
|
|
['auto' => 'Auto', 'display-large' => 'Display Large (970x250)']
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
return $html;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function buildExclusionsGroup(string $cid): string
|
|
|
|
|
{
|
|
|
|
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">';
|
|
|
|
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #6c757d;">';
|
|
|
|
|
$html .= ' <div class="card-body">';
|
|
|
|
|
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
|
|
|
|
$html .= ' <i class="bi bi-slash-circle me-2" style="color: #FF8600;"></i>';
|
|
|
|
|
$html .= ' <i class="bi bi-slash-circle me-2" style="color: #6c757d;"></i>';
|
|
|
|
|
$html .= ' Exclusiones y Rendimiento';
|
|
|
|
|
$html .= ' </h5>';
|
|
|
|
|
|
|
|
|
|
// Exclusions
|
|
|
|
|
// Accordion para exclusiones
|
|
|
|
|
$html .= '<div class="accordion accordion-flush" id="exclusionsAccordion">';
|
|
|
|
|
|
|
|
|
|
// Exclusiones
|
|
|
|
|
$html .= '<div class="accordion-item">';
|
|
|
|
|
$html .= ' <h2 class="accordion-header">';
|
|
|
|
|
$html .= ' <button class="accordion-button collapsed py-2" type="button" data-bs-toggle="collapse" data-bs-target="#exclusionsCollapse">';
|
|
|
|
|
$html .= ' <i class="bi bi-funnel me-2"></i> Filtros de exclusion';
|
|
|
|
|
$html .= ' </button>';
|
|
|
|
|
$html .= ' </h2>';
|
|
|
|
|
$html .= ' <div id="exclusionsCollapse" class="accordion-collapse collapse" data-bs-parent="#exclusionsAccordion">';
|
|
|
|
|
$html .= ' <div class="accordion-body">';
|
|
|
|
|
|
|
|
|
|
$excludeCats = $this->renderer->getFieldValue($cid, 'forms', 'exclude_categories', '');
|
|
|
|
|
$html .= $this->buildTextarea($cid . 'ExcludeCategories', 'Excluir categorias (IDs)', $excludeCats, 'Ej: 5,12,23');
|
|
|
|
|
|
|
|
|
|
@@ -334,9 +513,18 @@ final class AdsensePlacementFormBuilder
|
|
|
|
|
$minLength = $this->renderer->getFieldValue($cid, 'forms', 'min_content_length', '500');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'MinContentLength', 'Longitud minima de contenido', $minLength);
|
|
|
|
|
|
|
|
|
|
// Delay settings
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= ' </div>';
|
|
|
|
|
$html .= '</div>';
|
|
|
|
|
|
|
|
|
|
$html .= '</div>'; // end accordion
|
|
|
|
|
|
|
|
|
|
// Delay settings (siempre visibles)
|
|
|
|
|
$html .= '<hr class="my-3">';
|
|
|
|
|
$html .= '<p class="small text-muted mb-2"><i class="bi bi-speedometer2 me-1"></i> Rendimiento:</p>';
|
|
|
|
|
|
|
|
|
|
$delayEnabled = $this->renderer->getFieldValue($cid, 'forms', 'delay_enabled', true);
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'DelayEnabled', 'Retrasar carga de anuncios', $delayEnabled, 'bi-hourglass-split');
|
|
|
|
|
$html .= $this->buildSwitch($cid . 'DelayEnabled', 'Retrasar carga (mejor PageSpeed)', $delayEnabled, 'bi-hourglass-split');
|
|
|
|
|
|
|
|
|
|
$delayTimeout = $this->renderer->getFieldValue($cid, 'forms', 'delay_timeout', '5000');
|
|
|
|
|
$html .= $this->buildTextInput($cid . 'DelayTimeout', 'Timeout de delay (ms)', $delayTimeout);
|
|
|
|
|
|