403Webshell
Server IP : 5.129.245.98  /  Your IP : 216.73.216.246
Web Server : Apache/2.4.66 (Debian)
System : Linux 1b8c17c336b9 6.8.0-111-generic #111-Ubuntu SMP PREEMPT_DYNAMIC Sat Apr 11 23:16:02 UTC 2026 x86_64
User : www-data ( 33)
PHP Version : 8.3.30
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : OFF  |  Perl : ON  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /var/www/html/wp-content/plugins/content-egg/application/models/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/html/wp-content/plugins/content-egg/application/models/ProductMapModel.php
<?php

namespace ContentEgg\application\models;



defined('\ABSPATH') || exit;

/**
 * ProductMapModel class file
 *
 * @author keywordrush.com <support@keywordrush.com>
 * @link https://www.keywordrush.com
 * @copyright Copyright &copy; 2025 keywordrush.com
 *
 * ProductMapModel — maps a CE item (module_id + unique_id) in a given source post
 * to an on-site target post (PDP or Woo product).
 *
 * - Per-post overrides: row has source_post_id = {post_id}
 * - Canonical mapping for the item: row has source_post_id = 0
 *
 * Click resolution order:
 *  1) (module_id, unique_id, source_post_id = current post)
 *  2) (module_id, unique_id, source_post_id = 0) → Special row that acts as the default target for that item across the whole site.
 *
 */
class ProductMapModel extends Model
{
    public const CANONICAL_SOURCE = 0;

    public function tableName(): string
    {
        return $this->getDb()->prefix . 'cegg_product_map';
    }

