HEX
Server: Apache
System: Linux srv13.cpanelhost.cl 3.10.0-962.3.2.lve1.5.38.el7.x86_64 #1 SMP Thu Jun 18 05:28:41 EDT 2020 x86_64
User: cca63905 (4205)
PHP: 7.3.20
Disabled: NONE
Upload Files
File: //proc/self/root/proc/self/cwd/nueva/modules/chatgptcontentgenerator/src/Process/GeneratePost.php
<?php
/**
 * 2007-2024 PrestaShop
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to http://www.prestashop.com for more information.
 *
 *  @author    PrestaShop SA <contact@prestashop.com>
 *  @copyright 2007-2024 PrestaShop SA
 *  @license   http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 *  International Registered Trademark & Property of PrestaShop SA
 */
namespace PrestaShop\Module\Chatgptcontentgenerator\Process;

if (!defined('_PS_VERSION_')) {
    exit;
}

use PrestaShop\Module\Chatgptcontentgenerator\Entity\GptContentGenerator;
use PrestaShop\Module\Chatgptcontentgenerator\Entity\GptContentPost;

class GeneratePost extends AbstractProcess
{
    /**
     * Generate Post by Product.
     *
     * @param int $idProduct product id
     * @param array $productData Product datas (name, category, brand)
     * @param int $idLang Specify the id of the language used
     * @param int $maxLength Maximum number of words for content
     * @param array $images Images (id, save_path)
     */
    public function generatePostByProduct(
        $idProduct,
        $productData,
        $idLang,
        $maxLength = 400,
        $images = [],
        $isActivePost = true,
        $numberProductLinks = 0
    ) {
        $name = '';
        $isoCode = \Language::getIsoById((int) $idLang);

        if (!$isoCode) {
            $message = $this->trans(
                'Language does not exist [%language%]',
                [
                    '%language%' => $isoCode,
                ],
                'Modules.Chatgptcontentgenerator.Admin'
            );

            throw new \Exception($message);
        }

        if (!empty($productData['name'])) {
            $name = trim($productData['name']);
        }

        if ('' === $name) {
            $name = (new \Product((int) $idProduct, false, (int) $idLang))->name;
        }

        if ('' === trim($name)) {
            $message = $this->trans(
                'Product name is empty [id_product = %id_product%, language = %language%]',
                [
                    '%id_product%' => $idProduct,
                    '%language%' => $isoCode,
                ],
                'Modules.Chatgptcontentgenerator.Admin'
            );

            throw new \Exception($message);
        }

        $post = $this->apiClient->generatePostForProduct([
            'name' => $name,
            'maxLength' => $maxLength > 0 ? $maxLength : 400,
            'langIsoCode' => $isoCode,
            'category' => (isset($product['category']) ? trim($product['category']) : ''),
            'brand' => (isset($product['brand']) ? trim($product['brand']) : ''),
        ]);

        $post_content = $this->insertImagesIntoText($images, $post['text']);
        $post_content = $this->insertProductLinks($post_content, $idProduct, $idLang, $numberProductLinks);

        $post_title = self::getTitleFromContent($post['text'], $name);

        // prepare post data
        $content = [];
        $title = [];

        foreach (\Language::getLanguages(false) as $lang) {
            $content[$lang['id_lang']] = $post_content;
            $title[$lang['id_lang']] = $post_title;
        }

        $product_post = $this->createPost((int) $idProduct, $title, $content, $isActivePost);

        return [
            'text' => $post['text'],
            'nbWords' => (!isset($post['nbWords'])
                ? str_word_count($post['text'])
                : $post['nbWords']),
            'inQueue' => $post['inQueue'],
            'requestId' => $post['requestId'],
            'post' => (new GptContentPost($product_post->id, $idLang)),
        ];
    }

