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;
}
}