Changeset 3034684
- Timestamp:
- 02/12/2024 03:29:42 PM (2 years ago)
- Location:
- news-parser/trunk
- Files:
-
- 17 added
- 29 edited
-
bootstrap.php (modified) (1 diff)
-
inc/Api/Rest/PostApiEndpoint.php (modified) (4 diffs)
-
inc/CLI/InvokeParse.php (modified) (3 diffs)
-
inc/CLI/options.json (added)
-
inc/CLI/posts.json (added)
-
inc/CLI/template.json (added)
-
inc/Config/di-config.php (modified) (1 diff)
-
inc/Config/scripts-config.php (modified) (1 diff)
-
inc/Controller/CronTaskController.php (modified) (1 diff)
-
inc/Controller/ListController.php (modified) (5 diffs)
-
inc/Controller/PostController.php (modified) (6 diffs)
-
inc/Entities/Factory/PostFactory.php (modified) (1 diff)
-
inc/Entities/Post.php (modified) (9 diffs)
-
inc/Models/PostCacheModel.php (modified) (3 diffs)
-
inc/Models/PostModel.php (modified) (5 diffs)
-
inc/Parser/HTMLPatternParser.php (modified) (2 diffs)
-
inc/Parser/Modifiers/AdapterModifiers/Before/AddImageSizesModifier.php (modified) (1 diff)
-
inc/Parser/Modifiers/AdapterModifiers/Before/AddSourceModifier.php (modified) (1 diff)
-
inc/Parser/Modifiers/AdapterModifiers/Before/GroupPicturesModifier.php (modified) (1 diff)
-
inc/Parser/Modifiers/AdapterModifiers/Before/RemoveSrcSetAndSizesModifier.php (modified) (1 diff)
-
inc/Parser/Modifiers/PostModifiers/AddPostThumbnailModifier.php (modified) (1 diff)
-
inc/Service/AI/OpenAIServiceProvider.php (modified) (3 diffs)
-
news-parser.php (modified) (2 diffs)
-
public/css/autopilot-2.1.1.css (added)
-
public/css/parser_page-2.1.1.css (added)
-
public/css/parser_rss-2.1.1.css (added)
-
public/js/384-2.1.1.bundle.js (added)
-
public/js/594-2.1.1.bundle.js (added)
-
public/js/748-2.1.1.bundle.js (added)
-
public/js/748-2.1.1.bundle.js.LICENSE.txt (added)
-
public/js/771-2.1.1.bundle.js (added)
-
public/js/771-2.1.1.bundle.js.LICENSE.txt (added)
-
public/js/autopilot-2.1.1.bundle.js (added)
-
public/js/i18n.js (added)
-
public/js/parser_page-2.1.1.bundle.js (added)
-
public/js/parser_rss-2.1.1.bundle.js (added)
-
readme.txt (modified) (2 diffs)
-
vendor/autoload.php (modified) (1 diff)
-
vendor/composer/autoload_real.php (modified) (2 diffs)
-
vendor/composer/autoload_static.php (modified) (2 diffs)
-
vendor/composer/installed.json (modified) (3 diffs)
-
vendor/composer/installed.php (modified) (3 diffs)
-
vendor/orhanerday/open-ai/README.md (modified) (2 diffs)
-
vendor/orhanerday/open-ai/legal.md (added)
-
vendor/orhanerday/open-ai/src/OpenAi.php (modified) (1 diff)
-
vendor/orhanerday/open-ai/src/Url.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
news-parser/trunk/bootstrap.php
r3023057 r3034684 78 78 $app->event->on('html:get',array(Controller\VisualConstructorController::class,'get')); 79 79 $app->event->on('posts:parse',array(Controller\PostController::class,'parsePost')); 80 $app->event->on('posts:autopilot-parse',array(Controller\PostController::class,'autopilotParsePost')); 80 81 $app->event->on('posts:create',array(Controller\PostController::class,'createPostFromParsedData')); 81 $app->event->on('posts:batch',array(Controller\PostController::class,'batchParsePost'));82 82 $app->event->on('posts:in-progress',array(Controller\PostController::class,'getPostsInProgress')); 83 83 $app->event->on('posts:data',array(Controller\PostController::class,'getPostsData')); -
news-parser/trunk/inc/Api/Rest/PostApiEndpoint.php
r3023057 r3034684 215 215 ) 216 216 )); 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 253 218 $base = 'posts/in-progress'; 254 219 … … 291 256 } 292 257 ), 293 'post Url'=>array(258 'post_id'=>array( 294 259 'description'=>'Parsing page url', 295 260 'type'=>'string', 296 'validate_callback'=>function ($ url) {297 return wp_http_validate_url($url);261 'validate_callback'=>function ($post_id) { 262 return true; 298 263 }, 299 'sanitize_callback'=>function ($ input_url) {300 return esc_url_raw($input_url);264 'sanitize_callback'=>function ($post_id) { 265 return intval($post_id); 301 266 } 302 267 ) … … 343 308 344 309 } 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 360 311 public function postsInProgress($request){ 361 312 try{ … … 374 325 try{ 375 326 $post_params=$request->get_params(); 376 $response=$this->event->trigger('posts:data', array($post_params['templateUrl'],$post_params['post Url']));327 $response=$this->event->trigger('posts:data', array($post_params['templateUrl'],$post_params['post_id'])); 377 328 $response_data=$this->formatResponse()->options($response)->get('array'); 378 329 return $this->sendResponse($response_data); -
news-parser/trunk/inc/CLI/InvokeParse.php
r3023057 r3034684 7 7 class InvokeParse { 8 8 protected $postController; 9 protected $urlErrorMessage='The --post option must be a valid URL.';9 protected $urlErrorMessage='The --posts option must be a valid URL.'; 10 10 protected $templateErrorMessage='The --template option must be a valid URL.'; 11 11 protected $optionsErrorMessage='The --options option must be a valid URL.'; … … 15 15 16 16 public function commandCallback( $args,$assoc_args ) { 17 if(!array_key_exists('post ',$assoc_args)){17 if(!array_key_exists('posts',$assoc_args)){ 18 18 \WP_CLI::log( $this->urlErrorMessage ); 19 19 return ; … … 28 28 } 29 29 30 $url=$assoc_args['post '];30 $url=$assoc_args['posts']; 31 31 if (!$url){ 32 32 \WP_CLI::log( $this->urlErrorMessage ); -
news-parser/trunk/inc/Config/di-config.php
r3023057 r3034684 38 38 Parser\Modifiers\PostModifiers\AddPostThumbnailModifier::class=>[], 39 39 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\Post CacheModel::class],40 Controller\ListController::class=>[Parser\XMLParser::class,Models\PostModel::class], 41 41 Controller\VisualConstructorController::class=>[Parser\HTMLRaw::class], 42 42 Controller\MediaController::class=>[Models\PostModel::class], -
news-parser/trunk/inc/Config/scripts-config.php
r3023057 r3034684 10 10 'global'=>array(), 11 11 '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', 14 14 'depends_on'=>array() 15 15 ), -
news-parser/trunk/inc/Controller/CronTaskController.php
r3023057 r3034684 80 80 if ($cron_data->getParsedPosts() < $cron_data->getMaxPostsParsed()) { 81 81 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())); 83 83 } catch (MyException $e) { 84 84 // ToDo: should add some logging -
news-parser/trunk/inc/Controller/ListController.php
r3023057 r3034684 5 5 use NewsParserPlugin\Message\Errors; 6 6 use NewsParserPlugin\Parser\Abstracts\AbstractParseContent; 7 use NewsParserPlugin\Models\PostCacheModel; 7 use NewsParserPlugin\Models\PostModel; 8 8 9 9 10 /** … … 26 27 */ 27 28 protected $parser; 28 protected $post Cache;29 protected $postModel; 29 30 /** 30 31 * Init function. … … 32 33 * @param AbstractParseContent $parser 33 34 */ 34 public function __construct(AbstractParseContent $parser, Post CacheModel $post_cache)35 public function __construct(AbstractParseContent $parser, PostModel $post_model) 35 36 { 36 37 $this->parser = $parser; 37 $this->post Cache=$post_cache;38 $this->postModel=$post_model; 38 39 } 39 40 /** … … 50 51 throw new MyException(Errors::text('WRONG_LIST_FORMAT'), Errors::code('BAD_REQUEST')); 51 52 } 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); 59 73 },$list_data); 60 74 } … … 91 105 if(!$post) return []; 92 106 return [ 93 'post_id'=>$post ['post_id'],107 'post_id'=>$post->ID, 94 108 'draft'=>[ 95 'editLink'=>$post ['links']['editLink'],109 'editLink'=>$post->links['editLink'], 96 110 ] 97 111 ]; -
news-parser/trunk/inc/Controller/PostController.php
r3023057 r3034684 3 3 namespace NewsParserPlugin\Controller; 4 4 5 use NewsParserPlugin\Entities\Post; 5 6 use NewsParserPlugin\Exception\MyException; 7 use NewsParserPlugin\Interfaces\AdapterInterface; 8 use NewsParserPlugin\Interfaces\ModelInterface; 6 9 use NewsParserPlugin\Message\Errors; 7 use NewsParserPlugin\M essage\Success;10 use NewsParserPlugin\Models\PostCacheModel; 8 11 use NewsParserPlugin\Models\PostModel; 9 12 use NewsParserPlugin\Models\TemplateModel; 10 13 use 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;17 14 18 15 /** … … 26 23 class PostController 27 24 { 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 57 29 /** 58 30 * @var AbstractParseContent Parser object … … 62 34 protected $postModel; 63 35 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) 86 38 { 87 39 $this->adapter = $adapter; 88 40 $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) 130 66 { 131 67 $parsed_url = parse_url($url); … … 133 69 throw new MyException(Errors::text('WRONG_OPTIONS_URL'), Errors::code('BAD_REQUEST')); 134 70 } 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 ]); 144 86 return $parsed_post; 145 } catch(MyException $e){146 $this->post CacheModel->create($this->createCacheErrorMessage($url,$_id,$e),$template_url);87 } catch (MyException $e) { 88 $this->postModel->delete($post_draft->ID); 147 89 throw new MyException($e->getMessage(), $e->getCode()); 148 90 } 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', 189 119 ]); 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); 245 151 // 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 286 165 /** 287 166 * Apply body adapter to parsed data 288 167 */ 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; 294 212 } 295 213 /** … … 300 218 * @throws MyException If no extra options or post options are available. 301 219 */ 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 } 327 234 /** 328 235 * Assign the current user's ID as the author ID … … 330 237 protected function currentUserID() 331 238 { 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 } 428 288 } -
news-parser/trunk/inc/Entities/Factory/PostFactory.php
r3023057 r3034684 22 22 * @return Post The created Post instance. 23 23 */ 24 public function create($ post_array)24 public function create($wp_post,$post_meta) 25 25 { 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))); 27 39 } 28 40 } -
news-parser/trunk/inc/Entities/Post.php
r3023057 r3034684 20 20 * @var string 21 21 */ 22 public $ title;22 public $post_title; 23 23 /** 24 24 * Post content. … … 26 26 * @var string 27 27 */ 28 public $ body;28 public $post_content; 29 29 /** 30 30 * Featured image url. … … 32 32 * @var string|false 33 33 */ 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=[]; 41 44 /** 42 45 * Url of source post. … … 44 47 * @var string|false 45 48 */ 46 public $ sourceUrl;49 public $_source_url; 47 50 /** 48 51 * Id of wordpress post. … … 74 77 { 75 78 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; 81 85 $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; 83 88 $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 84 93 } 85 94 /** … … 92 101 public function addPostThumbnail($image_url = null, $alt = '') 93 102 { 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; 96 105 return $this->attachImageToPostWordpress($url, $this->ID, true, $featured_image_title); 97 106 } … … 104 113 * @return array|string|object 105 114 */ 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') 107 138 { 108 139 $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, 114 147 ); 115 148 $data_json = json_encode($data_array); … … 123 156 } 124 157 } 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 } 125 175 /** 126 176 * Facade function for WP media_sideload_image … … 147 197 return \media_sideload_image($file, $post_id, $desc, $return); 148 198 } 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 } 150 207 /** 151 208 * Download and attach image to WP post -
news-parser/trunk/inc/Models/PostCacheModel.php
r3023057 r3034684 2 2 namespace NewsParserPlugin\Models; 3 3 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; 4 class 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; 15 12 16 13 /** … … 34 31 * 'data' => error data @array 35 32 * ] 36 * 33 * 37 34 * @param string $type Type of cached posts 38 35 * @param string $prefix Prefix of cached posts 39 36 * @return array|mixed 40 37 */ 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) { 43 45 case 'in_progress': 44 $response =get_transient(self::IN_PROGRESS_CACHE_KEY.'-'.$prefix);46 $response = get_transient(self::IN_PROGRESS_CACHE_KEY . '-' . $prefix); 45 47 break; 46 48 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) { 51 53 return []; 52 54 } … … 78 80 * @return void 79 81 */ 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) { 83 90 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)) { 104 112 unset($posts_in_progress[$post['link']]); 105 113 } 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)) { 113 121 return false; 114 122 } 115 if (array_key_exists($id,$posts)){123 if (array_key_exists($id, $posts)) { 116 124 return $posts[$id]; 117 125 } 118 126 return false; 119 127 } 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)) { 124 132 return false; 125 133 } 126 134 return $posts; 127 135 } 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); 136 144 return; 137 145 } 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)) { 141 149 unset($posts[$id]); 142 150 } 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; 159 167 }); 160 168 } 161 169 public function removeErrorPosts($posts) 162 170 { 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); 165 173 }); 166 174 } 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 167 205 } -
news-parser/trunk/inc/Models/PostModel.php
r3023057 r3034684 2 2 namespace NewsParserPlugin\Models; 3 3 4 use NewsParserPlugin\Exception\MyException;5 use NewsParserPlugin\Interfaces\ModelInterface;6 use NewsParserPlugin\Message\Errors;7 4 use NewsParserPlugin\Entities\Factory\PostFactory; 8 5 use NewsParserPlugin\Entities\Post; 6 use NewsParserPlugin\Exception\MyException; 7 use NewsParserPlugin\Message\Errors; 8 use WP_Query; 9 9 10 10 11 /** … … 18 19 */ 19 20 20 class PostModel implements ModelInterface21 class PostModel 21 22 { 23 24 protected $wpID; 22 25 /** 23 26 * The post factory instance. 24 * 27 * 25 28 * @var PostFactory 26 29 */ 27 30 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 } 38 41 /** 39 42 * Create post instance from existed post data. … … 47 50 return false; 48 51 } 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 80 142 if (\is_wp_error($post_id)) { 81 143 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); 86 149 } 87 150 /** … … 92 155 * @return void 93 156 */ 94 public function update( $post_id,$update_data)157 public function update(Post $post) 95 158 { 96 159 $post_array = [ 97 'ID' => $post _id,160 'ID' => $post->ID, 98 161 ]; 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; 100 185 } 101 186 protected function isDataValid($post_data_array) 102 187 { 103 if (!isset($post_data_array['title']) ||empty($post_data_array['title'])) {188 if (!isset($post_data_array['title']) || empty($post_data_array['title'])) { 104 189 throw new MyException(Errors::text('NO_TITLE'), Errors::code('BAD_REQUEST')); 105 190 } 106 if (!isset($post_data_array['body']) ||empty($post_data_array['body'])) {191 if (!isset($post_data_array['body']) || empty($post_data_array['body'])) { 107 192 throw new MyException(Errors::text('NO_BODY'), Errors::code('BAD_REQUEST')); 108 193 } … … 111 196 } 112 197 } 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 } 114 206 } -
news-parser/trunk/inc/Parser/HTMLPatternParser.php
r3023057 r3034684 39 39 } 40 40 $template = $this->options['template']; 41 42 41 foreach ($template['children'] as $child_element) { 43 42 // Create search template for Sunra\HtmlDomParser::find method 44 // https://simplehtmldom.sourceforge.io/ manual.htmHow to find HTML elements? section.43 // https://simplehtmldom.sourceforge.io/docs/1.9/manual/finding-html-elements/ How to find HTML elements? section. 45 44 $search_template .= $child_element['searchTemplate'] . ','; 46 45 } … … 51 50 return ''; 52 51 } 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 54 61 $body = $this->parseContainer($elements); 55 62 return $body ? $body: ''; -
news-parser/trunk/inc/Parser/Modifiers/AdapterModifiers/Before/AddImageSizesModifier.php
r3023057 r3034684 18 18 function __invoke ($parsed_data,$options) 19 19 { 20 if(!$options[' addSrcSetAndSizes']) return $parsed_data;20 if(!$options['extraOptions']['addSrcSetAndSizes']) return $parsed_data; 21 21 22 22 $break_points_array=[480, 768, 1024, 1280, 1440, 1900]; -
news-parser/trunk/inc/Parser/Modifiers/AdapterModifiers/Before/AddSourceModifier.php
r3023057 r3034684 20 20 function __invoke ($parsed_data,$options) 21 21 { 22 if(!$options[' addSource']) return $parsed_data;22 if(!$options['extraOptions']['addSource']) return $parsed_data; 23 23 $source_link_caption=(array_key_exists('sourceLinkCaption',$options)&&$options['sourceLinkCaption']!=='')?$options['sourceLinkCaption']:'Source'; 24 24 $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 18 18 function __invoke ($parsed_data,$options) 19 19 { 20 if(!$options[' groupImagesRow']) return $parsed_data;20 if(!$options['extraOptions']['groupImagesRow']) return $parsed_data; 21 21 22 22 $new_body=[]; -
news-parser/trunk/inc/Parser/Modifiers/AdapterModifiers/Before/RemoveSrcSetAndSizesModifier.php
r3023057 r3034684 18 18 function __invoke ($parsed_data,$options) 19 19 { 20 if($options[' addSrcSetAndSizes']) return $parsed_data;20 if($options['extraOptions']['addSrcSetAndSizes']) return $parsed_data; 21 21 $new_body=[]; 22 22 foreach($parsed_data['body'] as $element){ -
news-parser/trunk/inc/Parser/Modifiers/PostModifiers/AddPostThumbnailModifier.php
r3023057 r3034684 17 17 function __invoke ($post,$options) 18 18 { 19 if($options[' addFeaturedMedia']) $post->addPostThumbnail();19 if($options['extraOptions']['addFeaturedMedia']) $post->addPostThumbnail(); 20 20 return $post; 21 21 } -
news-parser/trunk/inc/Service/AI/OpenAIServiceProvider.php
r3023057 r3034684 5 5 use NewsParserPlugin\Exception\MyException; 6 6 use NewsParserPlugin\Message\Errors; 7 use NewsParserPlugin\Message\Success;8 7 use Orhanerday\OpenAi\OpenAi; 9 8 9 class 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 } 10 21 11 class OpenAIServiceProvider12 {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;21 22 } 22 23 } … … 27 28 public function getOptions() 28 29 { 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()); 31 35 $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; 35 42 }); 36 $models_list =array_values(array_map(function($model){43 $models_list = array_values(array_map(function ($model) { 37 44 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 ]; 51 58 } 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); 59 74 } 75 } else { 76 return $responce->choices[0]->message->content; 60 77 } 61 $this->setLock($this->lockDuration);62 78 } 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 66 80 } 67 81 public function isAPIKeyDefined() 68 82 { 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 != '') { 70 84 return true; 71 85 } … … 78 92 protected function checkResponceStatus() 79 93 { 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 82 99 } 83 100 protected function aquireLock() 84 101 { 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); 88 105 return $lock; 89 106 } 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; 92 110 set_transient($lock_key, true, $lock_duration); 93 111 } 94 protected function releaseLock(){ 95 $lock_key=self::LOCK_KEY; 112 protected function releaseLock() 113 { 114 $lock_key = self::LOCK_KEY; 96 115 delete_transient($lock_key); 97 116 } 98 117 99 118 } -
news-parser/trunk/news-parser.php
r3023057 r3034684 4 4 Plugin URI: https://github.com/zalevsk1y/news-parser 5 5 Description: Parse full text news from RSS Feed 6 Version: 2.1. 06 Version: 2.1.1 7 7 Author: Evgeny S.Zalevskiy <[email protected]> 8 8 Author URI: https://github.com/zalevsk1y/ … … 15 15 16 16 17 define('NEWS_PARSER_PLUGIN_VERSION', '2.1. 0');17 define('NEWS_PARSER_PLUGIN_VERSION', '2.1.1'); 18 18 define ("NEWS_PARSER_PLUGIN_MODE","production"); 19 19 -
news-parser/trunk/readme.txt
r3023057 r3034684 7 7 Requires at least: 5.2.0 8 8 Tested up to: 6.3.1 9 Stable tag: 2.1. 09 Stable tag: 2.1.1 10 10 License: MIT 11 11 License URI: https://opensource.org/licenses/MIT … … 160 160 == Changelog == 161 161 162 = 2.1.1 - 12-02-24 = 163 164 * Fix: some bugs. 165 162 166 = 2.1.0 - 18-01-24 = 163 167 -
news-parser/trunk/vendor/autoload.php
r3023057 r3034684 23 23 require_once __DIR__ . '/composer/autoload_real.php'; 24 24 25 return ComposerAutoloaderInit c804c738e2d8a7d63c5cd42310df9bd8::getLoader();25 return ComposerAutoloaderInit707959137d01bb12ed46c6237dfa5e26::getLoader(); -
news-parser/trunk/vendor/composer/autoload_real.php
r3023057 r3034684 3 3 // autoload_real.php @generated by Composer 4 4 5 class ComposerAutoloaderInit c804c738e2d8a7d63c5cd42310df9bd85 class ComposerAutoloaderInit707959137d01bb12ed46c6237dfa5e26 6 6 { 7 7 private static $loader; … … 25 25 require __DIR__ . '/platform_check.php'; 26 26 27 spl_autoload_register(array('ComposerAutoloaderInit c804c738e2d8a7d63c5cd42310df9bd8', 'loadClassLoader'), true, true);27 spl_autoload_register(array('ComposerAutoloaderInit707959137d01bb12ed46c6237dfa5e26', 'loadClassLoader'), true, true); 28 28 self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); 29 spl_autoload_unregister(array('ComposerAutoloaderInit c804c738e2d8a7d63c5cd42310df9bd8', 'loadClassLoader'));29 spl_autoload_unregister(array('ComposerAutoloaderInit707959137d01bb12ed46c6237dfa5e26', 'loadClassLoader')); 30 30 31 31 require __DIR__ . '/autoload_static.php'; 32 call_user_func(\Composer\Autoload\ComposerStaticInit c804c738e2d8a7d63c5cd42310df9bd8::getInitializer($loader));32 call_user_func(\Composer\Autoload\ComposerStaticInit707959137d01bb12ed46c6237dfa5e26::getInitializer($loader)); 33 33 34 34 $loader->register(true); -
news-parser/trunk/vendor/composer/autoload_static.php
r3023057 r3034684 5 5 namespace Composer\Autoload; 6 6 7 class ComposerStaticInit c804c738e2d8a7d63c5cd42310df9bd87 class ComposerStaticInit707959137d01bb12ed46c6237dfa5e26 8 8 { 9 9 public static $prefixLengthsPsr4 = array ( … … 46 46 { 47 47 return \Closure::bind(function () use ($loader) { 48 $loader->prefixLengthsPsr4 = ComposerStaticInit c804c738e2d8a7d63c5cd42310df9bd8::$prefixLengthsPsr4;49 $loader->prefixDirsPsr4 = ComposerStaticInit c804c738e2d8a7d63c5cd42310df9bd8::$prefixDirsPsr4;50 $loader->prefixesPsr0 = ComposerStaticInit c804c738e2d8a7d63c5cd42310df9bd8::$prefixesPsr0;51 $loader->classMap = ComposerStaticInit c804c738e2d8a7d63c5cd42310df9bd8::$classMap;48 $loader->prefixLengthsPsr4 = ComposerStaticInit707959137d01bb12ed46c6237dfa5e26::$prefixLengthsPsr4; 49 $loader->prefixDirsPsr4 = ComposerStaticInit707959137d01bb12ed46c6237dfa5e26::$prefixDirsPsr4; 50 $loader->prefixesPsr0 = ComposerStaticInit707959137d01bb12ed46c6237dfa5e26::$prefixesPsr0; 51 $loader->classMap = ComposerStaticInit707959137d01bb12ed46c6237dfa5e26::$classMap; 52 52 53 53 }, null, ClassLoader::class); -
news-parser/trunk/vendor/composer/installed.json
r3023057 r3034684 57 57 { 58 58 "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", 61 61 "source": { 62 62 "type": "git", 63 63 "url": "https://github.com/orhanerday/open-ai.git", 64 "reference": " 48c94a922318a33dbc15436e8bc086f00d869a4e"64 "reference": "386c7f65a50cbfb0fbdbebcd72f7e6c7a6039c84" 65 65 }, 66 66 "dist": { 67 67 "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", 70 70 "shasum": "" 71 71 }, … … 80 80 "spatie/ray": "^1.28" 81 81 }, 82 "time": "202 3-11-30T06:47:07+00:00",82 "time": "2024-01-25T06:43:19+00:00", 83 83 "type": "library", 84 84 "installation-source": "dist", … … 107 107 "support": { 108 108 "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" 110 110 }, 111 111 "funding": [ -
news-parser/trunk/vendor/composer/installed.php
r3023057 r3034684 4 4 'pretty_version' => 'dev-master', 5 5 'version' => 'dev-master', 6 'reference' => ' 5ae536c2e8ccedbefadffc430758ab0b99f90dd3',6 'reference' => '292f668135f8d296c98bb08ff6b4cc2744d39f91', 7 7 'type' => 'library', 8 8 'install_path' => __DIR__ . '/../../', … … 23 23 'pretty_version' => 'dev-master', 24 24 'version' => 'dev-master', 25 'reference' => ' 5ae536c2e8ccedbefadffc430758ab0b99f90dd3',25 'reference' => '292f668135f8d296c98bb08ff6b4cc2744d39f91', 26 26 'type' => 'library', 27 27 'install_path' => __DIR__ . '/../../', … … 30 30 ), 31 31 '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', 35 35 'type' => 'library', 36 36 'install_path' => __DIR__ . '/../orhanerday/open-ai', -
news-parser/trunk/vendor/orhanerday/open-ai/README.md
r3023057 r3034684 124 124 - [x] [Create embeddings](https://beta.openai.com/docs/api-reference/embeddings/create) 125 125 - Audio 126 - [x] [Text to Speech (TTS)](https://platform.openai.com/docs/guides/text-to-speech) 126 127 - [x] [Create transcription](https://platform.openai.com/docs/api-reference/audio/create) 127 128 - [x] [Create translation](https://platform.openai.com/docs/api-reference/audio/create) … … 661 662 ## Audio 662 663 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 675 file_put_contents('tts-result.mp3', $result); 676 ``` 677 663 678 ### Create Transcription 664 679 -
news-parser/trunk/vendor/orhanerday/open-ai/src/OpenAi.php
r3023057 r3034684 840 840 841 841 /** 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 /** 842 854 * @param int $timeout 843 855 */ -
news-parser/trunk/vendor/orhanerday/open-ai/src/Url.php
r3023057 r3034684 179 179 return self::OPEN_AI_URL . "/threads"; 180 180 } 181 182 /** 183 * @param 184 * @return string 185 */ 186 public static function ttsUrl(): string 187 { 188 return self::OPEN_AI_URL . "/audio/speech"; 189 } 181 190 }
Note: See TracChangeset
for help on using the changeset viewer.