    public function generatePostByPrompt(
        $idProduct,
        $idLang,
        $promptContent,
        $promptTitle = '',
        $maxLength = 400,
        $images = [],
        $isActivePost = true,
        $numberProductLinks = 0
    ) {
        $isoCode = \Language::getIsoById((int) $idLang);

        if (!$isoCode) {
            $message = $this->trans(
                'Language does not exist [%language%]',
                [
                    '%language%' => $isoCode,
                ],
                'Modules.Chatgptcontentgenerator.Admin'
            );

            throw new \Exception($message);
        }

        if ('' === trim($promptContent)) {
            $message = $this->trans(
                'Request to GPT (content) is empty [id_product = %id_product%, language = %language%]',
                [
                    '%id_product%' => $idProduct,
                    '%language%' => $isoCode,
                ],
                'Modules.Chatgptcontentgenerator.Admin'
            );

            throw new \Exception($message);
        }

        // $requestContent = $this->apiClient->descriptionByPrompt($promptContent, 'blog');
        $requestContent = $this->apiClient->postContent($promptContent, $maxLength, $isoCode);
        $post_content = $requestContent['text'];

        if ($promptTitle) {
            $requestTitle = $this->apiClient->descriptionByPrompt($promptTitle, 'blog');
            $post_title = trim($requestTitle['text'], '"');
        } else {
            $post_title = self::getTitleFromContent(
                $post_content,
                (new \Product((int) $idProduct, false, (int) $idLang))->name
            );
        }

        $post_content = $this->insertImagesIntoText($images, $post_content);
        $post_content = $this->insertProductLinks($post_content, $idProduct, $idLang, $numberProductLinks);

        // prepare post data
        $content = [];
        $title = [];

        foreach (\Language::getLanguages(false) as $lang) {
            $content[$lang['id_lang']] = $post_content;
            $title[$lang['id_lang']] = $post_title;
        }

        $product_post = $this->createPost((int) $idProduct, $title, $content, $isActivePost);

        return [
            'request_content' => [
                'text' => $requestContent['text'],
                'nbWords' => (!isset($requestContent['nbWords'])
                    ? str_word_count($requestContent['text'])
                    : $requestContent['nbWords']),
                'inQueue' => $requestContent['inQueue'],
                'requestId' => $requestContent['requestId'],
            ],
            'request_title' => [
                'text' => isset($requestTitle['text']) ? $requestTitle['text'] : '',
                'nbWords' => (isset($requestTitle['nbWords'])
                    ? $requestTitle['nbWords']
                    : (isset($requestTitle['text'])
                        ? str_word_count($requestTitle['text'])
                        : 0
                    )
                ),
                'inQueue' => isset($requestTitle['inQueue']) ? $requestTitle['inQueue'] : false,
                'requestId' => isset($requestTitle['requestId']) ? $requestTitle['requestId'] : '',
            ],
            'post' => (new GptContentPost($product_post->id, $idLang)),
        ];
    }

    private function insertImagesIntoText($images, $htmlContent)
    {
        if (!is_array($images) || empty($images)) {
            return $htmlContent;
        }

        // split HTML by paragraphs
        $paragraphs = null;
        preg_match_all('/<p>((.|\r\n|\r|\n)*?)<\/p>/', $htmlContent, $paragraphs);

        if (!is_array($paragraphs) || !isset($paragraphs[0]) || empty($paragraphs[0])) {
            return $htmlContent;
        }

        $paragraphs = $paragraphs[0];

        $dir = _PS_IMG_DIR_ . 'chatgptcontentgenerator/post-media/';

        if (!file_exists(rtrim($dir))) {
            mkdir($dir, 0777, true);
        }

        foreach ($images as $k => $img) {
            if (!file_exists($img['save_path'])) {
                unset($images[$k]);
                continue;
            }
            $path_parts = pathinfo($img['save_path']);
            $fileName = date('Y-m-d_h-i-s') . '-' . $path_parts['filename'] . '.' . $path_parts['extension'];
            copy($img['save_path'], $dir . $fileName);
            $images[$k]['url'] = $this->context->link->getMediaLink('/img/chatgptcontentgenerator/post-media/' . $fileName);
        }

        $images = array_values($images);

        $nbParagraphs = count($paragraphs);
        $avgImages = ceil(count($images) / $nbParagraphs);

        for ($i = 0; $i < $nbParagraphs; $i = $i + 1) {
            $pImages = [];

            if ($images) {
                for ($j = 0; $j < $avgImages; $j = $j + 1) {
                    if (!isset($images[$j])) {
                        break;
                    }
                    $pImages[] = $images[$j];
                    unset($images[$j]);
                    $images = array_values($images);
                }
            }
            if ($pImages) {
                $htmlContent = str_replace(
                    $paragraphs[$i],
                    $paragraphs[$i] . '<p>' .
                            implode(
                                ' ',
                                array_map(
                                    function ($img) {
                                        return '<img src="' . $img['url'] . '" class="blog-content-images" alt="" style="display: inline-block;"/>';
                                    },
                                    $pImages
                                )
                            ) .
                        '</p>',
                    $htmlContent
                );
            }
        }

        return $htmlContent;
    }

