Plugin Directory

Changeset 3034684


Ignore:
Timestamp:
02/12/2024 03:29:42 PM (2 years ago)
Author:
bikkel
Message:

add trunk

Location:
news-parser/trunk
Files:
17 added
29 edited

Legend:

Unmodified
Added
Removed
  • news-parser/trunk/bootstrap.php

    r3023057 r3034684  
    7878    $app->event->on('html:get',array(Controller\VisualConstructorController::class,'get'));
    7979    $app->event->on('posts:parse',array(Controller\PostController::class,'parsePost'));
     80    $app->event->on('posts:autopilot-parse',array(Controller\PostController::class,'autopilotParsePost'));
    8081    $app->event->on('posts:create',array(Controller\PostController::class,'createPostFromParsedData'));
    81     $app->event->on('posts:batch',array(Controller\PostController::class,'batchParsePost'));
    8282    $app->event->on('posts:in-progress',array(Controller\PostController::class,'getPostsInProgress'));
    8383    $app->event->on('posts:data',array(Controller\PostController::class,'getPostsData'));
  • news-parser/trunk/inc/Api/Rest/PostApiEndpoint.php

    r3023057 r3034684  
    215215                )
    216216                ));
    217             $base = 'posts/create/batch';
    218 
    219             register_rest_route($namespace, '/' . $base, array(
    220                     array(
    221                         'methods' => \WP_REST_Server::CREATABLE,
    222                         'callback' => array($this, 'createBatchPosts'),
    223                         'permission_callback' => array($this, 'checkPermission'),
    224                         'args' => array(
    225                             'posts'=>array(
    226                                 'description'=>'Front end requested page index',
    227                                 'type'=>'integer',
    228                                 'validate_callback'=>function ($posts) {
    229                                     if(is_array($posts)){
    230                                         return true;
    231                                     } else {
    232                                         return false;
    233                                     }
    234                                 },
    235                                 'sanitize_callback'=>function ($posts) {
    236                                     return $posts;
    237                                 }
    238                             ),
    239                             'templateUrl'=>array(
    240                                 'description'=>'Url that identifies template',
    241                                 'type'=>'string',
    242                                 'validate_callback'=>function ($url) {
    243                                     return true;
    244                                 },
    245                                 'sanitize_callback'=>function ($input_url) {
    246                                     return esc_url_raw($input_url);
    247                                 }
    248                             )
    249                         )
    250                     )
    251                 )
    252             );
     217       
    253218            $base = 'posts/in-progress';
    254219
     
    291256                                }
    292257                            ),
    293                             'postUrl'=>array(
     258                            'post_id'=>array(
    294259                                'description'=>'Parsing page url',
    295260                                'type'=>'string',
    296                                 'validate_callback'=>function ($url) {
    297                                     return wp_http_validate_url($url);
     261                                'validate_callback'=>function ($post_id) {
     262                                    return true;
    298263                                },
    299                                 'sanitize_callback'=>function ($input_url) {
    300                                     return esc_url_raw($input_url);
     264                                'sanitize_callback'=>function ($post_id) {
     265                                    return intval($post_id);
    301266                                }
    302267                            )
     
    343308
    344309}
    345 public function createBatchPosts ($request)
    346 {
    347     try{
    348         $post_params=$request->get_params();
    349         $response=$this->event->trigger('posts:batch', array($post_params['posts'],$post_params['templateUrl']));
    350         $response_data=$this->formatResponse()->posts($response)->message('success', Success::text('POSTS_SAVED'))->get('array');
    351         return $this->sendResponse($response_data);
    352     }catch(MyException $e){
    353         $error_data=$this->formatResponse()->error($e->getCode())->message('error', $e->getMessage())->get('array');
    354         $error_code=$e->getCode();
    355         $error_message=$e->getMessage();
    356         return $this->sendError($error_code,$error_message,$error_data);
    357     }
    358 
    359 }
     310
    360311public function postsInProgress($request){
    361312    try{
     
    374325    try{
    375326        $post_params=$request->get_params();
    376         $response=$this->event->trigger('posts:data', array($post_params['templateUrl'],$post_params['postUrl']));
     327        $response=$this->event->trigger('posts:data', array($post_params['templateUrl'],$post_params['post_id']));
    377328        $response_data=$this->formatResponse()->options($response)->get('array');
    378329        return $this->sendResponse($response_data);
  • news-parser/trunk/inc/CLI/InvokeParse.php

    r3023057 r3034684  
    77class InvokeParse {
    88    protected $postController;
    9     protected $urlErrorMessage='The --post option must be a valid URL.';
     9    protected $urlErrorMessage='The --posts option must be a valid URL.';
    1010    protected $templateErrorMessage='The --template option must be a valid URL.';
    1111    protected $optionsErrorMessage='The --options option must be a valid URL.';
     
    1515
    1616    public function commandCallback( $args,$assoc_args ) {
    17         if(!array_key_exists('post',$assoc_args)){
     17        if(!array_key_exists('posts',$assoc_args)){
    1818            \WP_CLI::log( $this->urlErrorMessage );
    1919             return ;
     
    2828        }
    2929       
    30         $url=$assoc_args['post'];
     30        $url=$assoc_args['posts'];
    3131        if (!$url){
    3232            \WP_CLI::log( $this->urlErrorMessage );
  • news-parser/trunk/inc/Config/di-config.php

    r3023057 r3034684  
    3838    Parser\Modifiers\PostModifiers\AddPostThumbnailModifier::class=>[],
    3939    Controller\PostController::class=>[Parser\HTMLPatternParser::class,Utils\AdapterGuttenberg::class,Models\TemplateModel::class,Models\PostModel::class,Models\PostCacheModel::class],
    40     Controller\ListController::class=>[Parser\XMLParser::class,Models\PostCacheModel::class],
     40    Controller\ListController::class=>[Parser\XMLParser::class,Models\PostModel::class],
    4141    Controller\VisualConstructorController::class=>[Parser\HTMLRaw::class],
    4242    Controller\MediaController::class=>[Models\PostModel::class],
  • news-parser/trunk/inc/Config/scripts-config.php

    r3023057 r3034684  
    1010    'global'=>array(),
    1111    'shared'=> array(
    12         NEWS_PARSER_PLUGIN_SLUG . '-471-chunk'=>array(
    13             'path'=>NEWS_PARSER_PLUGIN_URL . '/public/js/471-'.NEWS_PARSER_PLUGIN_VERSION.'.bundle.js',
     12        NEWS_PARSER_PLUGIN_SLUG . '-384-chunk'=>array(
     13            'path'=>NEWS_PARSER_PLUGIN_URL . '/public/js/384-'.NEWS_PARSER_PLUGIN_VERSION.'.bundle.js',
    1414            'depends_on'=>array()
    1515        ),
  • news-parser/trunk/inc/Controller/CronTaskController.php

    r3023057 r3034684  
    8080            if ($cron_data->getParsedPosts() < $cron_data->getMaxPostsParsed()) {
    8181                try {
    82                     $this->event->trigger('posts:parse', array($post_data['link'], null, $cron_data->getUrl()));
     82                    $this->event->trigger('posts:autopilot-parse', array($post_data['link'], null, $cron_data->getUrl()));
    8383                } catch (MyException $e) {
    8484                    // ToDo: should add some logging
  • news-parser/trunk/inc/Controller/ListController.php

    r3023057 r3034684  
    55use NewsParserPlugin\Message\Errors;
    66use NewsParserPlugin\Parser\Abstracts\AbstractParseContent;
    7 use NewsParserPlugin\Models\PostCacheModel;
     7use NewsParserPlugin\Models\PostModel;
     8
    89
    910/**
     
    2627     */
    2728    protected $parser;
    28     protected $postCache;
     29    protected $postModel;
    2930    /**
    3031     * Init function.
     
    3233     * @param AbstractParseContent $parser
    3334     */
    34     public function __construct(AbstractParseContent $parser, PostCacheModel $post_cache)
     35    public function __construct(AbstractParseContent $parser, PostModel $post_model)
    3536    {
    3637        $this->parser = $parser;
    37         $this->postCache=$post_cache;
     38        $this->postModel=$post_model;
    3839    }
    3940    /**
     
    5051            throw new MyException(Errors::text('WRONG_LIST_FORMAT'), Errors::code('BAD_REQUEST'));
    5152        }
    52         $cached_data=$this->postCache->findByPrefix($url,'created');
    53         $expiration_date=strtotime(end($list_data)->pubDate);
    54         $cached_data=$this->postCache->removeOldPosts($cached_data,$expiration_date);
    55         $cached_data=$this->postCache->removeErrorPosts($cached_data);
    56         $this->postCache->set('created',$cached_data,$url);
    57         return array_map(function($post) use ($cached_data){
    58             return array_merge($this->toArray($post),array_key_exists($post->link,$cached_data)?$this->formatPostDraftData($cached_data[$post->link]):[]);
     53       
     54       
     55        $desired_format = "Y-m-d H:i:s";
     56       // $expiration_date=strtotime(end($list_data)->pubDate);
     57        $expiration_date = date($desired_format, strtotime(end($list_data)->pubDate));
     58        $cached_data=$this->postModel->findByMeta('_template_id',$url,$expiration_date);
     59        //$cached_data=$this->postCache->removeOldPosts($cached_data,$expiration_date,$expiration_date);
     60        //$cached_data=$this->postCache->removeErrorPosts($cached_data);
     61        //$this->postCache->set('created',$cached_data,$url);
     62        $parsed_posts=array_filter($cached_data,function($post){
     63            return $post->_parsing_status!=PostController::PARSING_STATUS_PROCESSING;
     64        });
     65        $cached_posts_links=array_map(function($post){
     66            return $post->_source_url;
     67        },$parsed_posts);
     68        return array_map(function($post) use ($cached_data,$cached_posts_links){
     69            if(($post_index=array_search($post->link,$cached_posts_links))!==false){
     70              return array_merge($this->toArray($post),$this->formatPostDraftData($cached_data[$post_index]));
     71            }
     72            return $this->toArray($post);
    5973        },$list_data);
    6074    }
     
    91105        if(!$post) return [];
    92106        return [
    93             'post_id'=>$post['post_id'],
     107            'post_id'=>$post->ID,
    94108            'draft'=>[
    95                 'editLink'=>$post['links']['editLink'],
     109                'editLink'=>$post->links['editLink'],
    96110            ]
    97111        ];
  • news-parser/trunk/inc/Controller/PostController.php

    r3023057 r3034684  
    33namespace NewsParserPlugin\Controller;
    44
     5use NewsParserPlugin\Entities\Post;
    56use NewsParserPlugin\Exception\MyException;
     7use NewsParserPlugin\Interfaces\AdapterInterface;
     8use NewsParserPlugin\Interfaces\ModelInterface;
    69use NewsParserPlugin\Message\Errors;
    7 use NewsParserPlugin\Message\Success;
     10use NewsParserPlugin\Models\PostCacheModel;
    811use NewsParserPlugin\Models\PostModel;
    912use NewsParserPlugin\Models\TemplateModel;
    1013use NewsParserPlugin\Parser\Abstracts\AbstractParseContent;
    11 use NewsParserPlugin\Interfaces\AdapterInterface;
    12 use NewsParserPlugin\Traits\FunctionAutoloadTrait;
    13 use NewsParserPlugin\Interfaces\PostControllerInterface;
    14 use NewsParserPlugin\Interfaces\EventControllerInterface;
    15 use NewsParserPlugin\Interfaces\ModelInterface;
    16 use NewsParserPlugin\Models\PostCacheModel;
    1714
    1815/**
     
    2623class PostController
    2724{
    28     protected const POST_IN_PROGRESS_KEY = 'news-parser-post-in-progress';
    29     /**
    30      * @var PostModel Post model
    31      */
    32     public $post;
    33     /**
    34      * @var array $parsedData Structure:
    35      * [title] - post title @string
    36      * [image] - post main image url @string
    37      * [body] - post content @string|@array
    38      * [sourceUrl] - url of source page @string
    39      * [authorId] - id of wp-post author
    40      */
    41     protected $parsedData;
    42 
    43     /**
    44      * @var array Parsing extra options
    45      */
    46     protected $options;
    47     /**
    48      * Parsing post options
    49      *
    50      * @var array
    51      */
    52     protected $postOptions;
    53      /**
    54      * User ID of post author
    55      */
    56     protected $authorID;
     25    protected const MAX_TIME_TO_PROCESS = 10 * 10;
     26    public const PARSING_STATUS_PARSED = 'parsed';
     27    public const PARSING_STATUS_PROCESSING = 'processing';
     28
    5729    /**
    5830     * @var AbstractParseContent Parser object
     
    6234    protected $postModel;
    6335    protected $postCacheModel;
    64     /**
    65      * Class Constructor.
    66      *
    67      * Initializes the class instance.
    68      *
    69      * @param AbstractParseContent $parser Parser instance for parsing content.
    70      * @param AdapterInterface $adapter Adapter instance that converts array of body elements data.
    71      * @param array $before_adapter_modifiers (optional) Associative array of modifiers to be applied before the adapter conversion. The format is as follows:
    72      *   [
    73      *     'option_id' => [
    74      *          'path_to_true_modifier_function',
    75      *          'path_to_false_modifier_function'
    76      *         ],
    77      *          ...
    78      *         ]
    79      * The 'option_id' is the identifier of the option.
    80      * The 'path_to_true_modifier_function' is the full PSR-4 like path to the modifier function that will be applied if the 'option_id' is true.
    81      * The 'path_to_false_modifier_function' is the full PSR-4 like path to the modifier function that will be applied if the 'option_id' is false.
    82      * @param array $post_modifiers (optional) Associative array of modifiers to be applied after the adapter conversion. The format is the same as the before_adapter_modifiers array.
    83      */
    84 
    85     public function __construct( AbstractParseContent $parser, AdapterInterface $adapter, ModelInterface $template_model,ModelInterface $post_model, PostCacheModel $post_cache_model)
     36
     37    public function __construct(AbstractParseContent $parser, AdapterInterface $adapter, ModelInterface $template_model, PostModel $post_model, PostCacheModel $post_cache_model)
    8638    {
    8739        $this->adapter = $adapter;
    8840        $this->parser = $parser;
    89         $this->templateModel=$template_model;
    90         $this->postModel=$post_model;
    91         $this->postCacheModel=$post_cache_model;
    92     }
    93     /**
    94      * Parse post and return response in proper format
    95      *
    96      * @param string $url URL of post that should be parsed and saved as draft.
    97      * @param string $_id Front-end index of post that should be parsed and saved as draft.
    98      * @param string $template_url Object with parameters for WP post.
    99      * @return array
    100      */
    101     public function batchParsePost($posts, $template_url = false)
    102     {
    103         $post_template_options = $this->getPostTemplateOptions($template_url);
    104         foreach($posts as $post){
    105             $this->postCacheModel->startProcessing($post,$template_url);
    106         }
    107         return array_map(function($post)use($post_template_options,$template_url){
    108             try{
    109                 $url = $post['link'];
    110                 $this->parsedData = $this->parser->get($url, $post_template_options);
    111                 $this->parsedData['authorId'] = $this->currentUserID();
    112                 $parsed_post= array_merge($this->createPost($url),[
    113                     '_id'=> $post['_id']
    114                 ]);
    115                 $this->postCacheModel->create($parsed_post,$template_url);
    116                 return $parsed_post;
    117             }catch(MyException $e){
    118                 $error_parsed_post=$this->createCacheErrorMessage($post['_id'],$post['link'],$e);
    119                 $this->postCacheModel->create($error_parsed_post,$template_url);
    120                 return $error_parsed_post;
    121             }
    122         },$posts);
    123     }
    124     /**
    125      * Parse post and return response in proper format
    126      *
    127      * @param string $url URL of post that should be parsed and saved as draft.
    128      */
    129     public function parsePost($url, $_id, $template_url = false)
     41        $this->templateModel = $template_model;
     42        $this->postModel = $post_model;
     43        $this->postCacheModel = $post_cache_model;
     44    }
     45
     46    public function parsePost($url, $_id, $template_url)
     47    {
     48
     49        list($post_options, $post_template_options) = $this->getPostTemplateOptions($template_url);
     50        $post_draft = $this->createPostDraft($url, $template_url);
     51        try {
     52            $parsed_data = $this->parser->get($url, $post_template_options);
     53            $processed_data = $this->processPostParsedData($parsed_data, $post_template_options, $url);
     54            $parsed_post = array_merge(
     55                $this->update($post_draft, $processed_data, $post_options, $post_template_options), [
     56                    '_id' => $_id,
     57                ]);
     58            return $parsed_post;
     59        } catch (MyException $e) {
     60            $this->postModel->delete($post_draft->ID);
     61            throw new MyException($e->getMessage(), $e->getCode());
     62        }
     63    }
     64
     65    public function autopilotParsePost($url, $_id, $template_url = false)
    13066    {
    13167        $parsed_url = parse_url($url);
     
    13369            throw new MyException(Errors::text('WRONG_OPTIONS_URL'), Errors::code('BAD_REQUEST'));
    13470        }
    135         $post_template_options = $this->getPostTemplateOptions($template_url);
    136         $this->postCacheModel->startProcessing(['link'=>$url],$template_url);
    137         try{
    138             $this->parsedData = $this->parser->get($url, $post_template_options);
    139             $this->parsedData['authorId'] = $this->currentUserID();
    140             $parsed_post= array_merge( $this->createPost($url),[
    141                 '_id'=> $_id
    142             ],);
    143             $this->postCacheModel->create($parsed_post,$template_url);
     71        list($post_options, $post_template_options) = $this->getPostTemplateOptions($template_url);
     72        $parsed_data = $this->parser->get($url, $post_template_options);
     73        $processed_data = $this->processPostParsedData($parsed_data, $post_template_options, $url);
     74        $post_draft = $this->createPostDraft($url, $template_url, $post_template_options['userID']);
     75        return $this->update($post_draft, $processed_data, $post_options, $post_template_options);
     76    }
     77
     78    public function createPostFromParsedData($url, $_id, $parsed_data, $options, $template_url)
     79    {
     80        $post_draft = $this->createPostDraft($url, $template_url);
     81        try {
     82            $processed_data = $this->processPostParsedData($parsed_data, $options, $url);
     83            $parsed_post = array_merge($this->update($post_draft, $processed_data, $options['postOptions'], $options), [
     84                '_id' => $_id,
     85            ]);
    14486            return $parsed_post;
    145         }catch(MyException $e){
    146             $this->postCacheModel->create($this->createCacheErrorMessage($url,$_id,$e),$template_url);
     87        } catch (MyException $e) {
     88            $this->postModel->delete($post_draft->ID);
    14789            throw new MyException($e->getMessage(), $e->getCode());
    14890        }
    149     }
    150     /**
    151      * Create post from parsed data and return response in proper format
    152      *
    153      * @param array $parsed_data Parsed data of post that should be saved as draft.
    154      * @param string $url URL of post that should be parsed and saved as draft.
    155      * @param string $_id Front-end index of post that should be parsed and saved as draft.
    156      * @param string $template_url Object with parameters for WP post.
    157      * @return array
    158      */
    159     public function autopilotParsePost($url, $_id, $template_url = false)
    160     {
    161         $parsed_url = parse_url($url);
    162         if (!is_array($parsed_url)) {
    163             throw new MyException(Errors::text('WRONG_OPTIONS_URL'), Errors::code('BAD_REQUEST'));
    164         }
    165         $post_template_options = $this->getPostTemplateOptions($template_url);
    166         $this->parsedData = $this->parser->get($url, $post_template_options);
    167         $this->parsedData['authorId'] = $post_template_options['userID'];
    168         return $this->createPost($url); 
    169     }
    170     /**
    171      * Create post from parsed data and return response in proper format
    172      *
    173      * @param array $parsed_data Parsed data of post that should be saved as draft.
    174      * @param string $url URL of post that should be parsed and saved as draft.
    175      * @param string $_id Front-end index of post that should be parsed and saved as draft.
    176      * @param string $template_url Object with parameters for WP post.
    177      * @return array
    178      */
    179     public function createPostFromParsedData($url,$_id,$parsed_data,$options,$template_url)
    180     {
    181         $this->setPostTemplateOptions($options);
    182         $this->postCacheModel->startProcessing(['link'=>$url],$template_url);
    183         $this->parsedData = $parsed_data;
    184         try{
    185             $user_id=$this->currentUserID();
    186             $this->parsedData['authorId'] = $user_id==null?$options['userID']:$user_id;
    187             $parsed_post=array_merge($this->createPost($url),[
    188                 '_id'=> $_id
     91
     92    }
     93
     94    public function getPostsInProgress($template_url, $post_url = null)
     95    {
     96        $desired_format = "Y-m-d H:i:s";
     97        // $expiration_date=strtotime(end($list_data)->pubDate);
     98        $current_timestamp = time();
     99        $expiration_date = date($desired_format, $current_timestamp - 24 * 60 * 60);
     100        $posts = $this->postModel->findByMeta('_parsing_status', self::PARSING_STATUS_PROCESSING);
     101        $filtered_posts = array_filter($posts,
     102            function ($post) use ($current_timestamp) {
     103                $post_timestamp = strtotime($post->post_date);
     104                if ($post->_parsing_status == self::PARSING_STATUS_PROCESSING) {
     105                    if ($current_timestamp - $post_timestamp > self::MAX_TIME_TO_PROCESS) {
     106                        $this->postModel->delete($post->ID);
     107                        return false;
     108                    }
     109                    return true;
     110                }
     111            }
     112        );
     113
     114        return array_map(function ($post) {
     115
     116            return $post->getFormatedAttributes([
     117                'sourceUrl' => '_source_url',
     118                'post_id' => 'ID',
    189119            ]);
    190             $this->postCacheModel->create($parsed_post,$template_url);
    191             return $parsed_post;
    192         }catch(MyException $e){
    193             $this->postCacheModel->create($this->createCacheErrorMessage($url,$_id,$e),$template_url);
    194             throw new MyException($e->getMessage(), $e->getCode());
    195         }
    196        
    197     }
    198     /**
    199      * Get created posts info
    200      *
    201      * @param string $template_url Url of rss feed that was parsed.
    202      * @param string $post_url URL of post that was parsed and saved.
    203      * @return array
    204      */
    205     public function getPostsInProgress($template_url,$post_url=null)
    206     {
    207         if($post_url!==null) return $this->postCacheModel->findByID($post_url,$template_url,'in_progress');
    208         return $this->postCacheModel->findByStatus('in_progress',$template_url);
    209     }
    210     /**
    211      * Get created posts info
    212      *
    213      * @param string $template_url Url of rss feed that was parsed.
    214      * @param string $post_url URL of post that was parsed and saved.
    215      * @return array
    216      */
    217     public function getPostsData($template_url,$post_url)
    218     {
    219         return $this->postCacheModel->findByID($post_url,$template_url);
    220     }
    221     /**
    222      * Create post draft and return response in proper format
    223      *
    224      * @param string $url URL of post that should be parsed and saved as draft.
    225      * @param string $_id Front-end index of post that should be parsed and saved as draft.
    226      * @param string $template_url Object with parameters for WP post.
    227      * @return array
    228      * @throws MyException
    229      */
    230    
    231     public function createPost($url)
    232     {
    233         //$this->assignAuthorId();
    234        
    235         // Unescaped URL
    236         $this->assignSourceUrl($url);
    237         $this->checkParsedData();
    238        
    239         // Apply adapter to adapt parsed body of the post to editor or make changes according to options
    240         $this->applyBodyAdapter();
    241        
    242         // Get post model
    243         $this->post = $this->postModel->create($this->parsedData,$this->formatPostOptions($this->postOptions));
    244 
     120        }, $filtered_posts);
     121    }
     122    public function getPostsData($template_url, $post_id)
     123    {
     124        $post = $this->postModel->findById($post_id);
     125        if (!$post) {
     126            return [
     127                'error' => Errors::text('POST_WAS_NOT_CREATED'),
     128            ];
     129        }
     130        if ($post->_parsing_status == self::PARSING_STATUS_PROCESSING) {
     131            return false;
     132        } else if ($post->_parsing_status == 'parsed') {
     133            return $post->getFormatedAttributes([
     134                'sourceUrl' => '_source_url',
     135                'post_id' => 'ID',
     136            ]);
     137        }
     138    }
     139
     140    protected function update(Post $post, $post_update, $post_options = [], $post_template_options = [])
     141    {
     142        $post->update(array_merge(
     143            $this->formatPostData($post_update),
     144            $this->formatPostOptions($post_options),
     145            $this->formatPostMeta([
     146                'status' => self::PARSING_STATUS_PARSED,
     147                'image' => $post_update['image'],
     148            ])
     149        ));
     150        $post_id = $this->postModel->update($post);
    245151        // Apply modifiers to post according to template post options
    246         \apply_filters('NewsParserPlugin\Controller\PostController:post', $this->post, $this->options);
    247 
    248         return $this->post->getAttributes();
    249     }
    250     /**
    251      * Retrieves the parsed data associated with the PostController.
    252      *
    253      * This method returns the parsed data stored in the PostController object.
    254      *
    255      * @return array The parsed data associated with the PostController.
    256      */
    257 
    258     public function getParsedData()
    259     {
    260         return $this->parsedData;
    261     }
    262     /**
    263      * Updates the body array in the parsed data of the PostController.
    264      *
    265      * This method takes an array of body elements and updates the 'body' key in the parsed data of the PostController with the provided array.
    266      *
    267      * @param array $body_array The array of body elements to update the parsed data with.
    268      * @return void
    269      */
    270 
    271     public function updateParsedDataBody(array|string $body)
    272     {
    273         $this->parsedData['body']=$body;
    274     }
    275     /**
    276      * Parsed data form url and returns parsed data.
    277      *
    278      * @param string $url URL of post that should be parsed and saved as draft.
    279      * @param string $template_options Object with parameters for WP post.
    280      */
    281     public function parseData($url,$template_options)
    282     {
    283         return $this->parser->get($url, $template_options);
    284     }
    285    
     152        if ($post_id !== false) {
     153            \apply_filters('NewsParserPlugin\Controller\PostController:post', $post, $post_template_options);
     154        }
     155        return $post->getFormatedAttributes([
     156            'post_author' => 'post_author',
     157            'link' => '_source_url',
     158            'title' => 'post_title',
     159            'links' => 'links',
     160            'status' => '_parsing_status',
     161            'post_id' => 'ID',
     162        ]);
     163    }
     164
    286165    /**
    287166     * Apply body adapter to parsed data
    288167     */
    289     protected function applyBodyAdapter()
    290     {
    291         $this->parsedData=\apply_filters('NewsParserPlugin\Controller\PostController\parsedData:adapterBefor', $this->parsedData, $this->options);
    292         $this->updateParsedDataBody( $this->adapter->convert($this->parsedData['body']));
    293         $this->updateParsedDataBody( \apply_filters('NewsParserPlugin\Controller\PostControllerp\arsedData\body:adapterAfter', $this->parsedData['body'], $this->options));
     168    protected function applyBodyAdapter($parsed_data, $options)
     169    {
     170        $parsed_data = \apply_filters('NewsParserPlugin\Controller\PostController\parsedData:adapterBefor', $parsed_data, $options);
     171        $parsed_data['body'] = $this->adapter->convert($parsed_data['body']);
     172        $parsed_data['body'] = \apply_filters('NewsParserPlugin\Controller\PostControllerp\arsedData\body:adapterAfter', $parsed_data['body'], $options);
     173        return $parsed_data;
     174    }
     175    protected function formatPostData($parsed_data)
     176    {
     177        $formated_post_data = [];
     178        if (array_key_exists('title', $parsed_data)) {
     179            $formated_post_data['post_title'] = \wp_strip_all_tags($parsed_data['title']);
     180        }
     181
     182        if (array_key_exists('body', $parsed_data)) {
     183            $formated_post_data['post_content'] = $parsed_data['body'];
     184        }
     185
     186        if (array_key_exists('authorId', $parsed_data)) {
     187            $formated_post_data['post_author'] = $parsed_data['authorId'];
     188        }
     189
     190        return $formated_post_data;
     191    }
     192    protected function formatPostMeta($options)
     193    {
     194        $formated_post_meta = [];
     195        if (array_key_exists('status', $options)) {
     196            $formated_post_meta['_parsing_status'] = $options['status'];
     197        }
     198
     199        if (array_key_exists('image', $options)) {
     200            $formated_post_meta['_image'] = $options['image'];
     201        }
     202
     203        if (array_key_exists('sourceUrl', $options)) {
     204            $formated_post_meta['_source_url'] = $options['sourceUrl'];
     205        }
     206
     207        if (array_key_exists('templateID', $options)) {
     208            $formated_post_meta['_template_id'] = $options['templateID'];
     209        }
     210
     211        return $formated_post_meta;
    294212    }
    295213    /**
     
    300218     * @throws MyException If no extra options or post options are available.
    301219     */
    302      protected function getPostTemplateOptions($options_id)
    303      {
    304          $template_options=$this->templateModel->findByID($options_id);
    305          $this->setPostTemplateOptions($template_options);
    306          return $template_options;
    307      }
    308      /**
    309       * Set the post options based on the given template options
    310       *
    311       * @param array $template_options Template options.
    312       * @return void|MyException
    313       */
    314      protected function setPostTemplateOptions($options)
    315      {
    316         if (!array_key_exists('extraOptions',$options)) {
    317             throw new MyException(Errors::text('NO_EXTRA_OPTIONS'), Errors::code('BAD_REQUEST'));
    318         }
    319         if (!array_key_exists('postOptions',$options)) {
    320             throw new MyException(Errors::text('NO_POST_OPTIONS'), Errors::code('BAD_REQUEST'));
    321         }
    322         $aiOptions=['aiOptions'=>array_key_exists('aiOptions',$options)?$options['aiOptions']:false];
    323          $this->options=array_merge($options['extraOptions'],$aiOptions);
    324          $this->postOptions=$options['postOptions'];
    325          return $this->options;
    326      }
     220    protected function getPostTemplateOptions($options_id)
     221    {
     222        $template_options = $this->templateModel->findByID($options_id);
     223        return [$template_options['postOptions'], $template_options];
     224    }
     225
     226    protected function processPostParsedData($parsed_data, $options, $url)
     227    {
     228        $parsed_data['sourceUrl'] = $url;
     229        $this->validateParsedData($parsed_data);
     230
     231        // Apply adapter to adapt parsed body of the post to editor or make changes according to options
     232        return $this->applyBodyAdapter($parsed_data, $options);
     233    }
    327234    /**
    328235     * Assign the current user's ID as the author ID
     
    330237    protected function currentUserID()
    331238    {
    332        return apply_filters('news_parser_filter_author_id', \get_current_user_id());
    333     }
    334    
    335     /**
    336      * Assign the source URL to the parsed data
    337      *
    338      * @param string $url Source URL to assign.
    339      */
    340     protected function assignSourceUrl($url)
    341     {
    342         $this->parsedData['sourceUrl'] = $url;
    343     }
    344 
    345 
    346     /**
    347      * Get an instance of the PostModel class.
    348      *
    349      * @return PostModel
    350      */
    351     protected function postModelsFactory()
    352     {
    353         return new PostModel($this->parsedData);
    354     }
    355 
    356     /**
    357      * Check parsed data for required fields.
    358      *
    359      * @throws MyException When any of the required fields are missing or empty.
    360      * @return void
    361      */
    362 
    363     protected function checkParsedData()
    364     {
    365         if(!array_key_exists('title',$this->parsedData)||empty($this->parsedData['title'])){
    366             throw new MyException(Errors::text('NO_TITLE'),Errors::code('INNER_ERROR'));
    367         }
    368         if(!array_key_exists('body',$this->parsedData)||empty($this->parsedData['body'])){
    369             throw new MyException(Errors::text('NO_BODY'),Errors::code('INNER_ERROR'));
    370         }
    371         if(!array_key_exists('authorId',$this->parsedData)||$this->parsedData['authorId']==''){
    372             throw new MyException(Errors::text('NO_AUTHOR'),Errors::code('INNER_ERROR'));
    373         }
    374         if(!array_key_exists('sourceUrl',$this->parsedData)||empty($this->parsedData['sourceUrl'])){
    375             throw new MyException(Errors::text('NO_POST_URL'),Errors::code('INNER_ERROR'));
    376         }
    377         if(!array_key_exists('image',$this->parsedData)||empty($this->parsedData['image'])){
    378             if($this->options['addFeaturedMedia']){
    379                 throw new MyException(Errors::text('NO_IMAGE'),Errors::code('INNER_ERROR'));
    380             }
    381         }
    382     }
    383     /**
    384      * Create a cache error message.
    385      *
    386      * @param string $url The URL of the post.
    387      * @param string $_id The ID of the post.
    388      * @param MyException $error The error message.
    389      * @return array Returns the formatted cache error message.
    390      * @throws MyException
    391      */
    392     protected function createCacheErrorMessage($url,$_id,$error)
    393     {
    394         return [
    395             '_id'=> $_id,
    396             'link'=>$url,
    397         'error'=>[
    398             'code'=> $error->getCode(),
    399             'message'=>$error->getMessage(),
    400             'data'=>[
    401                 'message'=>$error->getMessage()
    402             ]
    403             ]
    404             ];
    405     }
    406     /**
    407      * Format the post options array to match the expected format.
    408      *
    409      * @param array $postOptions The post options to format.
    410      *
    411      * @return array Returns the formatted post options array.
    412      */
    413 
    414      protected function formatPostOptions($post_options)
    415      {
    416         $formated_post_options=[];
    417          if (isset($post_options['status'])){
    418             $formated_post_options['post_status']=$post_options['status'];
    419          }
    420          if (isset($post_options['categories'])){
    421              $formated_post_options['post_category']=$post_options['categories'];
    422          }
    423          if (isset($post_options['tags'])){
    424              $formated_post_options['tags_input']=$post_options['tags'];
    425          }
    426          return $formated_post_options;
    427      }
     239        return apply_filters('news_parser_filter_author_id', \get_current_user_id());
     240    }
     241
     242    protected function validateParsedData($parsed_data)
     243    {
     244        if (!array_key_exists('title', $parsed_data) || empty($parsed_data['title'])) {
     245            throw new MyException(Errors::text('NO_TITLE'), Errors::code('INNER_ERROR'));
     246        }
     247        if (!array_key_exists('body', $parsed_data) || empty($parsed_data['body'])) {
     248            throw new MyException(Errors::text('NO_BODY'), Errors::code('INNER_ERROR'));
     249        }
     250        if (!array_key_exists('authorId', $parsed_data) || $parsed_data['authorId'] == '') {
     251            // throw new MyException(Errors::text('NO_AUTHOR'),Errors::code('INNER_ERROR'));
     252        }
     253        if (!array_key_exists('sourceUrl', $parsed_data) || empty($parsed_data['sourceUrl'])) {
     254            throw new MyException(Errors::text('NO_POST_URL'), Errors::code('INNER_ERROR'));
     255        }
     256
     257    }
     258
     259    protected function createPostDraft($url, $template_url, $post_author = null)
     260    {
     261        return $this->postModel->create($this->formatPostData([
     262            'authorId' => $post_author == null ? $this->currentUserID() : $post_author,
     263            'body' => 'Processing...',
     264            'title' => 'Processing...',
     265        ]),
     266            [],
     267            $this->formatPostMeta([
     268                'sourceUrl' => $url,
     269                'status' => self::PARSING_STATUS_PROCESSING,
     270                'templateID' => $template_url,
     271            ]));
     272    }
     273
     274    protected function formatPostOptions($post_options)
     275    {
     276        $formated_post_options = [];
     277        if (isset($post_options['status'])) {
     278            $formated_post_options['post_status'] = $post_options['status'];
     279        }
     280        if (isset($post_options['categories'])) {
     281            $formated_post_options['post_category'] = $post_options['categories'];
     282        }
     283        if (isset($post_options['tags'])) {
     284            $formated_post_options['tags_input'] = $post_options['tags'];
     285        }
     286        return $formated_post_options;
     287    }
    428288}
  • news-parser/trunk/inc/Entities/Factory/PostFactory.php

    r3023057 r3034684  
    2222     * @return Post The created Post instance.
    2323     */
    24     public function create($post_array)
     24    public function create($wp_post,$post_meta)
    2525    {
    26         return new Post($post_array);
     26        /*
     27        $data = [
     28            'ID' => $post_object->ID,
     29            'post_title' => $post_object->post_title,
     30            'post_content' => $post_object->post_content,
     31            'post_author' => $post_object->post_author,
     32            'post_date' => $post_object->post_date,
     33            'post_status' => $post_object->post_status,
     34            'post_category' => $post_object->post_status,
     35            'tags_input' => $post_object->tags_input,
     36        ];
     37        */
     38        return new Post(array_merge($post_meta,get_object_vars($wp_post)));
    2739    }
    2840}
  • news-parser/trunk/inc/Entities/Post.php

    r3023057 r3034684  
    2020     * @var string
    2121     */
    22     public $title;
     22    public $post_title;
    2323    /**
    2424     * Post content.
     
    2626     * @var string
    2727     */
    28     public $body;
     28    public $post_content;
    2929    /**
    3030     * Featured image url.
     
    3232     * @var string|false
    3333     */
    34     public $image;
    35     /**
    36      * Status of the post could be parsed|draft
    37      *
    38      * @var string
    39      */
    40     public $status;
     34    public $_image;
     35    /**
     36     * Status of the post could be parsed|processing
     37     *
     38     * @var string
     39     */
     40    public $_parsing_status;
     41    public $post_status;
     42    public $post_category=[];
     43    public $tags_input=[];
    4144    /**
    4245     * Url of source post.
     
    4447     * @var string|false
    4548     */
    46     public $sourceUrl;
     49    public $_source_url;
    4750    /**
    4851     * Id of wordpress post.
     
    7477    {
    7578       
    76         $this->title = $post_data_array['title'];
    77         $this->body = $post_data_array['body'];
    78         $this->authorId = $post_data_array['authorId'];
    79         $this->image = isset($post_data_array['image'])?$post_data_array['image']:false;
    80         $this->sourceUrl = isset($post_data_array['sourceUrl'])?$post_data_array['sourceUrl']:false;
     79        $this->post_title = $post_data_array['post_title'];
     80        $this->post_date= $post_data_array['post_date'];
     81        $this->post_content = $post_data_array['post_content'];
     82        $this->post_author = $post_data_array['post_author'];
     83        $this->_image = isset($post_data_array['_image'])?$post_data_array['_image']:false;
     84        $this->_source_url = isset($post_data_array['_source_url'])?$post_data_array['_source_url']:false;
    8185        $this->ID=$post_data_array['ID'];
    82         $this->status = 'parsed';
     86        $this->_parsing_status = array_key_exists('_parsing_status',$post_data_array)?$post_data_array['_parsing_status']:null;
     87        $this->_template_id = array_key_exists('_template_id',$post_data_array)?$post_data_array['_template_id']:null;
    8388        $this->links=$this->getPostLinksWordpress($this->ID);
     89        $this->post_status = array_key_exists('post_status',$post_data_array)?$post_data_array['post_status']:'draft';
     90        $this->post_category = array_key_exists('post_category',$post_data_array)?$post_data_array['post_category']:[];
     91        $this->tags_input = array_key_exists('tags_input',$post_data_array)?$post_data_array['tags_input']:[];
     92       
    8493    }
    8594    /**
     
    92101    public function addPostThumbnail($image_url = null, $alt = '')
    93102    {
    94         $url=is_null($image_url)?$this->image:$image_url;
    95         $featured_image_title=!empty($alt)?$alt:$this->title;
     103        $url=is_null($image_url)?$this->_image:$image_url;
     104        $featured_image_title=!empty($alt)?$alt:$this->post_title;
    96105        return $this->attachImageToPostWordpress($url, $this->ID, true, $featured_image_title);
    97106    }
     
    104113     * @return array|string|object
    105114     */
    106     public function getAttributes($format = 'array')
     115    public function getFormatedAttributes($map=['post_author'],$format = 'array')
     116    {
     117        $data_array = [];
     118        foreach ($map as $map_key=>$local_key) {
     119            $data_array[$map_key] = $this->$local_key;
     120        }
     121        $data_json = json_encode($data_array);
     122        switch ($format) {
     123            case 'json':
     124                return $data_json;
     125            case 'object':
     126                return json_decode($data_json);
     127            default:
     128                return $data_array;
     129        }
     130    }
     131    /**
     132     * Return Post data in array|json|object format
     133     *
     134     * @param string $format
     135     * @return array|string|object
     136     */
     137    public function getPostAttributes($format = 'array')
    107138    {
    108139        $data_array = array(
    109             'link'=>$this->sourceUrl,
    110             'title' => $this->title,
    111             'links' => $this->links,
    112             'status' => $this->status,
    113             'post_id' => $this->ID,
     140            'post_author'=>$this->post_author,
     141            'post_title'=>$this->post_title,
     142            'post_content' => $this->post_content,
     143            'post_status' => $this->post_status,
     144            'post_category' => $this->post_category,
     145            'tags_input' => $this->tags_input,
     146            'ID' => $this->ID,
    114147        );
    115148        $data_json = json_encode($data_array);
     
    123156        }
    124157    }
     158    public function getPostMetaAttributes($format = 'array')
     159    {
     160        $data_array = array(
     161            '_parsing_status'=>$this->_parsing_status,
     162            '_source_url'=>$this->_source_url,
     163            '_template_id'=>$this->_template_id,
     164        );
     165        $data_json = json_encode($data_array);
     166        switch ($format) {
     167            case 'json':
     168                return $data_json;
     169            case 'object':
     170                return json_decode($data_json);
     171            default:
     172                return $data_array;
     173        }
     174    }
    125175    /**
    126176     * Facade function for WP media_sideload_image
     
    147197        return \media_sideload_image($file, $post_id, $desc, $return);
    148198    }
    149    
     199    public function update($post_data_array)
     200    {
     201        foreach ($post_data_array as $prop => $value) {
     202            if(property_exists($this, $prop)){
     203                $this->$prop = $value;
     204            }
     205        }
     206    }
    150207    /**
    151208     * Download and attach image to WP post
  • news-parser/trunk/inc/Models/PostCacheModel.php

    r3023057 r3034684  
    22namespace NewsParserPlugin\Models;
    33
    4 use NewsParserPlugin\Exception\MyException;
    5 use NewsParserPlugin\Interfaces\ModelInterface;
    6 use NewsParserPlugin\Message\Errors;
    7 use NewsParserPlugin\Entities\Factory\CronDataFactory;
    8 
    9 
    10 class PostCacheModel{
    11     protected const POST_CACHE_KEY='news-parser-post_cache';
    12     protected const IN_PROGRESS_CACHE_KEY='news-parser-post_cache_in_progress';
    13     protected const IN_PROGRESS_CACHE_LIFETIME=60*10;
    14     protected const POST_CACHE_LIFETIME=60*60*24*14;
     4class PostCacheModel
     5{
     6    protected $isLocked = false;
     7    protected const LOCK_FILE_NAME = 'PostCacheModelLock.txt';
     8    protected const POST_CACHE_KEY = 'news-parser-post_cache';
     9    protected const IN_PROGRESS_CACHE_KEY = 'news-parser-post_cache_in_progress';
     10    protected const IN_PROGRESS_CACHE_LIFETIME = 60 * 10;
     11    protected const POST_CACHE_LIFETIME = 60 * 60 * 24 * 14;
    1512
    1613    /**
     
    3431     *      'data' => error data @array
    3532     *  ]
    36      * 
     33     *
    3734     * @param string $type Type of cached posts
    3835     * @param string $prefix Prefix of cached posts
    3936     * @return array|mixed
    4037     */
    41     public function get($type,$prefix){
    42         switch ($type){
     38    public function get($type, $prefix)
     39    {
     40        if ($this->isLocked()) {
     41            sleep(0.5);
     42            return $this->get($type, $prefix);
     43        }
     44        switch ($type) {
    4345            case 'in_progress':
    44                 $response=get_transient(self::IN_PROGRESS_CACHE_KEY.'-'.$prefix);
     46                $response = get_transient(self::IN_PROGRESS_CACHE_KEY . '-' . $prefix);
    4547                break;
    4648            case 'created':
    47                 $response=get_transient(self::POST_CACHE_KEY.'-'.$prefix);
    48                 break;
    49             }
    50         if(!$response){
     49                $response = get_transient(self::POST_CACHE_KEY . '-' . $prefix);
     50                break;
     51        }
     52        if (!$response) {
    5153            return [];
    5254        }
     
    7880     * @return void
    7981     */
    80     public function set($type,$posts,$prefix)
    81     {
    82         switch ($type){
     82    public function set($type, $posts, $prefix)
     83    {
     84        if ($this->isLocked()) {
     85            sleep(0.5);
     86            return $this->get($type, $prefix);
     87        }
     88        $this->setLock();
     89        switch ($type) {
    8390            case 'in_progress':
    84                 set_transient(self::IN_PROGRESS_CACHE_KEY.'-'.$prefix,$this->removeOldPosts($posts,time()-self::IN_PROGRESS_CACHE_LIFETIME),self::IN_PROGRESS_CACHE_LIFETIME);
    85                 break;
    86             case  'created':
    87                 set_transient(self::POST_CACHE_KEY.'-'.$prefix,$this->removeOldPosts($posts,time()-self::POST_CACHE_LIFETIME),self::POST_CACHE_LIFETIME);
    88                 break;
    89             }
    90     }
    91     public function update($post,$prefix)
    92     {
    93         $posts=$this->get('created',$prefix);
    94         if(!is_array($posts)){
    95             $posts=[];
    96         }
    97         $posts[$post['link']]=$post;
    98         $this->set('created',$posts,$prefix);
    99     }
    100     public function create($post,$prefix)
    101     {
    102         $posts_in_progress=$this->get('in_progress',$prefix);
    103         if(is_array($posts_in_progress)&&array_key_exists($post['link'],$posts_in_progress)){
     91                set_transient(self::IN_PROGRESS_CACHE_KEY . '-' . $prefix, $this->removeOldPosts($posts, time() - self::IN_PROGRESS_CACHE_LIFETIME), self::IN_PROGRESS_CACHE_LIFETIME);
     92                break;
     93            case 'created':
     94                set_transient(self::POST_CACHE_KEY . '-' . $prefix, $this->removeOldPosts($posts, time() - self::POST_CACHE_LIFETIME), self::POST_CACHE_LIFETIME);
     95                break;
     96        }
     97        $this->releaseLock();
     98    }
     99    public function update($post, $prefix)
     100    {
     101        $posts = $this->get('created', $prefix);
     102        if (!is_array($posts)) {
     103            $posts = [];
     104        }
     105        $posts[$post['link']] = $post;
     106        $this->set('created', $posts, $prefix);
     107    }
     108    public function create($post, $prefix)
     109    {
     110        $posts_in_progress = $this->get('in_progress', $prefix);
     111        if (is_array($posts_in_progress) && array_key_exists($post['link'], $posts_in_progress)) {
    104112            unset($posts_in_progress[$post['link']]);
    105113        }
    106         $this->set('in_progress',$posts_in_progress,$prefix);
    107         $this->update(array_merge($post,['status'=>'created','timestamp'=>time()]),$prefix);
    108     }
    109     public function findByID($id,$prefix,$status='created')
    110     {
    111         $posts=$this->get($status,$prefix);
    112         if(!is_array($posts)){
     114        $this->set('in_progress', $posts_in_progress, $prefix);
     115        $this->update(array_merge($post, ['status' => 'created', 'timestamp' => time()]), $prefix);
     116    }
     117    public function findByID($id, $prefix, $status = 'created')
     118    {
     119        $posts = $this->get($status, $prefix);
     120        if (!is_array($posts)) {
    113121            return false;
    114122        }
    115         if(array_key_exists($id,$posts)){
     123        if (array_key_exists($id, $posts)) {
    116124            return $posts[$id];
    117125        }
    118126        return false;
    119127    }
    120     public function findByStatus($status,$prefix)
    121     {
    122         $posts=$this->get($status,$prefix);
    123         if(!is_array($posts)){
     128    public function findByStatus($status, $prefix)
     129    {
     130        $posts = $this->get($status, $prefix);
     131        if (!is_array($posts)) {
    124132            return false;
    125133        }
    126134        return $posts;
    127135    }
    128     public function findByPrefix($prefix,$status='created')
    129     {
    130         return $this->findByStatus($status,$prefix);
    131     }
    132     public function delete($prefix,$id=null)
    133     {
    134         if($id==null) {
    135             delete_transient(self::POST_CACHE_KEY.'-'.$prefix);
     136    public function findByPrefix($prefix, $status = 'created')
     137    {
     138        return $this->findByStatus($status, $prefix);
     139    }
     140    public function delete($prefix, $id = null)
     141    {
     142        if ($id == null) {
     143            delete_transient(self::POST_CACHE_KEY . '-' . $prefix);
    136144            return;
    137145        }
    138         $posts=$this->get('created',$prefix);
    139        
    140         if(array_key_exists($id,$posts)){
     146        $posts = $this->get('created', $prefix);
     147
     148        if (array_key_exists($id, $posts)) {
    141149            unset($posts[$id]);
    142150        }
    143         $this->set($posts,'created',$prefix);
    144     }
    145     public function startProcessing($post,$prefix)
    146     {
    147         $posts=$this->get('in_progress',$prefix);
    148         if(!is_array($posts)){
    149             $posts=[];
    150         }
    151         $posts[$post['link']]=array_merge($post,['status'=>'processing','timestamp'=>time()]);
    152         $this->set('in_progress',$posts,$prefix);
    153         $this->delete($post['link'],$prefix);
    154     }
    155     public function removeOldPosts($posts,$expiration_timestamp)
    156     {
    157         return array_filter($posts,function($post) use ($expiration_timestamp){
    158             return $post['timestamp']>$expiration_timestamp;
     151        $this->set($posts, 'created', $prefix);
     152    }
     153    public function startProcessing($post, $prefix)
     154    {
     155        $posts = $this->get('in_progress', $prefix);
     156        if (!is_array($posts)) {
     157            $posts = [];
     158        }
     159        $posts[$post['link']] = array_merge($post, ['status' => 'processing', 'timestamp' => time()]);
     160        $this->set('in_progress', $posts, $prefix);
     161        $this->delete($post['link'], $prefix);
     162    }
     163    public function removeOldPosts($posts, $expiration_timestamp)
     164    {
     165        return array_filter($posts, function ($post) use ($expiration_timestamp) {
     166            return $post['timestamp'] > $expiration_timestamp;
    159167        });
    160168    }
    161169    public function removeErrorPosts($posts)
    162170    {
    163         return array_filter($posts,function($post) {
    164             return !array_key_exists('error',$post);
     171        return array_filter($posts, function ($post) {
     172            return !array_key_exists('error', $post);
    165173        });
    166174    }
     175    private function setLock()
     176    {
     177        /*
     178        $lock_file_name = NEWS_PARSER_PLUGIN_DIR . self::LOCK_FILE_NAME;
     179        if(!$is_lock_file_exists=file_exists($lock_file_name)&&!$is_writable=is_writable($lock_file_name)) error_log("No file to acquire lock");
     180        $fp = fopen($lock_file_name, 'r+');
     181        if (flock($fp, LOCK_EX)) { // Acquire exclusive lock, potentially blocking
     182            $this->isLocked = true;
     183        } else {
     184            error_log("Failed to acquire lock");
     185            return false; // Lock not acquired
     186        }
     187        */
     188    }
     189
     190    private function releaseLock()
     191    {
     192        /*
     193        $this->isLocked = false;
     194        flock($lock_file, LOCK_UN); // Release lock
     195        fclose($lock_file);
     196        */
     197    }
     198
     199    private function isLocked()
     200    {
     201       if ($this->isLocked) return true;
     202       return false;
     203    }
     204
    167205}
  • news-parser/trunk/inc/Models/PostModel.php

    r3023057 r3034684  
    22namespace NewsParserPlugin\Models;
    33
    4 use NewsParserPlugin\Exception\MyException;
    5 use NewsParserPlugin\Interfaces\ModelInterface;
    6 use NewsParserPlugin\Message\Errors;
    74use NewsParserPlugin\Entities\Factory\PostFactory;
    85use NewsParserPlugin\Entities\Post;
     6use NewsParserPlugin\Exception\MyException;
     7use NewsParserPlugin\Message\Errors;
     8use WP_Query;
     9
    910
    1011/**
     
    1819 */
    1920
    20 class PostModel implements ModelInterface
     21class PostModel
    2122{
     23   
     24    protected $wpID;
    2225    /**
    2326     * The post factory instance.
    24      * 
     27     *
    2528     * @var PostFactory
    2629     */
    2730
    28    protected $postFactory;
    29    /**
    30     * Constructor.
    31     *
    32     * @param PostFactory $post_factory The post factory instance.
    33     */
    34    public function __construct (PostFactory $post_factory)
    35    {
    36         $this->postFactory=$post_factory;
    37    }
     31    protected $postFactory;
     32    /**
     33     * Constructor.
     34     *
     35     * @param PostFactory $post_factory The post factory instance.
     36     */
     37    public function __construct(PostFactory $post_factory)
     38    {
     39        $this->postFactory = $post_factory;
     40    }
    3841    /**
    3942     * Create post instance from existed post data.
     
    4750            return false;
    4851        }
    49         $post_array=array(
    50             'title'=>$wp_post->post_title,
    51             'body'=>$wp_post->post_content,
    52             'sourceUrl'=>false,
    53             'authorId'=>$wp_post->post_author,
    54             'image'=>get_the_post_thumbnail_url($wp_post, 'full'),
    55             'ID'=>absint($post_id)
    56         );
    57         return $this->postFactory->create($post_array);
    58     }
    59     /**
    60      * Create wordpress post, gets WP post ID.Returns array with post data.
    61      * Returned array structure:
    62      *  [link,
    63      *   post_id,
    64      *   title,
    65      *   links=>[previewLink,editLink,deleteLink],
    66      *   status=>draft|parsed]
    67      *
    68      * @param array $post_data Array with wp post attributes  https://developer.wordpress.org/reference/functions/wp_insert_post/
    69      * @return array|false
    70      */
    71     public function create($post_array,$post_options_array)
    72     {
    73         $this->isDataValid($post_array);
    74         $post_initial_data = array(
    75             'post_title' => \wp_strip_all_tags($post_array['title']),
    76             'post_content' => $post_array['body'],
    77             'post_author' => $post_array['authorId']
    78         );
    79         $post_id = \wp_insert_post(array_merge($post_initial_data,$post_options_array));
     52        $post_meta=array_map(function($meta){
     53            return count($meta)>0?$meta[0]:false;
     54        },get_post_meta($post_id));
     55        $post_array = array_merge(array(
     56            'post_title' => $wp_post->post_title,
     57            'post_content' => $wp_post->post_content,
     58            'post_author' => $wp_post->post_author,
     59            '_image' => get_the_post_thumbnail_url($wp_post, 'full'),
     60            'ID' => absint($post_id),
     61        ),$post_meta);
     62        return $this->postFactory->create($wp_post,$post_meta);
     63    }
     64    /**
     65     * Finds WordPress posts with the specified meta key and value.
     66     *
     67     * @param string $meta_key The meta key to query.
     68     * @param string $meta_value The meta value to match.
     69     *
     70     * @return array An array of WordPress post objects or an empty array if none found.
     71     */
     72    public function findByMeta($meta_key, $meta_value,$exp_date=false)
     73    {
     74        global $post;
     75        $args = [
     76            'meta_key' => $meta_key,
     77            'meta_value' => $meta_value,
     78            'posts_per_page' => 9999,
     79            'post_status'=>'all'
     80           
     81        ];
     82        if($exp_date){
     83            $args['date_query']=array(
     84                array(
     85                    'after' => $exp_date
     86                )
     87            );
     88        }
     89        $query = new WP_Query($args);
     90
     91        // Return an array of Post objects from the query results
     92        $posts = [];
     93       
     94        if ($query->have_posts()) {
     95            while ($query->have_posts()) {
     96                $query->the_post();
     97               
     98                $post_meta=array_map(function($meta){
     99                   return $meta[0];
     100                }, get_post_meta($post->ID));
     101                $posts[] = $this->postFactory->create($post, $post_meta);
     102            }
     103        }
     104        wp_reset_postdata();
     105
     106        return $posts;
     107    }
     108   
     109
     110    /**
     111     * Creates a WordPress post and returns details as an array.
     112     *
     113     * @param {object} post_data WordPress post attributes (see {@link https://developer.wordpress.org/reference/functions/wp_insert_post/}).
     114     * @param {object} [post_options_array={}] Additional post options to pass to `wp_insert_post`.
     115     * @param {string} [mode=''] Optional validation mode:
     116     *   - `'strict'`: Performs additional data validation (implementation dependent).
     117     *   - '': Skips additional validation.
     118     *
     119     * @returns {object|false}
     120     *   - On success, returns an instance of Post object with the following properties:
     121     *     - `link`: String, post permalink.
     122     *     - `authorId`: ID of the post author.
     123     *     - 'image' : String, post featured image URL.
     124     *     - `ID`: Number, WordPress post ID.
     125     *     - 'sourceUrl': String, post source URL.
     126     *     - `title`: String, post title.
     127     *     - `links`: Object with preview, edit, and delete links.
     128     *     - `status`: String, post status ('processing' or 'parsed').
     129     *   - On failure, returns `false`.
     130     *
     131     * @throws {MyException} If WP post creation fails or post data is invalid in strict mode.
     132     */
     133
     134    public function create($post_array, $post_options_array, $post_meta = [], $mode = '')
     135    {
     136        if ($mode == 'strict') {
     137            $this->isDataValid($post_array);
     138        }
     139
     140        $post_id = \wp_insert_post(array_merge($post_array, $post_options_array));
     141
    80142        if (\is_wp_error($post_id)) {
    81143            throw new MyException($post_id->get_error_message(), Errors::code('BAD_REQUEST'));
    82         }
    83         $post_array['ID']=$post_id;
    84    
    85         return $this->postFactory->create($post_array);
     144        }
     145        $post_array['ID'] = $post_id;
     146        $this->updatePostMeta($post_id, $post_meta);
     147        $wp_post=get_post($post_id);
     148        return $this->postFactory->create($wp_post, $post_meta);
    86149    }
    87150    /**
     
    92155     * @return void
    93156     */
    94     public function update($post_id,$update_data)
     157    public function update(Post $post)
    95158    {
    96159        $post_array = [
    97             'ID' => $post_id,
     160            'ID' => $post->ID,
    98161        ];
    99         \wp_update_post(array_merge($post_array,$update_data));
     162        $post_id = \wp_update_post($post->getPostAttributes());
     163        $post_meta = $post->getPostMetaAttributes();
     164        $this->updatePostMeta($post_id, $post_meta);
     165        return $post_id;
     166    }
     167   
     168    /**
     169     * Deletes a WordPress post.
     170     *
     171     * @param integer $post_id The ID of the post to delete.
     172     *
     173     * @return bool True if the post was deleted successfully, false otherwise.
     174     * @throws MyException If the post deletion fails.
     175     */
     176    public function delete($post_id)
     177    {
     178        if (!wp_delete_post($post_id, true)) {
     179           
     180            $error = wp_get_error_reason();
     181            throw new MyException($error, Errors::code('DELETE_FAILED'));
     182        }
     183
     184        return true;
    100185    }
    101186    protected function isDataValid($post_data_array)
    102187    {
    103         if (!isset($post_data_array['title'])||empty($post_data_array['title'])) {
     188        if (!isset($post_data_array['title']) || empty($post_data_array['title'])) {
    104189            throw new MyException(Errors::text('NO_TITLE'), Errors::code('BAD_REQUEST'));
    105190        }
    106         if (!isset($post_data_array['body'])||empty($post_data_array['body'])) {
     191        if (!isset($post_data_array['body']) || empty($post_data_array['body'])) {
    107192            throw new MyException(Errors::text('NO_BODY'), Errors::code('BAD_REQUEST'));
    108193        }
     
    111196        }
    112197    }
    113      
     198    protected function updatePostMeta($post_id, $post_meta)
     199    {
     200        if(!is_array($post_meta)) return false;
     201        foreach ($post_meta as $key => $value) {
     202            update_post_meta($post_id, $key, $value);
     203        }
     204        return true;
     205    }
    114206}
  • news-parser/trunk/inc/Parser/HTMLPatternParser.php

    r3023057 r3034684  
    3939        }
    4040        $template = $this->options['template'];
    41 
    4241        foreach ($template['children'] as $child_element) {
    4342            // Create search template for Sunra\HtmlDomParser::find method
    44             // https://simplehtmldom.sourceforge.io/manual.htm How to find HTML elements? section.
     43            // https://simplehtmldom.sourceforge.io/docs/1.9/manual/finding-html-elements/ How to find HTML elements? section.
    4544            $search_template .= $child_element['searchTemplate'] . ',';
    4645        }
     
    5150            return '';
    5251        }
    53         $elements = $container[0]->find($search_template);
     52        if(count($container)>1){
     53            $elements=[];
     54            foreach ($container as $container_element){
     55                $elements=array_merge($elements,$container_element->find($search_template));
     56            }
     57        }else{
     58            $elements = $container[0]->find($search_template);
     59        }
     60       
    5461        $body = $this->parseContainer($elements);
    5562        return $body ? $body: '';
  • news-parser/trunk/inc/Parser/Modifiers/AdapterModifiers/Before/AddImageSizesModifier.php

    r3023057 r3034684  
    1818function __invoke ($parsed_data,$options)
    1919{
    20     if(!$options['addSrcSetAndSizes']) return $parsed_data;
     20    if(!$options['extraOptions']['addSrcSetAndSizes']) return $parsed_data;
    2121   
    2222    $break_points_array=[480, 768, 1024, 1280, 1440, 1900];
  • news-parser/trunk/inc/Parser/Modifiers/AdapterModifiers/Before/AddSourceModifier.php

    r3023057 r3034684  
    2020function __invoke ($parsed_data,$options)
    2121{
    22     if(!$options['addSource']) return $parsed_data;
     22    if(!$options['extraOptions']['addSource']) return $parsed_data;
    2323    $source_link_caption=(array_key_exists('sourceLinkCaption',$options)&&$options['sourceLinkCaption']!=='')?$options['sourceLinkCaption']:'Source';
    2424    $anchor_rel_attr=(array_key_exists('sourceLinkIsNoFollow',$options)&&$options['sourceLinkIsNoFollow']==true)?'nofollow':'dofollow';
  • news-parser/trunk/inc/Parser/Modifiers/AdapterModifiers/Before/GroupPicturesModifier.php

    r3023057 r3034684  
    1818function __invoke ($parsed_data,$options)
    1919{
    20     if(!$options['groupImagesRow']) return $parsed_data;
     20    if(!$options['extraOptions']['groupImagesRow']) return $parsed_data;
    2121   
    2222    $new_body=[];
  • news-parser/trunk/inc/Parser/Modifiers/AdapterModifiers/Before/RemoveSrcSetAndSizesModifier.php

    r3023057 r3034684  
    1818function __invoke ($parsed_data,$options)
    1919{
    20     if($options['addSrcSetAndSizes']) return $parsed_data;
     20    if($options['extraOptions']['addSrcSetAndSizes']) return $parsed_data;
    2121    $new_body=[];
    2222    foreach($parsed_data['body'] as $element){
  • news-parser/trunk/inc/Parser/Modifiers/PostModifiers/AddPostThumbnailModifier.php

    r3023057 r3034684  
    1717function __invoke ($post,$options)
    1818{
    19     if($options['addFeaturedMedia']) $post->addPostThumbnail();
     19    if($options['extraOptions']['addFeaturedMedia']) $post->addPostThumbnail();
    2020    return $post;
    2121}
  • news-parser/trunk/inc/Service/AI/OpenAIServiceProvider.php

    r3023057 r3034684  
    55use NewsParserPlugin\Exception\MyException;
    66use NewsParserPlugin\Message\Errors;
    7 use NewsParserPlugin\Message\Success;
    87use Orhanerday\OpenAi\OpenAi;
    98
     9class OpenAIServiceProvider
     10{
     11    protected $openAIClient = null;
     12    protected const LOCK_KEY = 'openai_lock';
     13    protected $lockDuration = 34;
     14    public function __construct()
     15    {
     16        if (defined('NEWS_PARSER_OPENAI_API_KEY')) {
     17            $this->openAIClient = $this->getOpenAIClient(NEWS_PARSER_OPENAI_API_KEY);
     18            if (defined('NEWS_PARSER_OPENAI_FREE_TIER')) {
     19                $this->lockDuration = 34;
     20            }
    1021
    11 class OpenAIServiceProvider
    12 {
    13     protected $openAIClient=null;
    14     protected const LOCK_KEY='openai_lock';
    15     protected $lockDuration=0;
    16     public function __construct()
    17     { 
    18         if(defined('NEWS_PARSER_OPENAI_API_KEY')){
    19             $this->openAIClient=$this->getOpenAIClient(NEWS_PARSER_OPENAI_API_KEY);
    20             if (defined('NEWS_PARSER_OPENAI_FREE_TIER')) $this->lockDuration=34;
    2122        }
    2223    }
     
    2728    public function getOptions()
    2829    {
    29         if(!$this->openAIClient) return false;
    30         $responce=json_decode($this->openAIClient->listModels());
     30        if (!$this->openAIClient) {
     31            return false;
     32        }
     33
     34        $responce = json_decode($this->openAIClient->listModels());
    3135        $this->checkResponceStatus();
    32         if(!$responce->data&&!is_array($responce->data)) return false;
    33         $open_ai_models=array_filter($responce->data,function($model){
    34             return strpos($model->id,'gpt')!==false;
     36        if (!$responce->data && !is_array($responce->data)) {
     37            return false;
     38        }
     39
     40        $open_ai_models = array_filter($responce->data, function ($model) {
     41            return strpos($model->id, 'gpt') !== false;
    3542        });
    36         $models_list=array_values(array_map(function($model){
     43        $models_list = array_values(array_map(function ($model) {
    3744            return $model->id;
    38         },$open_ai_models));
    39        return [
    40         'featuredImage' => [
    41             'models'=>['dall-e-2','dall-e-3'],
    42             'generationType'=> ['create','variation'],
    43         ],
    44         'postTitle'=>[
    45             'models'=>$models_list,
    46         ],
    47         'postBody'=>[
    48             'models'=>$models_list,
    49         ],
    50        ];
     45        }, $open_ai_models));
     46        return [
     47            'featuredImage' => [
     48                'models' => ['dall-e-2', 'dall-e-3'],
     49                'generationType' => ['create', 'variation'],
     50            ],
     51            'postTitle' => [
     52                'models' => $models_list,
     53            ],
     54            'postBody' => [
     55                'models' => $models_list,
     56            ],
     57        ];
    5158    }
    52     public function chat($chat_options_array){
    53         if($this->lockDuration!=0) {
    54             $lockAqured=$this->aquireLock();
    55             if($lockAqured){
    56                 while($lockAqured){
    57                     sleep(5);
    58                     $lockAqured=$this->aquireLock();
     59    public function chat($chat_options_array)
     60    {
     61        $counter = 0;
     62        $max_counter = 10;
     63        while (true) {
     64            $responce = json_decode($this->openAIClient->chat($chat_options_array));
     65            if (property_exists($responce, 'error')) {
     66                if ($responce->error->code == 'rate_limit_exceeded') {
     67                    if ($counter >= $max_counter) {
     68                        throw new MyException($responce->error->message, $responce->error->code);
     69                    }
     70                    $counter++;
     71                    sleep($this->lockDuration);
     72                } else {
     73                    throw new MyException($responce->error->message, $responce->error->code);
    5974                }
     75            } else {
     76                return $responce->choices[0]->message->content;
    6077            }
    61             $this->setLock($this->lockDuration);   
    6278        }
    63         $responce=json_decode($this->openAIClient->chat($chat_options_array)); 
    64         if(property_exists($responce,'error')) throw new MyException($responce->error->message, $responce->error->code);     
    65         return $responce->choices[0]->message->content;           
     79       
    6680    }
    6781    public function isAPIKeyDefined()
    6882    {
    69         if(defined('NEWS_PARSER_OPENAI_API_KEY') && NEWS_PARSER_OPENAI_API_KEY!=''){
     83        if (defined('NEWS_PARSER_OPENAI_API_KEY') && NEWS_PARSER_OPENAI_API_KEY != '') {
    7084            return true;
    7185        }
     
    7892    protected function checkResponceStatus()
    7993    {
    80         $request_detatils=$this->openAIClient->getCURLInfo();
    81         if($request_detatils['http_code']!=200) throw new MyException(Errors::text('OPENAI_API_ERROR'), $request_detatils['http_code']);
     94        $request_detatils = $this->openAIClient->getCURLInfo();
     95        if ($request_detatils['http_code'] != 200) {
     96            throw new MyException(Errors::text('OPENAI_API_ERROR'), $request_detatils['http_code']);
     97        }
     98
    8299    }
    83100    protected function aquireLock()
    84101    {
    85         $lock_key=self::LOCK_KEY;
    86         $lock_duration=$this->lockDuration;
    87         $lock=get_transient($lock_key);
     102        $lock_key = self::LOCK_KEY;
     103        $lock_duration = $this->lockDuration;
     104        $lock = get_transient($lock_key);
    88105        return $lock;
    89106    }
    90     protected function setLock($lock_duration){
    91         $lock_key=self::LOCK_KEY;
     107    protected function setLock($lock_duration)
     108    {
     109        $lock_key = self::LOCK_KEY;
    92110        set_transient($lock_key, true, $lock_duration);
    93111    }
    94     protected function releaseLock(){
    95         $lock_key=self::LOCK_KEY;
     112    protected function releaseLock()
     113    {
     114        $lock_key = self::LOCK_KEY;
    96115        delete_transient($lock_key);
    97116    }
    98    
     117
    99118}
  • news-parser/trunk/news-parser.php

    r3023057 r3034684  
    44Plugin URI: https://github.com/zalevsk1y/news-parser
    55Description: Parse full text news from RSS Feed
    6 Version: 2.1.0
     6Version: 2.1.1
    77Author: Evgeny S.Zalevskiy <[email protected]>
    88Author URI: https://github.com/zalevsk1y/
     
    1515
    1616
    17 define('NEWS_PARSER_PLUGIN_VERSION', '2.1.0');
     17define('NEWS_PARSER_PLUGIN_VERSION', '2.1.1');
    1818define ("NEWS_PARSER_PLUGIN_MODE","production");
    1919
  • news-parser/trunk/readme.txt

    r3023057 r3034684  
    77Requires at least: 5.2.0
    88Tested up to: 6.3.1
    9 Stable tag: 2.1.0
     9Stable tag: 2.1.1
    1010License: MIT
    1111License URI: https://opensource.org/licenses/MIT
     
    160160== Changelog ==
    161161
     162= 2.1.1 - 12-02-24 =
     163
     164* Fix: some bugs.
     165
    162166= 2.1.0 - 18-01-24 =
    163167
  • news-parser/trunk/vendor/autoload.php

    r3023057 r3034684  
    2323require_once __DIR__ . '/composer/autoload_real.php';
    2424
    25 return ComposerAutoloaderInitc804c738e2d8a7d63c5cd42310df9bd8::getLoader();
     25return ComposerAutoloaderInit707959137d01bb12ed46c6237dfa5e26::getLoader();
  • news-parser/trunk/vendor/composer/autoload_real.php

    r3023057 r3034684  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInitc804c738e2d8a7d63c5cd42310df9bd8
     5class ComposerAutoloaderInit707959137d01bb12ed46c6237dfa5e26
    66{
    77    private static $loader;
     
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInitc804c738e2d8a7d63c5cd42310df9bd8', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInit707959137d01bb12ed46c6237dfa5e26', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInitc804c738e2d8a7d63c5cd42310df9bd8', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInit707959137d01bb12ed46c6237dfa5e26', 'loadClassLoader'));
    3030
    3131        require __DIR__ . '/autoload_static.php';
    32         call_user_func(\Composer\Autoload\ComposerStaticInitc804c738e2d8a7d63c5cd42310df9bd8::getInitializer($loader));
     32        call_user_func(\Composer\Autoload\ComposerStaticInit707959137d01bb12ed46c6237dfa5e26::getInitializer($loader));
    3333
    3434        $loader->register(true);
  • news-parser/trunk/vendor/composer/autoload_static.php

    r3023057 r3034684  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInitc804c738e2d8a7d63c5cd42310df9bd8
     7class ComposerStaticInit707959137d01bb12ed46c6237dfa5e26
    88{
    99    public static $prefixLengthsPsr4 = array (
     
    4646    {
    4747        return \Closure::bind(function () use ($loader) {
    48             $loader->prefixLengthsPsr4 = ComposerStaticInitc804c738e2d8a7d63c5cd42310df9bd8::$prefixLengthsPsr4;
    49             $loader->prefixDirsPsr4 = ComposerStaticInitc804c738e2d8a7d63c5cd42310df9bd8::$prefixDirsPsr4;
    50             $loader->prefixesPsr0 = ComposerStaticInitc804c738e2d8a7d63c5cd42310df9bd8::$prefixesPsr0;
    51             $loader->classMap = ComposerStaticInitc804c738e2d8a7d63c5cd42310df9bd8::$classMap;
     48            $loader->prefixLengthsPsr4 = ComposerStaticInit707959137d01bb12ed46c6237dfa5e26::$prefixLengthsPsr4;
     49            $loader->prefixDirsPsr4 = ComposerStaticInit707959137d01bb12ed46c6237dfa5e26::$prefixDirsPsr4;
     50            $loader->prefixesPsr0 = ComposerStaticInit707959137d01bb12ed46c6237dfa5e26::$prefixesPsr0;
     51            $loader->classMap = ComposerStaticInit707959137d01bb12ed46c6237dfa5e26::$classMap;
    5252
    5353        }, null, ClassLoader::class);
  • news-parser/trunk/vendor/composer/installed.json

    r3023057 r3034684  
    5757        {
    5858            "name": "orhanerday/open-ai",
    59             "version": "5.0",
    60             "version_normalized": "5.0.0.0",
     59            "version": "5.1",
     60            "version_normalized": "5.1.0.0",
    6161            "source": {
    6262                "type": "git",
    6363                "url": "https://github.com/orhanerday/open-ai.git",
    64                 "reference": "48c94a922318a33dbc15436e8bc086f00d869a4e"
     64                "reference": "386c7f65a50cbfb0fbdbebcd72f7e6c7a6039c84"
    6565            },
    6666            "dist": {
    6767                "type": "zip",
    68                 "url": "https://api.github.com/repos/orhanerday/open-ai/zipball/48c94a922318a33dbc15436e8bc086f00d869a4e",
    69                 "reference": "48c94a922318a33dbc15436e8bc086f00d869a4e",
     68                "url": "https://api.github.com/repos/orhanerday/open-ai/zipball/386c7f65a50cbfb0fbdbebcd72f7e6c7a6039c84",
     69                "reference": "386c7f65a50cbfb0fbdbebcd72f7e6c7a6039c84",
    7070                "shasum": ""
    7171            },
     
    8080                "spatie/ray": "^1.28"
    8181            },
    82             "time": "2023-11-30T06:47:07+00:00",
     82            "time": "2024-01-25T06:43:19+00:00",
    8383            "type": "library",
    8484            "installation-source": "dist",
     
    107107            "support": {
    108108                "issues": "https://github.com/orhanerday/open-ai/issues",
    109                 "source": "https://github.com/orhanerday/open-ai/tree/5.0"
     109                "source": "https://github.com/orhanerday/open-ai/tree/5.1"
    110110            },
    111111            "funding": [
  • news-parser/trunk/vendor/composer/installed.php

    r3023057 r3034684  
    44        'pretty_version' => 'dev-master',
    55        'version' => 'dev-master',
    6         'reference' => '5ae536c2e8ccedbefadffc430758ab0b99f90dd3',
     6        'reference' => '292f668135f8d296c98bb08ff6b4cc2744d39f91',
    77        'type' => 'library',
    88        'install_path' => __DIR__ . '/../../',
     
    2323            'pretty_version' => 'dev-master',
    2424            'version' => 'dev-master',
    25             'reference' => '5ae536c2e8ccedbefadffc430758ab0b99f90dd3',
     25            'reference' => '292f668135f8d296c98bb08ff6b4cc2744d39f91',
    2626            'type' => 'library',
    2727            'install_path' => __DIR__ . '/../../',
     
    3030        ),
    3131        'orhanerday/open-ai' => array(
    32             'pretty_version' => '5.0',
    33             'version' => '5.0.0.0',
    34             'reference' => '48c94a922318a33dbc15436e8bc086f00d869a4e',
     32            'pretty_version' => '5.1',
     33            'version' => '5.1.0.0',
     34            'reference' => '386c7f65a50cbfb0fbdbebcd72f7e6c7a6039c84',
    3535            'type' => 'library',
    3636            'install_path' => __DIR__ . '/../orhanerday/open-ai',
  • news-parser/trunk/vendor/orhanerday/open-ai/README.md

    r3023057 r3034684  
    124124    - [x] [Create embeddings](https://beta.openai.com/docs/api-reference/embeddings/create)
    125125- Audio
     126    - [x] [Text to Speech (TTS)](https://platform.openai.com/docs/guides/text-to-speech)
    126127    - [x] [Create transcription](https://platform.openai.com/docs/api-reference/audio/create)
    127128    - [x] [Create translation](https://platform.openai.com/docs/api-reference/audio/create)
     
    661662## Audio
    662663
     664### Text To Speech (TTS)
     665
     666```php
     667
     668$result = $open_ai->tts([
     669    "model" => "tts-1", // tts-1-hd
     670    "input" => "I'm going to use the stones again. Hey, we'd be going in short-handed, you know",
     671    "voice" => "alloy", // echo, fable, onyx, nova, and shimmer
     672]);
     673
     674// Save audio file
     675file_put_contents('tts-result.mp3', $result);
     676```
     677
    663678### Create Transcription
    664679
  • news-parser/trunk/vendor/orhanerday/open-ai/src/OpenAi.php

    r3023057 r3034684  
    840840
    841841    /**
     842     * @param $opts
     843     * @return bool|string
     844     */
     845    public function tts($opts)
     846    {
     847        $url = Url::ttsUrl();
     848        $this->baseUrl($url);
     849
     850        return $this->sendRequest($url, 'POST', $opts);
     851    }
     852
     853    /**
    842854     * @param  int  $timeout
    843855     */
  • news-parser/trunk/vendor/orhanerday/open-ai/src/Url.php

    r3023057 r3034684  
    179179        return self::OPEN_AI_URL . "/threads";
    180180    }
     181
     182    /**
     183     * @param
     184     * @return string
     185     */
     186    public static function ttsUrl(): string
     187    {
     188        return self::OPEN_AI_URL . "/audio/speech";
     189    }
    181190}
Note: See TracChangeset for help on using the changeset viewer.