HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: /var/www/html/triad-infosec/wp-content/plugins/autoupdater/lib/Task/WoocommerceUrls.php
<?php
defined('AUTOUPDATER_LIB') or die;

class AutoUpdater_Task_WoocommerceUrls extends AutoUpdater_Task_Base
{
    protected $high_priority = false;
    protected $home_url = '';

    public function doTask()
    {
        if (!is_plugin_active('woocommerce/woocommerce.php')) {
            return array(
                'success' => true,
                'message' => 'WooCommerce plugin is not active, skipping acquiring urls'
            );
        }

        if (
            file_exists(WP_PLUGIN_DIR . '/woocommerce/woocommerce.php')
            && file_exists(WP_PLUGIN_DIR . '/woocommerce/includes/wc-core-functions.php')
            && file_exists(WP_PLUGIN_DIR . '/woocommerce/includes/wc-page-functions.php')
        ) {
            include_once WP_PLUGIN_DIR . '/woocommerce/woocommerce.php';
            include_once WP_PLUGIN_DIR . '/woocommerce/includes/wc-core-functions.php';
            include_once WP_PLUGIN_DIR . '/woocommerce/includes/wc-page-functions.php';
        }

        if (!defined('WC_PLUGIN_FILE')) {
            return array(
                'success' => true,
                'needs_refactor' => true,
                'message' => 'WooCommerce plugin not loaded'
            );
        }

        if (
            !function_exists('wc_get_cart_url')
            || !function_exists('wc_get_checkout_url')
            || !function_exists('wc_get_page_id')
            || !function_exists('wc_get_products')
        ) {
            return array(
                'success' => true,
                'needs_refactor' => true,
                'message' => 'WooCommerce URL functions not found, check for source code updates',
            );
        }

        return array(
            'success' => true,
            'urls' => $this->getUrls()
        );
    }

    /**
     * @return array
     */
    protected function getUrls()
    {
        $this->home_url = get_home_url();

        $urls = $this->getBaseUrls();

        $limit = (int) $this->input('limit', 20);
        if ($limit <= count($urls)) {
            return array_slice($urls, 0, $limit);
        }

        $categories_limit = (int) round(($limit - count($urls)) * 0.2);
        if ($categories_limit > 0) {
            $urls = array_merge($urls, $this->getCategoriesUrls($categories_limit));
        }

        $products_limit = $limit - count($urls);
        $urls = array_merge($urls, $this->getProductsUrls($products_limit));

        return $urls;
    }

    /**
     * @return array
     */
    protected function getBaseUrls()
    {
        $urls = array($this->home_url);

        if (($cart_url = wc_get_cart_url()) && $cart_url !== $this->home_url) {
            $urls[] = $this->escapeUrl($cart_url);
        }

        if (($checkout_url = wc_get_checkout_url()) && $checkout_url !== $this->home_url) {
            $urls[] = $this->escapeUrl($checkout_url);
        }

        $my_account_page_id = wc_get_page_id('myaccount');
        if ($my_account_page_id !== -1) {
            $my_account_url = get_page_link($my_account_page_id);
            // It is not a link to a page without a numeric ID or it is not the home page
            if (!preg_match('/(\?|&)page_id=(&.+)?$/', $my_account_url) && $my_account_url !== $this->home_url) {
                $urls[] = $this->escapeUrl($my_account_url);
            }
        }

        return $urls;
    }

    /**
     * @param int $limit
     * @return array
     */
    protected function getProductsUrls($limit)
    {
        $urls = array();

        $products = wc_get_products(array(
            'status' => 'publish',
            'visibility' => 'visible',
            'limit' => $limit * 10,
            'paginate' => false
        ));

        $products_count = count($products);
        if ($products_count === 0) {
            return $urls;
        }

        // Trying to pick more elements than there are in the array by array_rand, will result in an E_WARNING level error, and NULL will be returned
        if ($products_count < $limit) {
            $keys = array_keys($products);
        } elseif ($limit === 1) {
            // Returns one key
            $keys = array(array_rand($products, 1));
        } else {
            // Returns array of keys
            $keys = array_rand($products, $limit);
        }

        // Add products URLs
        foreach ($keys as $key) {
            /** @var WC_Product $product */
            $product = $products[$key];
            $product_url = $this->validateUrl($product->get_permalink());
            if (is_wp_error($product_url)) {
                AutoUpdater_Log::error(sprintf('Failed to get permalink for product ID %d with the error: %s', $product->get_id(), $product_url->get_error_message()));
                continue;
            }
            $urls[] = $this->escapeUrl($product_url);
        }

        return $urls;
    }

    /**
     * @param int $limit
     * @return array
     */
    protected function getCategoriesUrls($limit)
    {
        $urls = array();

        $categories = get_terms(array(
            'taxonomy' => 'product_cat',
            'fields' => 'ids',
            'number' => $limit * 10,
            'nopaging' => true
        ));

        $categories_count = count($categories);
        if ($categories_count === 0) {
            return $urls;
        }

        // Trying to pick more elements than there are in the array by array_rand, will result in an E_WARNING level error, and NULL will be returned
        if ($categories_count < $limit) {
            $keys = array_keys($categories);
        } elseif ($limit === 1) {
            // Returns one key
            $keys = array(array_rand($categories, 1));
        } else {
            // Returns array of keys
            $keys = array_rand($categories, $limit);
        }

        // Add categories URLs
        foreach ($keys as $key) {
            $category_id = $categories[$key];
            $category_url = $this->validateUrl(get_term_link($category_id, 'product_cat'));
            if (is_wp_error($category_url)) {
                AutoUpdater_Log::error(sprintf('Failed to get permalink for category ID %d with the error: %s', $category_id, $category_url->get_error_message()));
                continue;
            }
            $urls[] = $this->escapeUrl($category_url);
        }

        return $urls;
    }

    /**
     * @param string $url
     * @return string|WP_Error
     */
    protected function validateUrl($url)
    {
        if (is_wp_error($url)) {
            return $url;
        }

        // Relative URL
        if (substr($url, 0, 1) === '/') {
            return $this->home_url . $url;
        }

        // Not absolute URL
        if (substr($url, 0, 4) !== 'http') {
            return new WP_Error('invalid_url', sprintf('Invalid URL: %s', $url));
        }

        esc_url_raw($url);
        return $url;
    }

    /**
     * @param string $url
     * @return string
     */
    protected function escapeUrl($url)
    {
        $path = parse_url($url, PHP_URL_PATH);
        $encoded_path = array_map('urlencode', array_map('urldecode', explode('/', $path)));
        $url = str_replace($path, implode('/', $encoded_path), $url);
        return $url;
    }
}