    protected function insertProductLinks($postContent, $idProduct, $idLang, $numberProductLinks = 1)
    {
        if ($numberProductLinks < 1) {
            return $postContent;
        }

        $product = new \Product((int) $idProduct, false, (int) $idLang);

        if (!\Validate::isLoadedObject($product)) {
            return $postContent;
        }

        $pattern = '/' . trim($product->name) . '/i';
        $replace = '<a href="' . $this->context->link->getProductLink($product, null, null, null, $idLang) . '">'
            . trim($product->name) . '</a>';

        $m = null;
        $htmlH1 = '';
        preg_match('/<h1>((.|\r\n|\r|\n)*?)<\/h1>/', $postContent, $m);
        if (!empty($m[0])) {
            $postContent = str_replace($m[0], '', $postContent);
            $htmlH1 = $m[0];
        }

        return $htmlH1 . preg_replace($pattern, $replace, $postContent, $numberProductLinks);
    }

    public static function getTitleFromContent($htmlContent, $defautlTitle = '')
    {
        $m = null;
        preg_match_all('/<h1>((.|\r\n|\r|\n)*?)<\/h1>/', $htmlContent, $m);

        if ($m && isset($m[1]) && !empty($m[1]) && trim($m[1][0]) !== '') {
            return trim(str_replace("\n", '', $m[1][0]));
        }

        return $defautlTitle;
    }

    private function createPost($idProduct, array $title, array $content, $isActivePost = true)
    {
        $post = new GptContentPost();
        $post->id_product = (int) $idProduct;
        $post->title = $title;
        $post->content = $content;
        $post->link_rewrite = array_map(
            function ($t) {
                return \Tools::link_rewrite($t);
            },
            $post->title
        );
        $post->short_content = [];
        $post->active = (bool) $isActivePost;

        foreach ($content as $id_lang => $html_content) {
            $post->short_content[$id_lang] = self::getShortDescriptionFromContent($html_content, '');
        }

        $post->add();

        $isUpdate = false;
        foreach ($post->link_rewrite as $idLang => &$link_rewrite) {
            if (GptContentPost::isExistsByRewrite($link_rewrite, $idLang, $post->id)) {
                $link_rewrite = (int) $post->id . '-' . $link_rewrite;
                $isUpdate = true;
            }
        }
        if (true === $isUpdate) {
            $post->save();
        }

        return $post;
    }

    public static function getShortDescriptionFromContent($htmlContent, $defautlContent = '')
    {
        $m = null;
        preg_match_all('/<p>((.|\r\n|\r|\n)*?)<\/p>/', $htmlContent, $m);
        if ($m && isset($m[0]) && !empty($m[0])) {
            return trim($m[0][0]);
        }

        $m = null;
        preg_match_all('/<\/b>((.|\r\n|\r|\n)*?)<b>/', $htmlContent, $m);
        if ($m && isset($m[1]) && !empty($m[1])) {
            return trim(preg_replace('/(<br>|<br \/>|\n)*?/', '', $m[1][0]));
        }

        return $defautlContent;
    }

    public function addGptContentGeneratorByPost($post, $idLang, $isCron = false)
    {
        $object = new GptContentGenerator();
        $object->setIdObject((int) $post->id)
            ->setObjectType(GptContentGenerator::TYPE_POST)
            ->setIdLang((int) $idLang)
            ->setIsGenerated(true)
            ->setIsCron((bool) $isCron)
        ;

        $object->add();

        return $object;
    }
}