    public function getDump(): string
    {
        return sprintf(
            "CREATE TABLE %s (
                id               BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
                module_id        VARCHAR(64)     NOT NULL,
                unique_id        VARCHAR(191)    NOT NULL,
                source_post_id   BIGINT UNSIGNED NOT NULL DEFAULT 0,
                target_post_id   BIGINT UNSIGNED NOT NULL,
                created_at       DATETIME        NOT NULL DEFAULT CURRENT_TIMESTAMP,
                updated_at       DATETIME        NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                PRIMARY KEY (id),
                UNIQUE KEY uniq_item_ctx (module_id, unique_id, source_post_id),
                KEY idx_item     (module_id, unique_id),
                KEY idx_source   (source_post_id),
                KEY idx_target   (target_post_id)
            ) %s;",
            $this->tableName(),
            $this->charset_collate
        );
    }

    public static function model($className = __CLASS__)
    {
        return parent::model($className);
    }

    public function attributeLabels(): array
    {
        return [
            'id'             => 'ID',
            'module_id'      => __('Module', 'content-egg'),
            'unique_id'      => __('Item ID', 'content-egg'),
            'source_post_id' => __('Source Post', 'content-egg'),
            'target_post_id' => __('Target Post', 'content-egg'),
            'created_at'     => __('Created', 'content-egg'),
            'updated_at'     => __('Updated', 'content-egg'),
        ];
    }

    /* ------------------------------------------------------------------
       CRUD / helpers
    ------------------------------------------------------------------ */

    /**
     * Upsert a mapping for (module_id, unique_id, source_post_id) → target_post_id.
     * Preserves created_at on duplicates.
     *
     * @return int Row ID
     */
    public function upsertMapping(string $module_id, string $unique_id, int $source_post_id, int $target_post_id): int
    {
        $db  = $this->getDb();
        $now = current_time('mysql');

        $sql = $db->prepare(
            "INSERT INTO {$this->tableName()}
                (module_id, unique_id, source_post_id, target_post_id, created_at, updated_at)
             VALUES (%s, %s, %d, %d, %s, %s)
             ON DUPLICATE KEY UPDATE
                target_post_id = VALUES(target_post_id),
                updated_at     = VALUES(updated_at)",
            $module_id,
            $unique_id,
            $source_post_id,
            $target_post_id,
            $now,
            $now
        );

        $db->query($sql);

        if ((int) $db->insert_id > 0)
        {
            return (int) $db->insert_id;
        }

        // Existing row updated; return its ID.
        $id = (int) $db->get_var(
            $db->prepare(
                "SELECT id FROM {$this->tableName()}
                 WHERE module_id = %s AND unique_id = %s AND source_post_id = %d
                 LIMIT 1",
                $module_id,
                $unique_id,
                $source_post_id
            )
        );

        return $id;
    }

    /**
     * Fetch one mapping row by composite key.
     */
    public function findOne(string $module_id, string $unique_id, int $source_post_id): ?array
    {
        return $this->getDb()->get_row(
            $this->getDb()->prepare(
                "SELECT * FROM {$this->tableName()}
                 WHERE module_id = %s AND unique_id = %s AND source_post_id = %d
                 LIMIT 1",
                $module_id,
                $unique_id,
                $source_post_id
            ),
            ARRAY_A
        ) ?: null;
    }

    /**
     * Resolve the target_post_id for a click:
     * tries per-post override, then canonical (source_post_id=0).
     *
     * @return int|null
     */
    public function resolveTargetPostId(string $module_id, string $unique_id, int $source_post_id, bool $tryCanonical = true): ?int
    {
        $db  = $this->getDb();
        $tbl = $this->tableName();

        // 1) Per-post override
        $target = $db->get_var(
            $db->prepare(
                "SELECT target_post_id FROM {$tbl}
                 WHERE module_id = %s AND unique_id = %s AND source_post_id = %d
                 LIMIT 1",
                $module_id,
                $unique_id,
                $source_post_id
            )
        );

        if ($target)
        {
            return (int) $target;
        }

        // 2) Canonical
        if ($tryCanonical)
        {
            $target = $db->get_var(
                $db->prepare(
                    "SELECT target_post_id FROM {$tbl}
                     WHERE module_id = %s AND unique_id = %s AND source_post_id = %d
                     LIMIT 1",
                    $module_id,
                    $unique_id,
                    self::CANONICAL_SOURCE
                )
            );

            if ($target)
            {
                return (int) $target;
            }
        }

        return null;
    }

    /**
     * Convenience: set or update the canonical mapping (source_post_id = 0).
     */
    public function setCanonical(string $module_id, string $unique_id, int $target_post_id): int
    {
        return $this->upsertMapping($module_id, $unique_id, self::CANONICAL_SOURCE, $target_post_id);
    }

    /**
     * Delete a single mapping row (by composite key).
     */
    public function deleteOne(string $module_id, string $unique_id, int $source_post_id): bool
    {
        return (bool) $this->getDb()->delete(
            $this->tableName(),
            array(
                'module_id'      => $module_id,
                'unique_id'      => $unique_id,
                'source_post_id' => $source_post_id,
            ),
            array('%s', '%s', '%d')
        );
    }

    /**
     * Delete ALL mappings for an item (both per-post and canonical).
     *
     * @return int rows affected
     */
    public function deleteAllForItem(string $module_id, string $unique_id): int
    {
        $this->getDb()->query(
            $this->getDb()->prepare(
                "DELETE FROM {$this->tableName()}
                 WHERE module_id = %s AND unique_id = %s",
                $module_id,
                $unique_id
            )
        );
        return (int) $this->getDb()->rows_affected;
    }

    /**
     * Delete mappings that point to a given target post (e.g., when PDP/Woo is trashed).
     *
     * @return int rows affected
     */
    public function deleteByTarget(int $target_post_id): int
    {
        $this->getDb()->query(
            $this->getDb()->prepare(
                "DELETE FROM {$this->tableName()} WHERE target_post_id = %d",
                $target_post_id
            )
        );
        return (int) $this->getDb()->rows_affected;
    }

    /**
     * Reassign mappings from one target post to another (merging PDPs).
     *
     * @return int rows affected
     */
    public function reassignTarget(int $from_target_post_id, int $to_target_post_id): int
    {
        if ($from_target_post_id === $to_target_post_id)
        {
            return 0;
        }

        $this->getDb()->query(
            $this->getDb()->prepare(
                "UPDATE {$this->tableName()}
                 SET target_post_id = %d, updated_at = %s
                 WHERE target_post_id = %d",
                $to_target_post_id,
                current_time('mysql'),
                $from_target_post_id
            )
        );

        return (int) $this->getDb()->rows_affected;
    }

    /**
     * List mappings for a given source post (all CE items used in that post).
     */
    public function listBySourcePost(int $source_post_id): array
    {
        $rows = $this->getDb()->get_results(
            $this->getDb()->prepare(
                "SELECT * FROM {$this->tableName()}
                 WHERE source_post_id = %d
                 ORDER BY module_id, unique_id",
                $source_post_id
            ),
            ARRAY_A
        );
        return $rows ? $rows : array();
    }

    /**
     * List all item mappings that point to a given target post.
     */
    public function listByTargetPost(int $target_post_id): array
    {
        $rows = $this->getDb()->get_results(
            $this->getDb()->prepare(
                "SELECT * FROM {$this->tableName()}
                 WHERE target_post_id = %d",
                $target_post_id
            ),
            ARRAY_A
        );
        return $rows ? $rows : array();
    }

    /**
     * Count mappings per item (how many contexts reference this item).
     */
    public function countContextsForItem(string $module_id, string $unique_id): int
    {
        $sql = $this->getDb()->prepare(
            "SELECT COUNT(*) FROM {$this->tableName()}
             WHERE module_id = %s AND unique_id = %s",
            $module_id,
            $unique_id
        );
        return (int) $this->getDb()->get_var($sql);
    }

    /**
     * Cleanup utility: remove per-post mappings whose source post no longer exists.
     * (leaves canonical rows alone)
     *
     * @return int rows affected
     */
    public function cleanupOrphanSources(): int
    {
        $tbl = $this->tableName();
        $sql = "
            DELETE m FROM {$tbl} m
            LEFT JOIN " . $this->getDb()->posts . " p
              ON (p.ID = m.source_post_id)
            WHERE m.source_post_id > 0
              AND p.ID IS NULL
        ";
        $this->getDb()->query($sql);
        return (int) $this->getDb()->rows_affected;
    }

    /** Delete all per-post mappings for a given source post. */
    public function deleteBySource(int $source_post_id): int
    {
        if ($source_post_id <= 0)
        {
            return 0;
        }

        $this->getDb()->query(
            $this->getDb()->prepare(
                "DELETE FROM {$this->tableName()} WHERE source_post_id = %d",
                $source_post_id
            )
        );
        return (int) $this->getDb()->rows_affected;
    }

    /** Cleanup utility: remove mappings whose TARGET post no longer exists. */
    public function cleanupOrphanTargets(): int
    {
        $tbl = $this->tableName();
        $sql = "
        DELETE m FROM {$tbl} m
        LEFT JOIN " . $this->getDb()->posts . " p
          ON (p.ID = m.target_post_id)
        WHERE p.ID IS NULL
    ";
        $this->getDb()->query($sql);
        return (int) $this->getDb()->rows_affected;
    }

    /**
     * Resolve target_post_id per unique_id for a given module in one shot.
     * Precedence: per-post (source_post_id) > canonical (source_post_id = 0).
     *
     * @param string   $module_id
     * @param string[] $unique_ids         Unique per module (assumed)
     * @param int|null $source_post_id     Context post; if null/<=0 resolves canonical-only
     * @return array                       [ unique_id => target_post_id ]
     */
    public function resolveTargetsForModule(string $module_id, array $unique_ids, ?int $source_post_id): array
    {
        global $wpdb;

        if ($module_id === '' || empty($unique_ids))
        {
            return [];
        }

        // Build SQL
        $placeholders = implode(',', array_fill(0, count($unique_ids), '%s'));
        $params       = [$module_id];

        // Limit to canonical or (canonical + per-post) depending on source_post_id
        if (!empty($source_post_id) && (int) $source_post_id > 0)
        {
            $whereSource = 'source_post_id IN (0, %d)';
            $params[]    = (int) $source_post_id;
        }
        else
        {
            $whereSource = 'source_post_id IN (0)';
        }

        $sql = "
        SELECT unique_id, source_post_id, target_post_id
          FROM {$this->tableName()}
         WHERE module_id = %s
           AND {$whereSource}
           AND unique_id IN ({$placeholders})
    ";

        $params = array_merge($params, $unique_ids);
        $rows   = $wpdb->get_results($wpdb->prepare($sql, $params), ARRAY_A);

        if (!$rows)
        {
            return [];
        }

        // Build best mapping per unique_id: set canonical first, then override with per-post row
        $best = []; // unique_id => target_post_id
        foreach ($rows as $r)
        {
            $u = (string) $r['unique_id'];
            $t = (int) $r['target_post_id'];
            $s = (int) $r['source_post_id'];

            if ($s === 0)
            {
                if (!isset($best[$u]))
                {
                    $best[$u] = $t;
                }
            }
            else
            {
                $best[$u] = $t; // per-post overrides canonical
            }
        }

        return $best;
    }

    /**
     * Batch resolve best targets for a module + set of unique_ids, including origin.
     * Returns: [ unique_id => ['target_post_id' => int, 'is_canonical' => bool] ]
     *
     * Order of precedence:
     *   1) per-post override (source_post_id = $source_post_id > 0) -> is_canonical=false
     *   2) canonical (source_post_id = 0)                          -> is_canonical=true
     *
     * @param string   $module_id
     * @param string[] $unique_ids
     * @param int|null $source_post_id
     * @return array<string,array{target_post_id:int,is_canonical:bool}>
     */
    public function resolveTargetsForModuleWithOrigin(string $module_id, array $unique_ids, ?int $source_post_id): array
    {
        $db = $this->getDb();
        $tbl = $this->tableName();

        // sanitize list
        $unique_ids = array_values(array_filter(array_map('strval', $unique_ids)));

        if (!$unique_ids)
        {
            return [];
        }

        // Fetch per-post overrides (if we have a real source context)
        $overrides = [];
        if ($source_post_id && $source_post_id > 0)
        {
            // chunk IN() if needed (kept simple here)
            $in = implode("','", array_map('esc_sql', $unique_ids));
            $sql = "
            SELECT unique_id, target_post_id
              FROM {$tbl}
             WHERE module_id = %s
               AND source_post_id = %d
               AND unique_id IN ('{$in}')
        ";
            $rows = $db->get_results($db->prepare($sql, $module_id, (int)$source_post_id), ARRAY_A);
            foreach ((array)$rows as $r)
            {
                $u = (string)$r['unique_id'];
                $overrides[$u] = (int)$r['target_post_id'];
            }
        }

        // Fetch canonical mappings for the same set
        $canon = [];
        {
            $in = implode("','", array_map('esc_sql', $unique_ids));
            $sql = "
            SELECT unique_id, target_post_id
              FROM {$tbl}
             WHERE module_id = %s
               AND source_post_id = 0
               AND unique_id IN ('{$in}')
        ";
            $rows = $db->get_results($db->prepare($sql, $module_id), ARRAY_A);
            foreach ((array)$rows as $r)
            {
                $u = (string)$r['unique_id'];
                $canon[$u] = (int)$r['target_post_id'];
            }
        }

        // Build result with origin flag
        $out = [];
        foreach ($unique_ids as $u)
        {
            if (isset($overrides[$u]))
            {
                $out[$u] = ['target_post_id' => $overrides[$u], 'is_canonical' => false];
            }
            elseif (isset($canon[$u]))
            {
                $out[$u] = ['target_post_id' => $canon[$u], 'is_canonical' => true];
            }
        }

        return $out;
    }
}

Youez - 2016 - github.com/yon3zu
LinuXploit