Plugin Directory

Changeset 2977790


Ignore:
Timestamp:
10/11/2023 06:10:31 PM (2 years ago)
Author:
bikkel
Message:

tagging version 2.0.0

Location:
news-parser
Files:
191 added
38 edited

Legend:

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

    r2265315 r2977790  
    1313    $path = __DIR__ . DIRECTORY_SEPARATOR . 'inc' . DIRECTORY_SEPARATOR . $cl . ".php";
    1414    if (file_exists($path)) {
    15         include $path;
     15        include_once $path;
    1616    }
    1717}
  • news-parser/trunk/inc/Ajax/Ajax.php

    r2265315 r2977790  
    11<?php
    22namespace NewsParserPlugin\Ajax;
     3
     4use NewsParserPlugin\Utils\ResponseFormatter;
    35
    46/**
     
    1113class Ajax
    1214{
     15    protected $formatter;
    1316    /**
    1417     * Checks input argument type.
     
    4750     * validate_callback - validation callback should return boolean
    4851     * sanitize_callback - sanitize input data callback.
    49      * @return void
     52     * @return array
    5053     */
    5154    protected function prepareArgs($dirty_request, $args_params)
     
    5659                $dirty_arg=$dirty_request[$key];
    5760                if (is_wp_error($e = $this->checkArgType($dirty_arg, $arg['type'], $arg['description']))) {
    58                     $this->sendError($e);
     61                    $this->sendError($e->get_error_message(),$e->get_error_code());
    5962                }
    6063                //validate arguments.
    6164                if (is_wp_error($e = call_user_func($arg['validate_callback'], $dirty_arg))) {
    62                     $this->sendError($e);
     65                    $this->sendError($e->get_error_message(),$e->get_error_code());
    6366                }
    6467                //sanitize arguments.
     
    7679     * @return void
    7780     */
    78     protected function sendError($error)
     81    protected function sendError($error_data,$error_code)
    7982    {
    80         if (!is_wp_error($error)) {
    81             return;
    82         }
    83         $response_message=array(
    84             'msg'=>array(
    85                 'type'=>'error',
    86                 'text'=>esc_html($error->get_message())
    87             ),
    88             'code'=>esc_html($error->get_code())
    89         );
    90         wp_send_json($response_message, $error->get_code());
     83        wp_send_json_error($error_data, $error_code);
    9184    }
    9285    /**
     
    9992    protected function sendResponse($response)
    10093    {
    101         switch ($response->contentType) {
    102             case 'json':
    103                 wp_send_json($response->get('array'));
    104                 break;
    105             case 'text':
    106                 echo $response->get('text');
    107                 wp_die();
    108                 break;
    109         }
     94       
     95        wp_send_json($response);
     96               
     97       
    11098    }
    11199
     
    119107        return json_decode(file_get_contents('php://input'), true);
    120108    }
     109    /**
     110     * Get an instance of the response formatter.
     111     *
     112     * @access protected
     113     * @return ResponseFormatter Returns an instance of the ResponseFormatter class.
     114     */
     115
     116    protected function getFormatter()
     117    {
     118       
     119        return new ResponseFormatter();
     120       
     121    }
    121122}
  • news-parser/trunk/inc/Controller/AjaxController.php

    r2265315 r2977790  
    77use NewsParserPlugin\Interfaces\EventControllerInterface;
    88use NewsParserPlugin\Message\Errors;
     9use NewsParserPlugin\Message\Success;
     10use NewsParserPlugin\Exception\MyException;
    911
    1012/**
     
    5860        $this->event=$event;
    5961        $this->init();
     62        $this->formatter=$this->getFormatter();
    6063    }
    6164    /**
     
    106109        }
    107110        return true;
     111    }
     112    protected function sendErrorResponse(MyException $e){
     113        $error_data=$this->formatter->error($e->getCode())->message('error', $e->getMessage())->get('array');
     114        $error_code=$e->getCode();
     115        $this->sendError($error_data,$error_code);
    108116    }
    109117    /**
     
    138146                )
    139147        ));
    140        
    141         $response=$this->event->trigger('media:create', array($request['url'],$request['options']['post_id'],$request['options']['alt']));
    142         $this->sendResponse($response);
    143     }
    144     /**
    145      * Callback that handles options api requests.
    146      *
    147      * @uses ValidateDataTrait::validateExtraOptions()
    148      * @uses ValidateDataTrait::validateTemplate()
    149      * @uses SanitizeDataTrait::sanitizeExtraOptions()
    150      * @uses SanitizeDataTrait::sanitizeTemplate()
    151      * @uses EventController::trigger()
    152      * @return void
    153      */
    154     public function templateApi()
    155     {
    156         //Get application\json encode data
    157         $json_post = $this->getJsonFromInput();
    158         $this->checkPermission('parsing_news_api', $json_post);
    159 
    160         $request=$this->prepareArgs($json_post, array(
    161             'url'=>array(
    162                 'description'=>'Url of post that was taken as example of template',
    163                 'type'=>'string',
    164                 'validate_callback'=>function ($url) {
    165                     return wp_http_validate_url($url);
    166                 },
    167                 'sanitize_callback'=>function ($input_url) {
    168                     return esc_url_raw($input_url);
    169                 }
    170             ),
    171             'extraOptions'=>array(
    172                 'description'=>'Extra options for automated parsing pages',
    173                 'type'=>'array',
    174                 'validate_callback'=>array($this,'validateExtraOptions'),
    175                 'sanitize_callback'=>array($this,'sanitizeExtraOptions')
    176             ),
    177             'template'=>array(
    178                 'description'=>'Template for automate parsing post',
    179                 'type'=>'array',
    180                 'validate_callback'=>array($this,'validateTemplate'),
    181                 'sanitize_callback'=>array($this,'sanitizeTemplate')
    182             )
    183         ));
    184         $options=array(
    185             'extraOptions'=>$request['extraOptions'],
    186             'template'=>$request['template']
    187         );
    188         $response=$this->event->trigger('template:create', array($request['url'],$options));
    189        
    190         $this->sendResponse($response);
    191     }
     148        try {
     149            $media_id=$this->event->trigger('media:create', array($request['url'],$request['options']['post_id'],$request['options']['alt']));
     150            $this->sendResponse($this->formatter->media($media_id)->message('success', Success::text('FEATURED_IMAGE_SAVED'))->get('array'));
     151        } catch (MyException $e) {
     152            $this->sendErrorResponse($e);
     153        }
     154    }
     155   
    192156    /**
    193157     * Callback that handles parsing list of posts from RSS api requests.
     
    216180        ));
    217181       
    218  
    219         $url = $request['url'];
    220 
    221         $response = $this->event->trigger('list:get', array($url));
    222         $this->sendResponse($response);
    223     }
     182
     183        try{
     184            $response = $this->event->trigger('list:get', array($request['url']));
     185            $this->sendResponse($this->formatter->rss($response)->message('success', Success::text('RSS_LIST_PARSED'))->get('array'));
     186        }catch (MyException $e){
     187            $this->sendErrorResponse($e);
     188        }
     189    }
     190   
    224191     /**
    225192     * Callback that handles parsing single page api requests and returns HTML of the page.
     
    247214            )
    248215        ));
    249        
    250          
    251         $url = $request['url'];
    252         $response = $this->event->trigger('html:get', array($url));
    253         $this->sendResponse($response);
     216        $request_url=$request['url'];
     217        try{
     218            $html = $this->event->trigger('html:get', array($request_url));
     219            $response=array(
     220                'html'=>$html,
     221                'url'=>$request_url
     222            );
     223            $this->sendResponse($this->formatter->rawHTML($response)->get('array'));
     224        }catch (MyException $e){
     225            $this->sendErrorResponse($e);
     226        }
     227       
    254228    }
    255229     /**
     
    292266                    return preg_replace('/[^0-9]/i', '', $_id);
    293267                }
    294             )
    295         ));
    296 
    297         $response=$this->event->trigger('post:create', $request);
    298         $this->sendResponse($response);
     268            ),
     269            'templateUrl'=>array(
     270                'description'=>'Url that identifies template',
     271                'type'=>'string',
     272                'validate_callback'=>function ($url) {
     273                    return wp_http_validate_url($url);
     274                },
     275                'sanitize_callback'=>function ($input_url) {
     276                    return esc_url_raw($input_url);
     277                }
     278            ),
     279        ));
     280        try{
     281            $response=$this->event->trigger('post:create', array($request['url'],$request['_id'],$request['templateUrl']));
     282            $this->sendResponse($this->formatter->post($response)->message('success', sprintf(Success::text('POST_SAVED'), $response['title']))->addCustomData('_id', $request['_id'])->get('array'));
     283        } catch (MyException $e) {
     284            $this->sendErrorResponse($e);
     285        }
    299286    }
    300287}
  • news-parser/trunk/inc/Controller/EventController.php

    r2265315 r2977790  
    22namespace NewsParserPlugin\Controller;
    33
    4 use Psr\Container\ContainerInterface;
    54use NewsParserPlugin\Interfaces\EventControllerInterface;
     5use \ContainerBuilder\Interfaces\ContainerInterface as ContainerInterface;
    66
    77/**
     
    1616class EventController implements EventControllerInterface
    1717{
     18
     19     static protected $instance;
    1820    /**
    1921     * Collection of events with controllers.
     
    3436     */
    3537   
    36     public function __construct(ContainerInterface $DIController)
     38    protected function __construct(ContainerInterface $DI_container)
    3739    {
    38         $this->di=$DIController;
     40        $this->di=$DI_container;
     41    }
     42    static public function getInstance($DI_container){
     43        if(!self::$instance){
     44            self::$instance=new self($DI_container);
     45        }
     46        return self::$instance;
    3947    }
    4048    /**
     
    8896        }
    8997        if (!is_array($args)) {
    90             throw new Exception('EventController::trigger() second argument should be an array, but '.gettype($args).' given.');
     98            throw new \Exception('EventController::trigger() second argument should be an array, but '.gettype($args).' given.');
    9199        }
    92100        return $this->di->call($this->eventCollection[$action], $args);
  • news-parser/trunk/inc/Controller/ListController.php

    r2265315 r2977790  
    33
    44use NewsParserPlugin\Exception\MyException;
    5 use NewsParserPlugin\Message\Success;
    65use NewsParserPlugin\Parser\Abstracts\AbstractParseContent;
    7 use NewsParserPlugin\Utils\ResponseFormatter;
    86use NewsParserPlugin\Models\ListModel;
    97
     
    2018 */
    2119
    22 class ListController extends BaseController
     20class ListController
    2321{
    2422    /**
     
    3937     * @param AbstractParseContent $parser
    4038     */
    41     public function __construct(AbstractParseContent $parser, ResponseFormatter $formatter)
     39    public function __construct(AbstractParseContent $parser)
    4240    {
    43         parent::__construct($formatter);
    4441        $this->parser = $parser;
    4542    }
     
    4744     * Get formated list of posts.
    4845     *
    49      * @uses NewsParserPlugin\Controller\BaseController::formatResponse
    50      * @uses NewsParserPlugin\Controller\BaseController::modelsFactory
    51      * @uses NewsParserPlugin\Utils\ResponseFormatter::message()
    52      * @uses NewsParserPlugin\Utils\ResponseFormatter::rss()
    53      * @uses NewsParserPlugin\Utils\ResponseFormatter::error()
    54      * @uses NewsParserPlugin\Utils\ResponseFormatter::get()
    5546     * @uses NewsParserPlugin\Parser\Abstracts\AbstractParseContent::get()
    5647     * @uses NewsParserPlugin\Interfaces\ModelInterface::getAttribute()
    5748     * @param string $url Url of the RSS source.
    58      * @return ResponseFormatter
     49     * @return array
    5950     */
    6051    public function get($url)
    6152    {
    62         try {
    63             $listData = $this->parser->get($url);
    64             $list = $this->listModelFactory($listData);
    65             $response = $this->formatResponse->rss($list->getAttributes())->message('success', Success::text('RSS_LIST_PARSED'));
    66         } catch (MyException $e) {
    67             $response = $this->formatResponse->error($e->getCode())->message('error', $e->getMessage());
    68         }
    69         return $response;
     53       
     54        $listData = $this->parser->get($url);
     55        $list = $this->listModelFactory($listData);   
     56        return $list->getAttributes();
    7057    }
    7158    /**
  • news-parser/trunk/inc/Controller/MediaController.php

    r2265315 r2977790  
    88use NewsParserPlugin\Utils\ResponseFormatter;
    99
    10 class MediaController extends BaseController
     10
     11/**
     12 * Class save media as post attachment
     13 *
     14 * PHP version 5.6
     15 *
     16 *
     17 * @package  Controller
     18 * @author   Evgeniy S.Zalevskiy <[email protected]>
     19 * @license  MIT
     20 *
     21 */
     22class MediaController
    1123{
    12     public function __construct(ResponseFormatter $formatter)
    13     {
    14         parent::__construct($formatter);
    15     }
     24   
    1625    /**
    1726     * Saves attached media.
    1827     *
    19      * @uses NewsParserPlugin\Controller\BaseController::formatResponse
    2028     * @throws MyException
    2129     * @param string $url Url of image that should be download.
    2230     * @param string $post_id Post id.
    2331     * @param string $alt Description of image.
    24      * @return ResponseFormatter
     32     * @return int id of media
    2533     */
    2634    public function create($url, $post_id, $alt = '')
    2735    {
    28         try {
    29             $post=$this->postModelsFactory($post_id);
    30             if (!$post) {
    31                 throw new MyException(Errors::text('WRONG_POST_ID'), Errors::code('BAD_REQUEST'));
    32             }
    33             $media_id=$post->addPostThumbnail($url, $alt);
    34             $response=$this->formatResponse->media($media_id)->message('success', Success::text('FEATURED_IMAGE_SAVED'));
    35         } catch (MyException $e) {
    36             $response = $this->formatResponse->error($e->getCode())->message('error', $e->getMessage());
     36        $this->addFilters();
     37        $post=$this->postModelsFactory($post_id);
     38        if (!$post) {
     39            throw new MyException(Errors::text('WRONG_POST_ID'), Errors::code('BAD_REQUEST'));
    3740        }
    38         return $response;
     41        $media_id=$post->addPostThumbnail($url, $alt);   
     42        return $media_id;
    3943    }
    4044    /**
     
    6064        return $this->create($url, $post_id, $alt);
    6165    }
     66    public function modifyImageSideloadExtension($allowed_extensions,$file)
     67    {
     68        if (is_array($allowed_extensions)) array_push($allowed_extensions,'webp');
     69        return $allowed_extensions;
     70    }
     71    public function modifyUploadMimes($mimes)
     72    {
     73        if (is_array($mimes)) $mimes['webp']='image/webp';
     74        return $mimes;
     75    }
     76    protected function addFilters()
     77    {
     78        add_filter('image_sideload_extensions', array($this,'modifyImageSideloadExtension'), 10, 2);
     79        add_filter('upload_mimes',array($this,'modifyUploadMimes'));
     80    }
    6281}
  • news-parser/trunk/inc/Controller/PostController.php

    r2265315 r2977790  
    11<?php
     2
    23namespace NewsParserPlugin\Controller;
    34
     
    89use NewsParserPlugin\Models\TemplateModel;
    910use NewsParserPlugin\Parser\Abstracts\AbstractParseContent;
    10 use NewsParserPlugin\Utils\ResponseFormatter;
     11use NewsParserPlugin\Interfaces\AdapterInterface;
     12use NewsParserPlugin\Traits\FunctionAutoloadTrait;
     13use NewsParserPlugin\Interfaces\PostControllerInterface;
    1114
    1215/**
    1316 * Class controller for post parsing.
    1417 *
    15  * PHP version 5.6
    16  *
    1718 *
    1819 * @package  Controller
    19  * @author   Evgeniy S.Zalevskiy <[email protected]>
    2020 * @license  MIT
    21  *
    2221 */
    23 class PostController extends BaseController
     22class PostController implements PostControllerInterface
    2423{
    25     /**
    26      * Post model
    27      *
    28      * @var PostModel
     24
     25    /**
     26     * Methods to get function psr-4 like way.
     27     *
     28     * @method loadFunction()
     29     * @method executerCallback()
     30     */
     31    use FunctionAutoloadTrait;
     32    /**
     33     * @var PostModel Post model
    2934     */
    3035    public $post;
    31     /**
    32      * Parsing extra options
    33      *
    34      * @var array
     36    protected $beforeAdapterModifiers;
     37    protected $postModifiers;
     38    /**
     39     * @var array $parsedData Structure:
     40     * [title] - post title @string
     41     * [image] - post main image url @string
     42     * [body] - post content @string|@array
     43     * [sourceUrl] - url of source page @string
     44     * [authorId] - id of wp-post author
     45     */
     46    protected $parsedData;
     47
     48    /**
     49     * @var array Parsing extra options
    3550     */
    3651    protected $options;
    37     /**
    38      * Parser object
    39      *
    40      * @var AbstractParseContent
     52
     53    /**
     54     * @var AbstractParseContent Parser object
    4155     */
    4256    protected $parser;
    4357
    4458    /**
    45      * Init function
    46      *
    47      * @param AbstractParseContent $parser
    48      * @param ResponseFormatter $formatter
    49      */
    50     public function __construct(AbstractParseContent $parser, ResponseFormatter $formatter)
    51     {
    52         parent::__construct($formatter);
     59     * Class Constructor.
     60     *
     61     * Initializes the class instance.
     62     *
     63     * @param AbstractParseContent $parser Parser instance for parsing content.
     64     * @param AdapterInterface $adapter Adapter instance that converts array of body elements data.
     65     * @param array $before_adapter_modifiers (optional) Associative array of modifiers to be applied before the adapter conversion. The format is as follows:
     66     *   [
     67     *     'option_id' => [
     68     *          'path_to_true_modifier_function',
     69     *          'path_to_false_modifier_function'
     70     *         ],
     71     *          ...
     72     *         ]
     73     * The 'option_id' is the identifier of the option.
     74     * 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.
     75     * 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.
     76     * @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.
     77     */
     78
     79    public function __construct(AbstractParseContent $parser, AdapterInterface $adapter,array $before_adapter_modifiers=[],array $post_modifiers=[])
     80    {
     81        $this->adapter = $adapter;
    5382        $this->parser = $parser;
    54     }
     83        $this->beforeAdapterModifiers=$before_adapter_modifiers;
     84        $this->postModifiers=$post_modifiers;
     85    }
     86
    5587    /**
    5688     * Create post draft and return response in proper format
    5789     *
    58      * @uses NewsParserPlugin\Controller\BaseController::formatResponse
    59      * @param string $url of post that should be parsed and saved as draft
    60      * @param string $_id front end index of post that should be parsed and saved as draft
    61      * @return ResponseFormatter
    62      */
    63     public function create($url, $_id)
    64     {
    65         try {
    66             $parsed_url=parse_url($url);
    67             if (!is_array($parsed_url)) {
    68                 throw new MyException(Errors::text('WRONG_OPTIONS_URL'), Errors::code('BAD_REQUEST'));
     90     * @param string $url URL of post that should be parsed and saved as draft.
     91     * @param string $_id Front-end index of post that should be parsed and saved as draft.
     92     * @param string $template_url Object with parameters for WP post.
     93     * @return array
     94     * @throws MyException
     95     */
     96    public function create($url, $_id, $template_url = false)
     97    {
     98        $parsed_url = parse_url($url);
     99        if (!is_array($parsed_url)) {
     100            throw new MyException(Errors::text('WRONG_OPTIONS_URL'), Errors::code('BAD_REQUEST'));
     101        }
     102        $post_options_model = $this->getPostOptionsModel($template_url);
     103        $this->parsedData = $this->parser->get($url, $post_options_model->getAttributes('array'));
     104       
     105        $this->assignAuthorId();
     106       
     107        // Unescaped URL
     108        $this->assignSourceUrl($url);
     109        $this->checkParsedData();
     110        $this->applyBeforAdapterModifiers();
     111        // Apply adapter to adapt parsed body of the post to editor or make changes according to options
     112        $this->applyBodyAdapter();
     113       
     114        // Get post model
     115        $this->post =  $this->postModelsFactory();
     116        $this->createPost();
     117
     118        // Apply modifiers to post according to template post options
     119        $this->applyPostModifiers();
     120
     121        return $this->post->getAttributes();
     122    }
     123    /**
     124     * Retrieves the parsed data associated with the PostController.
     125     *
     126     * This method returns the parsed data stored in the PostController object.
     127     *
     128     * @return array The parsed data associated with the PostController.
     129     */
     130
     131    public function getParsedData()
     132    {
     133        return $this->parsedData;
     134    }
     135    /**
     136     * Updates the body array in the parsed data of the PostController.
     137     *
     138     * This method takes an array of body elements and updates the 'body' key in the parsed data of the PostController with the provided array.
     139     *
     140     * @param array $body_array The array of body elements to update the parsed data with.
     141     * @return void
     142     */
     143
     144    public function updateParsedDataBody(array $body_array)
     145    {
     146        $this->parsedData['body']=$body_array;
     147    }
     148    /**
     149     * Apply body adapter to parsed data
     150     */
     151    protected function applyBodyAdapter()
     152    {
     153        $pre_adapted_body = \apply_filters('news_parser_filter_pre_adapter', $this->parsedData['body']);
     154        $post_adapter_body = $this->adapter->convert($pre_adapted_body);
     155        $this->parsedData['body'] = \apply_filters('news_parser_filter_post_adapter', $post_adapter_body);
     156    }
     157    /**
     158     * Add modifiers to the adapter.
     159     *
     160     * The modifiers array should be in the following format:
     161     *
     162     * [
     163     *    'option_id' => [
     164     *        'path_to_true_modifier_function',
     165     *        'path_to_false_modifier_function'
     166     *    ],
     167     *    ...
     168     * ]
     169     *
     170     * The 'option_id' is the identifier of the option.
     171     * 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.
     172     * 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. If a false modifier is not provided, it can be set as null.
     173     *
     174     * beforOptions - modifiers will be run without options check
     175     * options - modifiers will run conditional according post options state
     176     * Syntax Example:
     177     * $modifiers_array = [
     178     * 'beforOptions'=>['Namespace\Modifiers\Modifier'...]
     179     * 'options'=>[
     180     *    'option1' => [
     181     *        'Namespace\Modifiers\TrueModifier',
     182     *        'Namespace\Modifiers\FalseModifier'
     183     *    ],
     184     *    'option2' => [
     185     *        'Namespace\Modifiers\AnotherTrueModifier',
     186     *        null
     187     *    ],
     188     *    ...
     189     * ]
     190     * ];
     191     *
     192     * @return void
     193     */
     194
     195    protected function applyBeforAdapterModifiers()
     196    {
     197        //beforeAll modifiers executes before all others
     198        if(array_key_exists('beforeOptions',$this->beforeAdapterModifiers)&&is_array($this->beforeAdapterModifiers['beforeOptions'])){
     199            foreach($this->beforeAdapterModifiers['beforeOptions'] as $modifier_function){
     200                $this->executerCallback($this,$modifier_function);
    69201            }
    70             $parsing_options=$this->templateModelsFactory($parsed_url);
    71             $parsed_data =$this->parser->get($url, $parsing_options->getAttributes('array'));
    72            
    73             $parsed_data['authorId'] = \get_current_user_id();
    74             if (!$options=$parsing_options->getExtraOptions()) {
    75                 throw new MyException(Errors::text('NO_EXTRA_OPTIONS'), Errors::code('BAD_REQUEST'));
     202        }
     203        if(!array_key_exists('options',$this->beforeAdapterModifiers)) return null;
     204        foreach ($this->beforeAdapterModifiers['options'] as $option_id=>$modifier_function){
     205            if(array_key_exists($option_id,$this->options)&&$this->options[$option_id])
     206            {
     207                $this->executerCallback($this,$modifier_function[0]);
     208
     209            }else if($modifier_function[1]!==null){
     210                $this->executerCallback($this,$modifier_function[1]);
    76211            }
    77             $this->options=$options;
    78             //unescaped url
    79 
    80             $parsed_data['sourceUrl'] = $url;
    81          
    82             $this->post=$post= $this->postModelsFactory($parsed_data);
    83  
    84             //Stages of post draw creating
    85             $this->createDraft($post)->addSource($post)->addPostThumbnail($post);
    86                
    87 
    88             $response = $this->formatResponse->post($post->getAttributes())->addCustomData('_id', $_id)->message('success', sprintf(Success::text('POST_SAVED_AS_DRAFT'), $post->title));
    89         } catch (MyException $e) {
    90             $response = $this->formatResponse->error($e->getCode())->message('error', $e->getMessage())->addCustomData('_id', $_id);
    91         }
    92         return $response;
    93     }
    94    
    95     /**
    96      * Create WP post draft
    97      *
    98      * @param PostModel $post
    99      * @return PostController
    100      */
    101     protected function createDraft(PostModel $post)
    102     {
    103         $post->createDraft();
     212        }
     213    }
     214    /**
     215     * Apply post modifiers to the adapter.
     216     *
     217     * The `executerCallback` function is a trait that allows executing a function by given path in a PSR-4 like way.
     218     *
     219     * The modifiers array should be in the following format:
     220     *
     221     * [
     222     *    'option_id' => [
     223     *        'path_to_true_modifier_function',
     224     *        'path_to_false_modifier_function'
     225     *    ],
     226     *    ...
     227     * ]
     228     *
     229     * The 'option_id' is the identifier of the option.
     230     * 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.
     231     * 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.
     232     *
     233     * Syntax Example:
     234     * $modifiers_array = [
     235     *    'option1' => [
     236     *        'Namespace\Modifiers\TrueModifier',
     237     *        'Namespace\Modifiers\FalseModifier'
     238     *    ],
     239     *    'option2' => [
     240     *        'Namespace\Modifiers\AnotherTrueModifier',
     241     *        'Namespace\Modifiers\AnotherFalseModifier'
     242     *    ],
     243     *    ...
     244     * ];
     245     *
     246     * @return void
     247     */
     248
     249    protected function applyPostModifiers()
     250    {
     251        foreach ($this->postModifiers as $option_id=>$modifier_function){
     252            if(array_key_exists($option_id,$this->options)&&$this->options[$option_id])
     253            {
     254                $this->executerCallback($this->post,$modifier_function[0]);
     255
     256            } else if ($modifier_function[1]!==null)
     257            {
     258                $this->executerCallback($this->post,$modifier_function[1]);
     259            }
     260        }
     261    }
     262    /**
     263     * Get the post options model based on the given options ID
     264     *
     265     * @param string $options_id ID of the template options.
     266     * @return TemplateModel
     267     * @throws MyException
     268     */
     269    protected function getPostOptionsModel($options_id)
     270    {
     271        $options_model = $this->templateModelsFactory($options_id);
     272        if (!$options = $options_model->getExtraOptions()) {
     273            throw new MyException(Errors::text('NO_EXTRA_OPTIONS'), Errors::code('BAD_REQUEST'));
     274        }
     275        $this->options = $options;
     276        return $options_model;
     277    }
     278
     279    /**
     280     * Assign the current user's ID as the author ID
     281     */
     282    protected function assignAuthorId()
     283    {
     284        $this->parsedData['authorId'] = apply_filters('news_parser_filter_author_id', \get_current_user_id());
     285    }
     286
     287    /**
     288     * Assign the source URL to the parsed data
     289     *
     290     * @param string $url Source URL to assign.
     291     */
     292    protected function assignSourceUrl($url)
     293    {
     294        $this->parsedData['sourceUrl'] = $url;
     295    }
     296
     297    /**
     298     * Create a WP post
     299     */
     300    protected function createPost()
     301    {
     302        $this->post->createPost();
     303    }
     304
     305    /**
     306     * Add the main image to the post
     307     */
     308    protected function addPostThumbnail()
     309    {
     310        if ($this->options['addFeaturedMedia']) {
     311            $this->post->addPostThumbnail();
     312        }
    104313        return $this;
    105314    }
    106     /**
    107      * Add main image to the post
    108      *
    109      * @param PostModel $post
    110      * @return PostController
    111      */
    112     protected function addPostThumbnail(PostModel $post)
    113     {
    114         if ($this->options['addFeaturedMedia']) {
    115             $post->addPostThumbnail();
     315
     316    /**
     317     * Add the link to the source
     318     */
     319    protected function addSource()
     320    {
     321        if ($this->options['addSource']) {
     322            $this->post->addSource();
    116323        }
    117324        return $this;
    118325    }
    119     /**
    120      * Add link to the source
    121      *
    122      * @param PostModel $post
    123      * @return PostController
    124      */
    125     protected function addSource(PostModel $post)
    126     {
    127         if ($this->options['addSource']) {
    128             $post->addSource();
    129         }
    130         return $this;
    131     }
    132    /**
    133     * Get instance of PostModel class.
    134     *
    135     * @param array $data Structure:
    136     * [title] - post title @string
    137     * [image] - post main image url @string
    138     * [body] - post content @string|@array
    139     * [sourceUrl]-url of source page @string
    140     * [authorId]- id of wp-post author
    141     * @return PostModel
    142     */
    143     protected function postModelsFactory($data)
    144     {
    145         return new PostModel($data);
    146     }
    147     /**
    148     * Get instance of TemplateModel class.
    149     *
    150     * @param array $url Structure:
    151     * [scheme] - protocol
    152     * [host] - host name
    153     * [path] - path to resource
    154     * [fragment] - path fragment
    155     * @return TemplateModel
    156     */
     326
     327    /**
     328     * Get an instance of the PostModel class.
     329     *
     330     * @return PostModel
     331     */
     332    protected function postModelsFactory()
     333    {
     334        return new PostModel($this->parsedData);
     335    }
     336
     337    /**
     338     * Get an instance of the TemplateModel class.
     339     *
     340     * @param array $url Structure:
     341     * [scheme] - protocol
     342     * [host] - host name
     343     * [path] - path to resource
     344     * [fragment] - path fragment
     345     * @return TemplateModel
     346     */
    157347    protected function templateModelsFactory($url)
    158348    {
    159349        return new TemplateModel($url['host']);
    160350    }
     351    /**
     352     * Check parsed data for required fields.
     353     *
     354     * @throws MyException When any of the required fields are missing or empty.
     355     * @return void
     356     */
     357
     358    protected function checkParsedData()
     359    {
     360        if(!array_key_exists('title',$this->parsedData)||empty($this->parsedData['title'])){
     361            throw new MyException(Errors::text('NO_TITLE'),Errors::code('INNER_ERROR'));
     362        }
     363        if(!array_key_exists('body',$this->parsedData)||empty($this->parsedData['body'])){
     364            throw new MyException(Errors::text('NO_BODY'),Errors::code('INNER_ERROR'));
     365        }
     366        if(!array_key_exists('authorId',$this->parsedData)||empty($this->parsedData['authorId'])){
     367            throw new MyException(Errors::text('NO_AUTHOR'),Errors::code('INNER_ERROR'));
     368        }
     369        if(!array_key_exists('sourceUrl',$this->parsedData)||empty($this->parsedData['sourceUrl'])){
     370            throw new MyException(Errors::text('NO_POST_URL'),Errors::code('INNER_ERROR'));
     371        }
     372        if(!array_key_exists('image',$this->parsedData)||empty($this->parsedData['image'])){
     373            if($this->options['addFeaturedMedia']){
     374                throw new MyException(Errors::text('NO_IMAGE'),Errors::code('INNER_ERROR'));
     375            }
     376        }
     377    }
     378
    161379}
  • news-parser/trunk/inc/Controller/TemplateController.php

    r2265315 r2977790  
    33
    44use NewsParserPlugin\Exception\MyException;
    5 use NewsParserPlugin\Utils\ResponseFormatter;
    65use NewsParserPlugin\Message\Errors;
    76use NewsParserPlugin\Message\Success;
    8 use NewsParserPlugin\Models\TemplateModel;
     7use NewsParserPlugin\Models\TemplateModelWithPostOptions as TemplateModel;
     8use NewsParserPlugin\Utils\ResponseFormatter;
    99
    1010/**
     11 * Class TemplateController
     12 *
    1113 * Class saves received options.
    1214 *
    13  * PHP version 5.6
    14  *
    15  *
    16  * @package  Controller
    17  * @author   Evgeniy S.Zalevskiy <[email protected]>
    18  * @license  MIT
    19  *
     15 * @package NewsParserPlugin\Controller
    2016 */
     17class TemplateController
     18{
     19    protected const TEMPLATE_TABLE_NAME = NEWS_PURSER_PLUGIN_TEMPLATE_OPTIONS_NAME;
    2120
    22 class TemplateController extends BaseController
    23 {
    24 
    25     /**
    26      * Init function.
    27      *
    28      */
    29     public function __construct(ResponseFormatter $formatter)
    30     {
    31         parent::__construct($formatter);
    32     }
    3321    /**
    3422     * Save received options.
    3523     *
    36      * @uses NewsParserPlugin\Controller\BaseController::formatResponse
    37      * @uses NewsParserPlugin\Controller\BaseController::modelsFactory
    38      * @uses NewsParserPlugin\Utils\ResponseFormatter::message()
    39      * @uses NewsParserPlugin\Utils\ResponseFormatter::error()
    40      * @uses NewsParserPlugin\Utils\ResponseFormatter::get()
    41      * @uses NewsParserPlugin\Models\TemplateModel::save()
    42      * @param string $url
    43      * @param array $options
    44      * @return ResponseFormatter
     24     * @param array $options The received options.
     25     * @return TemplateModel  created template model.
    4526     */
    46     public function create($url, $options)
     27    public function create($options)
    4728    {
    48         $parsed_url=parse_url($url);
    49         try {
    50             if (!is_array($parsed_url)) {
    51                 throw new MyException(Errors::text('WRONG_OPTIONS_URL'), Errors::code('BAD_REQUEST'));
    52             }
    53             $TemplateModel=$this->modelsFactory($parsed_url);
    54             $TemplateModel->save($options);
    55             $response=$this->formatResponse->message('success', Success::text('TEMPLATE_SAVED'));
    56         } catch (MyException $e) {
    57             $response = $this->formatResponse->error($e->getCode())->message('error', $e->getMessage());
     29        /**
     30         * @var TemplateModel $template_model
     31         */
     32        $template_model = $this->modelsFactory($options);
     33        $template_model->create();
     34        return $template_model->getAttributes('array');
     35    }
     36
     37    /**
     38     * Get template by URL.
     39     *
     40     * @param string $url The URL of the template.
     41     * @return array|false The array of  template model attributes if found, false otherwise.
     42     */
     43    public function get($url)
     44    {
     45        $template_model=$this->findByUrl($url);
     46        return $template_model!==false?$template_model->getAttributes('array'):$template_model;
     47    }
     48
     49    /**
     50     * Get all template keys.
     51     *
     52     * @return array The array of template keys.
     53     */
     54    public function templateKeys()
     55    {
     56        return array_keys($this->getAll());
     57    }
     58
     59    /**
     60     * Delete template by URL.
     61     *
     62     * @param string $url The URL of the template to delete.
     63     * @return void
     64     */
     65    public function delete($url)
     66    {
     67        $template = $this->findByUrl($url);
     68        if ($template) {
     69            $template->delete();
    5870        }
    59         return $response;
     71        return $this->templateKeys();
    6072    }
    61      /**
    62     * Get instance of TemplateModel class.
    63     *
    64     * @param array $url Structure:
    65     * [scheme] - protocol
    66     * [host] - host name
    67     * [path] - path to resource
    68     * [fragment] - path fragment
    69     * @return TemplateModel
    70     */
    71     protected function modelsFactory($url)
     73
     74    /**
     75     * Get all templates.
     76     *
     77     * @return array The array of templates.
     78     */
     79    protected function getAll()
    7280    {
    73         return new TemplateModel($url['host']);
     81        if (!$templates = $this->getOption(self::TEMPLATE_TABLE_NAME)) {
     82            return [];
     83        }
     84        return json_decode(json_encode($templates),true);
     85    }
     86
     87    /**
     88     * Get instance of TemplateModel class.
     89     *
     90     * @param array $template_options The template options.
     91     * @return TemplateModel The instance of TemplateModel class.
     92     */
     93    protected function modelsFactory($template_options)
     94    {
     95        $template_model = new TemplateModel($template_options);
     96        return $template_model;
     97    }
     98
     99    /**
     100     * Find template by URL.
     101     *
     102     * @param string $url The URL of the template.
     103     * @return TemplateModel|false The template model if found, false otherwise.
     104     */
     105    protected function findByUrl($url)
     106    {
     107        $templates = $this->getAll();
     108        if (array_key_exists($url, $templates)) {
     109            return $this->modelsFactory($templates[$url]);
     110        }
     111        return false;
     112    }
     113
     114    /**
     115     * Get option by key.
     116     *
     117     * @param string $key The option key.
     118     * @return mixed The option value.
     119     */
     120    protected function getOption($key)
     121    {
     122        return get_option($key);
    74123    }
    75124}
  • news-parser/trunk/inc/Controller/VisualConstructorController.php

    r2265315 r2977790  
    66use NewsParserPlugin\Message\Errors;
    77use NewsParserPlugin\Message\Success;
    8 use NewsParserPlugin\Utils\ResponseFormatter;
    98use NewsParserPlugin\Models\PostModel;
    109
     
    2120 */
    2221
    23 class VisualConstructorController extends BaseController
     22class VisualConstructorController
    2423{
    2524    /**
     
    3332     *
    3433     * @param AbstractParseContent $parser
    35      * @param ResponseFormatter $formatter
    3634     */
    37     public function __construct(AbstractParseContent $parser, ResponseFormatter $formatter)
     35    public function __construct(AbstractParseContent $parser)
    3836    {
    39         parent::__construct($formatter);
    4037        $this->parser=$parser;
    4138    }
     
    4340     * Parse raw html data of the page.
    4441     *
    45      * @uses NewsParserPlugin\Controller\BaseController::formatResponse
    4642     * @param string $url Url of the page.
    4743     * @param array $options Array of options.
    48      * @return ResponseFormatter
     44     * @return array|string
    4945     */
    5046    public function get($url, $options = array())
    5147    {
    52         try {
    53             $html_data=$this->parser->get($url, $options);
    54             $response=$this->formatResponse->rawHTML($html_data);
    55         } catch (MyException $e) {
    56             $response = $this->formatResponse->error($e->getCode())->message('error', $e->getMessage());
    57         }
    58         return $response;
     48        $html_data=$this->parser->get($url, $options);   
     49        return $html_data;
    5950    }
    6051    /**
     
    6354     * @param string $url Url of the page.
    6455     * @param array $options Array of options.
    65      * @return string
     56     * @return array|string
    6657     */
    6758    public function __invoke($url, $options)
  • news-parser/trunk/inc/Message/Errors.php

    r2265315 r2977790  
    2121                return \__('Template could not be saved right now.', NEWS_PARSER_PLUGIN_SLUG);
    2222            case 'NO_TEMPLATE':
    23                 return \__('Post could not be parsed, because there is no template for that kind of posts.', NEWS_PARSER_PLUGIN_SLUG);
     23                return \__('There is no template for that kind of posts.', NEWS_PARSER_PLUGIN_SLUG);
    2424            case 'NO_EXTRA_OPTIONS':
    2525                return \__('Post could not be parsed, because there is no parsing options for that kind of posts.', NEWS_PARSER_PLUGIN_SLUG);
     26            case 'NO_POST_OPTIONS':
     27                return \__('Post could not be parsed, because there is no post options for that kind of posts.', NEWS_PARSER_PLUGIN_SLUG);
    2628            case 'FILE_DOWNLOAD':
    2729                return \__('Sorry file cannot be downloaded', NEWS_PARSER_PLUGIN_SLUG);
     
    3941                return \__('Some program error has occurred', NEWS_PARSER_PLUGIN_SLUG);
    4042            case 'NO_TITLE':
    41                 return \__('No Title', NEWS_PARSER_PLUGIN_SLUG);
     43                return \__('Parsing error.Parsed post has no "Title".', NEWS_PARSER_PLUGIN_SLUG);
    4244            case 'NO_BODY':
    43                 return \__('No Body', NEWS_PARSER_PLUGIN_SLUG);
     45                return \__('Parsing error.Parsed post has no "Body"', NEWS_PARSER_PLUGIN_SLUG);
     46            case 'NO_AUTHOR':
     47                return \__('No Author ID was set to parsed post', NEWS_PARSER_PLUGIN_SLUG);
     48            case 'NO_POST_URL':
     49                return \__('No source URL was set to parsed post', NEWS_PARSER_PLUGIN_SLUG);
     50            case 'NO_IMAGE':
     51                return \__('Parsing error.No post image URL was set to parsed post', NEWS_PARSER_PLUGIN_SLUG);
    4452            case 'SETTINGS_CANNOT_BE_SAVED':
    4553                return \__('Sorry temporary settings cannot be saved', NEWS_PARSER_PLUGIN_SLUG);
    4654            case 'OPTIONS_WRONG_FORMAT':
    4755                return \__('Options could not be saved.Wrong options format.', NEWS_PARSER_PLUGIN_SLUG);
     56            case 'NO_DI_DEFENITION_FILE':
     57                    return \__('File with class defenitions for DI container could not be found. Check file path.', NEWS_PARSER_PLUGIN_SLUG);
     58            case 'DI_DEFENITION_FILE_WRONG_ORDER':
     59                    return \__('In dependency defenition file wrong depandency oreder.Dependencies should be placed earlier in array', NEWS_PARSER_PLUGIN_SLUG);   
     60            case 'NO_NEEDED_DEPENDENCY_IN_DEFENITION':
     61                    return \__('No needed dependency in defenition file.', NEWS_PARSER_PLUGIN_SLUG);       
     62            case 'WRONG_DEFENITION_FILE_FORMAT':
     63                    return \__('Defenition file should be array.', NEWS_PARSER_PLUGIN_SLUG);
     64            case 'NO_CRON':
     65                return \__('Cron is not configured', NEWS_PARSER_PLUGIN_SLUG);   
     66            case 'NO_RIGHTS_TO_PUBLISH':
     67                return \__('You have no rights to get, create or modify this type of content.');       
     68                   
    4869        }
    4970    }
     
    5374            case 'BAD_REQUEST':
    5475                return '400 Bad Request';
     76            case 'INNER_ERROR':
     77                return '500 Inner Error';
     78            case 'UNSUPPORTED_MEDIA_TYPE';
     79                return '415 Unsupported Media Type';
     80            case 'CONTENT_NOT_FOUND':
     81                return '404 Content Not Found';
     82            case 'NO_CONTENT':
     83                return '204 No Content';
    5584        }
    5685    }
  • news-parser/trunk/inc/Message/Success.php

    r2265315 r2977790  
    1818            case 'RSS_LIST_PARSED':
    1919                return  \__('XML File successfully parsed.', 'news-parser');
    20             case 'POST_SAVED_AS_DRAFT':
    21                 return \__('Post "%s" was successfully parsed and saved as "draft"', 'news-parser');
     20            case 'POST_SAVED':
     21                return \__('Post "%s" was successfully parsed and saved.', 'news-parser');
    2222            case 'TEMPLATE_SAVED':
    2323                return \__('Options was saved successful.', 'news-parser');
     24            case 'TEMPLATE_EXIST':
     25                return \__('You have parsing template for this RSS thread.', 'news-parser');
    2426            case 'FEATURED_IMAGE_SAVED':
    2527                return \__('Featured image was saved and attach to the post.', 'news-parser');
     28            case 'CRON_EXIST':
     29                return \__('Cron job options already exist.', 'news-parser');
     30                case 'CRON_CREATED':
     31                    return \__('Cron job options successfully created.', 'news-parser');
     32                case 'CRON_DELETED':
     33                    return \__('Cron job options successfully deleted.', 'news-parser');
     34           
    2635        }
    2736    }
  • news-parser/trunk/inc/Models/PostModel.php

    r2265315 r2977790  
    3333     * Featured image url.
    3434     *
    35      * @var string
     35     * @var string|false
    3636     */
    3737    public $image;
     
    4545     * Url of source post.
    4646     *
    47      * @var string
     47     * @var string|false
    4848     */
    4949    public $sourceUrl;
     
    8484        }
    8585        $this->body = $data['body'];
    86         if (!isset($data['authorId'])||empty($data['authorId'])) {
     86        if (!isset($data['authorId'])) {
    8787            throw new MyException(Errors::text('NO_AUTHOR'), Errors::code('BAD_REQUEST'));
    8888        }
     
    118118    }
    119119    /**
    120      * Create wordpress draft gets WP post ID and change postModel status to draft
    121      *
    122      * @return void
    123      */
    124     public function createDraft()
    125     {
    126         $this->ID = $this->createPostWordPress();
    127         if ($this->ID === 0) {
    128             throw new MyException(Errors::text('POST_WAS_NOT_CREATED'), Errors::code('BAD_REQUEST'));
    129         }
     120     * Create wordpress post, gets WP post ID.
     121     *
     122     * @param array $post_data Array with wp post attributes  https://developer.wordpress.org/reference/functions/wp_insert_post/
     123     * @return void
     124     */
     125    public function createPost($post_data=[])
     126    {
     127        $this->ID = $this->createPostWordPress($post_data);
    130128        $this->getPostLinksWordpress();
    131         $this->status = 'draft';
     129        if(array_key_exists('post_status',$post_data)) $this->status = $post_data['post_status'];
    132130    }
    133131    /**
     
    196194    public function mediaSideloadImage($file, $post_id = 0, $desc = null, $return = 'html')
    197195    {
    198         return media_sideload_image($file, $post_id, $desc, $return);
     196        if(function_exists('media_sideload_image')){
     197            return \media_sideload_image($file, $post_id, $desc, $return);
     198        }
     199        /** WordPress Administration File API */
     200        require_once ABSPATH . 'wp-admin/includes/file.php';
     201
     202        /** WordPress Image Administration API */
     203        require_once ABSPATH . 'wp-admin/includes/image.php';
     204
     205        /** WordPress Media Administration API */
     206        require_once ABSPATH . 'wp-admin/includes/media.php';
     207        return \media_sideload_image($file, $post_id, $desc, $return);
    199208    }
    200209    /**
    201210     * Create wordpress post
    202211     *
     212     * @param array $post_user_data Array with wp post attributes  https://developer.wordpress.org/reference/functions/wp_insert_post/
    203213     * @return int Post iD
    204214     */
    205     protected function createPostWordPress()
    206     {
    207         $date = new \DateTime();
    208         $post_date = $date->format('Y-m-d H:i:s');
    209         $post_data = array(
     215    protected function createPostWordPress($post_user_data)
     216    {
     217
     218        $post_initial_data = array(
    210219            'post_title' => \wp_strip_all_tags($this->title),
    211220            'post_content' => $this->body,
    212             'post_date' => $post_date,
    213221            'post_author' => $this->authorId,
    214 
    215         );
     222        );
     223        if(!is_array($post_user_data))$post_user_data=[];
     224        $post_data=array_merge($post_initial_data,$post_user_data);
    216225        $postId = \wp_insert_post($post_data);
    217226        if (\is_wp_error($postId)) {
     
    227236     * @param int $id post ID in WP
    228237     * @param boolean $post_thumb if image will use NewsParserPlugin\as main image of the post
    229      * @return int image ID
    230      */
    231     protected function attachImageToPostWordpress($image, $id, $post_thumb = false, $alt = '')
     238     * @param int $max_attempt counts of downloads attempts
     239     * @return WP_Error|string  image ID
     240     */
     241    protected function attachImageToPostWordpress($image, $id, $post_thumb = false, $alt = '',$max_attempt=3)
    232242    {
    233243        $url = $image;
    234244        $post_id = $id;
    235245        $desc = $alt?:"image";
    236         $img_id = $this->mediaSideloadImage($url, $post_id, $desc, 'id');
     246        for ($attempt = 0;$attempt<$max_attempt;$attempt++){
     247            $img_id = $this->mediaSideloadImage($url, $post_id, $desc, 'id');
     248            if(!\is_wp_error($img_id)) break;
     249        }
    237250        if (\is_wp_error($img_id)) {
    238251            throw new MyException($img_id->get_error_message().' Image url:'.esc_url_raw($url), Errors::code('BAD_REQUEST'));
     
    249262     *
    250263     * @param string $update_item name of updated field
    251      * @param $data new data that will be add to the field
     264     * @param mixed $data new data that will be add to the field
    252265     * @return void
    253266     */
  • news-parser/trunk/inc/Models/TemplateModel.php

    r2265315 r2977790  
    77
    88/**
    9  * Class operates with parsing options.
     9 * Class TemplateModel
    1010 *
    11  * PHP version 5.6
     11 * This class represents a model that operates with parsing options.
    1212 *
    1313 * @package  Models
    14  * @author   Evgeniy S.Zalevskiy <[email protected]>
    1514 * @license  MIT
    1615 */
    1716
     17
    1818class TemplateModel implements ModelInterface
    1919{
    2020    /**
     21     * The name of the template table.
     22     */
     23
     24    protected const TEMPLATE_TABLE_NAME = NEWS_PURSER_PLUGIN_TEMPLATE_OPTIONS_NAME;
     25    /**
    2126     * Url of resource that will be source of the posts feed.
    2227     *
     
    2732     * Extra options
    2833     * Structure:
     34     * [addSrcSetAndSizes] - bool - add sizes attribute with image sizes breakpoints
     35     * [groupImagesRow] - bool - Groups images in Guttenberg group by two and arrange them in a row
    2936     * [addFeaturedMedia]- bool- Add featured media to the post.
    3037     * [addSource] -bool - Add link to the source page to th end of the post.
     
    5562     * init function
    5663     *
    57      * @param string $url Url of resource that will be source of the posts feed.
    58      */
    59     public function __construct($url)
    60     {
    61         $this->resourceUrl=$url;
    62         $this->hash=sha1($this->resourceUrl);
    63         if ($options=$this->get()) {
    64             $this->assignOptions($options);
    65         };
     64     * @param array of template optrions.
     65     * [url]
     66     * [template]
     67     * [extraOptions]
     68     */
     69    public function __construct(array $template_data)
     70    {
     71        if (!$this->isOptionsValid($template_data)) {
     72            throw new MyException(Errors::text('OPTIONS_WRONG_FORMAT'), Errors::code('BAD_REQUEST'));
     73        }
     74        $this->assignOptions($template_data);
    6675    }
    6776    /**
     
    7281     * @return boolean
    7382     */
    74     public function save($options)
    75     {
    76         if (!isset($options['extraOptions'])||!isset($options['template'])) {
    77             throw new MyException(Errors::text('OPTIONS_WRONG_FORMAT'), Errors::code('BAD_REQUEST'));
    78         }
    79         $data=array(
    80             'extraOptions'=>$options['extraOptions'],
    81             'template'=>$options['template']
    82         );
    83         $result=update_option($this->hash, $data, '', 'no');
    84         if ($result) {
    85             $this->assignOptions($data);
    86         }
    87         return $result;
     83    public function create()
     84    {
     85        $templates=$this->getAll();
     86        $template_data=$this->getAttributes('array');
     87        if(!is_array($templates)) $templates=[];
     88        $templates[$this->resourceUrl]=$template_data;
     89        return $this->updateOptions(self::TEMPLATE_TABLE_NAME, $templates, 'no');
     90    }
     91    /**
     92     * Update options using wp function update_option.
     93     *
     94     * @param string $key The option key.
     95     * @param mixed $data The option data.
     96     * @param string|null $autoload Optional. Whether to load the option when WordPress starts up ('yes' or 'no').
     97     *
     98     * @return bool Returns true if the options were successfully updated, false otherwise.
     99     */
     100
     101    public function update()
     102    {
     103        $templates=$this->getAll();
     104        if(array_key_exists($this->resourceUrl,$templates)){
     105            return $this->updateOptions(self::TEMPLATE_TABLE_NAME, $templates, 'no');
     106        }
     107        return false;
     108    }
     109    /**
     110     * Delete options using wp function update_option.
     111     *
     112     * @return bool Returns true if the options were successfully deleted, false otherwise.
     113     */
     114
     115    public function delete (){
     116        $templates=$this->getAll();
     117        if(array_key_exists($this->resourceUrl,$templates)){
     118            unset($templates[$this->resourceUrl]);
     119            return $this->updateOptions(self::TEMPLATE_TABLE_NAME, $templates, 'no');
     120        }
     121        return false;
     122    }
     123    protected function updateOptions($key,$data,$autoload=null)
     124    {
     125        return update_option($key, $data, $autoload);
    88126    }
    89127    /**
     
    92130     * @return boolean
    93131     */
    94     public function delete()
    95     {
    96         return delete_option($this->hash);
     132    public static function deleteAll()
     133    {
     134        return delete_option(self::TEMPLATE_TABLE_NAME);
    97135    }
    98136    /**
     
    101139     * @return false|array
    102140     */
    103     protected function get()
    104     {
    105         return get_option($this->hash);
     141    protected function getAll()
     142    {
     143        return get_option(self::TEMPLATE_TABLE_NAME);
    106144    }
    107145    /**
     
    122160    {
    123161        return isset($this->extraOptions)?$this->extraOptions:false;
    124     }/**
     162    }
     163    /**
     164     * Check if the options have a valid format.
     165     *
     166     * @param array $options The options to validate.
     167     *
     168     * @return bool Returns true if the options have a valid format, false otherwise.
     169     */
     170
     171    protected function isOptionsValid($options)
     172    {
     173        if(!isset($options['extraOptions'])||
     174        !isset($options['template'])||
     175        !isset($options['url'])){
     176            return false;
     177        }
     178        return true;
     179    }
     180    /**
    125181     * Assign options to object properties.
    126182     *
     
    130186    protected function assignOptions($options)
    131187    {
     188        $this->resourceUrl=$options['url'];
    132189        $this->parseTemplate=$options['template'];
    133190        $this->extraOptions=$options['extraOptions'];
    134191    }
    135192    /**
    136      * Get all options in needed format.
     193     * Get all options in needed format. If no options found return Exception.
    137194     *
    138195     * @throws MyException if there is no options for that url.
     
    142199    public function getAttributes($format)
    143200    {
    144         if (!isset($this->extraOptions)||!isset($this->parseTemplate)) {
    145             throw new MyException(Errors::text('NO_TEMPLATE'), Errors::code('BAD_REQUEST'));
    146         }
     201       return $this->formatAttributes($format);
     202    }
     203    /**
     204     * Return options data in proper format.
     205     *
     206     * @param string $format accept array|object|json.
     207     * @return array|object|string
     208     */
     209    protected function formatAttributes($format)
     210    {
    147211        $data=array(
     212            'url'=>$this->resourceUrl,
    148213            'extraOptions'=>$this->extraOptions,
    149214            'template'=>$this->parseTemplate
  • news-parser/trunk/inc/Parser/Abstracts/AbstractParseContent.php

    r2265315 r2977790  
    66use NewsParserPlugin\Utils\Pipe;
    77use NewsParserPlugin\Utils\Chain;
     8use NewsParserPlugin\Models\TemplateModel;
    89
    910/**
     
    3334     */
    3435    protected $options;
    35 
     36   
     37    protected $url;
    3638    /**
    3739     * @param integer $cache_expiration
     
    8789        $data = $this->wpRemoteGet($url, $request_args);
    8890        if (is_wp_error($data)) {
    89             throw new MyException(Errors::text('FILE_DOWNLOAD'), Errors::code('BAD_REQUEST'));
     91            $error_code=$data->get_error_code();
     92            $error_message=$data->get_error_message($error_code);
     93                throw new MyException(Errors::text('FILE_DOWNLOAD'), Errors::code('INNER_ERROR'));
    9094        }
    9195        $response_code= wp_remote_retrieve_response_code($data);
    9296        if ($response_code!=200) {
    93             throw new MyException(Errors::text('FILE_DOWNLOAD'), Errors::code('BAD_REQUEST'));
     97            throw new MyException(Errors::text('FILE_DOWNLOAD'), Errors::code('INNER_ERROR'));
    9498        }
    9599        $body=wp_remote_retrieve_body($data);
     
    100104     *
    101105     * @param string $url url of the page that should get.
    102      * @param array $options Extra options that might be used by parser.
     106     * @param TemplateModel $options Extra options that might be used by parser.
    103107     * @return array|stdClass|string Parsed data.
    104108     */
    105     public function get($url, $options = array())
     109    public function get($url, $options=array())
    106110    {
    107         if (!empty($options)) {
    108             $this->options=$options;
    109         }
     111        $this->url=$url;
     112       
     113        $this->options=$options;
     114       
    110115        $data = $this->getFromCache($url);
    111116        if (gettype($data)==='string') {
  • news-parser/trunk/inc/Parser/HTMLPatternParser.php

    r2265315 r2977790  
    33
    44use NewsParserPlugin\Parser\HTMLParser;
    5 use NewsParserPlugin\Interfaces\AdapterInterface;
    65
    76/**
    8  * Parse html using pre saved template pattern.
     7 * Class HTMLPatternParser
    98 *
    10  * PHP version 5.6
     9 * Parse HTML using pre-saved template pattern.
    1110 *
    12  * @package Parser
    13  * @author  Evgeniy S.Zalevskiy <[email protected]>
    14  * @license MIT
     11 * @package NewsParserPlugin\Parser
    1512 */
    16 
    1713class HTMLPatternParser extends HTMLParser
    1814{
    1915
    20     /**
    21      * Class that provide methods that convert array body data to string for post model
    22      * using gutenberg editor blocks markup.
    23      *
    24      * @var AdapterInterface
    25      * @method convert array of body elements data.
    26      */
    27     protected $adapter;
    2816
    2917    /**
    30      * Init function.
     18     * HTMLPatternParser constructor.
    3119     *
    32      * @param integer $cache_expiration cache expiration time.
     20     * @param int              $cache_expiration  Cache expiration time in seconds.
    3321     */
    34     public function __construct(AdapterInterface $adapter, $cache_expiration = 3600)
     22    public function __construct($cache_expiration = 3600)
    3523    {
    3624        parent::__construct($cache_expiration);
    37         $this->adapter=$adapter;
    3825    }
     26
    3927    /**
    40      * Parse post body
     28     * Parse post body.
    4129     *
    42      * @uses AdapterInterface::convert() convert array of elements into string.
    43      * @return string data that would be saved as post content.
     30     *
     31     * @return string Data that would be saved as the post content.
     32     * @throws \Exception If parsing template patterns are not set.
    4433     */
    45 
    4634    public function postBody()
    4735    {
    48         $search_template='';
     36        $search_template = '';
    4937        if (!isset($this->options['template'])) {
    5038            throw new \Exception('Parsing template patterns should be set.');
    5139        }
    52         $template=$this->options['template'];
    53        
     40        $template = $this->options['template'];
     41
    5442        foreach ($template['children'] as $child_element) {
    55             //Create search template for Sunra\HtmlDomParser::find method
    56             //https://simplehtmldom.sourceforge.io/manual.htm How to find HTML elements? section.
    57             $search_template.=$child_element['searchTemplate'].',';
     43            // Create search template for Sunra\HtmlDomParser::find method
     44            // https://simplehtmldom.sourceforge.io/manual.htm How to find HTML elements? section.
     45            $search_template .= $child_element['searchTemplate'] . ',';
    5846        }
    59         $search_template=substr($search_template, 0, -1);
    60         $container=$this->find($template['searchTemplate']);
     47        $search_template = substr($search_template, 0, -1);
     48        $container = $this->find($template['searchTemplate']);
    6149
    6250        if (empty($container)) {
    6351            return '';
    6452        }
    65         $elements=$container[0]->find($search_template);
    66         $body=$this->parseContainer($elements);
    67        
    68        
    69         return $body ? $this->adapter->convert($body):'';
     53        $elements = $container[0]->find($search_template);
     54        $body = $this->parseContainer($elements);
     55        return $body ? $body: '';
    7056    }
     57
    7158    /**
    72      * Iterate over array of HtmlDomParser elements and parse data.
     59     * Iterate over an array of HtmlDomParser elements and parse data.
    7360     *
    74      * @param array $elements array of HtmlDomParser elements objects
     61     * @param array $elements Array of HtmlDomParser element objects.
     62     *
    7563     * @return array ['tagName'=>string,'content'=>string|array]
    7664     */
    7765    protected function parseContainer($elements)
    7866    {
    79         $body=array();
     67        $body = array();
    8068        foreach ($elements as $el) {
    81             $el_tag=$el->tag;
    82                 $el_data=array(
    83                     'tagName'=>$el_tag,
    84                 );
    85                 switch ($el_tag) {
    86                     case 'img':
    87                     //If element is image content element will be type of array.
    88                         $el_data['content']=array(
    89                             'alt'=>$el->alt,
    90                             //if lazy load attribute data-src exists take that as source of image if none take src attribute.
    91                             'src'=>(is_array($el->attr)&&array_key_exists('data-src', $el->attr))?$el->attr['data-src']:$el->src
    92                         );
     69            $el_tag = $el->tag;
     70            $el_data = array(
     71                'tagName' => $el_tag,
     72            );
     73            switch ($el_tag) {
     74                case 'img':
     75                    if (!$this->isImageFitToContext($el)) {
    9376                        break;
    94                     case 'ul':
    95                         //if element is list content element will be type of array.
    96                         $el_data['content']=array();
    97                         foreach ($el->find('li') as $li) {
    98                             $el_data['content'][]=$this->removeTags($li->innertext);
    99                         }
    100                         break;
    101                     case 'iframe':
    102                         //find youtube video ID.
    103                         preg_match('/youtube\.com\/embed\/([a-zA-Z0-9\_]*)/i', $el->src, $match);
    104                         //remove any symbols except that is allowed.
    105                         $el_data['content']=array_key_exists(1, $match)?$match[1]:false;
    106                         break;
    107                     default:
    108                         $el_data['content']=$this->removeTags(trim($el->innertext));
     77                    }
     78                    $image_srcset = $this->parseSourceImageTag($el);
     79                    // If the element is an image, the content will be of type array.
     80                    $el_data['content'] = array(
     81                        'alt' => $el->alt,
     82                        // If the lazy load attribute data-src exists, take that as the source of the image. If none, take the src attribute.
     83                        'src' => $image_srcset !== false ? $this->srcSetSplit($image_srcset) : ((is_array($el->attr) && array_key_exists('data-src', $el->attr)) ? $this->srcSetSplit($el->attr['data-src']) : $el->src),
     84                        'srcSet' => $image_srcset!==false ? $image_srcset : '',
     85                        'sizes'=>''
     86                    );
     87                    break;
     88                case 'ul':
     89                    // If the element is a list, the content will be of type array.
     90                    $el_data['content'] = array();
     91                    foreach ($el->find('li') as $li) {
     92                        $el_data['content'][] = $this->removeTags($li->innertext);
     93                    }
     94                    break;
     95                case 'iframe':
     96                    // Find the YouTube video ID.
     97                    preg_match('/youtube\.com\/embed\/([a-zA-Z0-9\_]*)/i', $el->src, $match);
     98                    // Remove any symbols except those that are allowed.
     99                    $el_data['content'] = array_key_exists(1, $match) ? $match[1] : false;
     100                    break;
     101                default:
     102                    $el_data['content'] = $this->removeTags(trim($el->innertext));
     103            }
     104            if (array_key_exists('content', $el_data) && $el_data['content'] !== false) {
     105                $body[] = $el_data;
     106            }
     107        }
     108
     109        return $body;
     110    }
     111
     112    /**
     113     * Parse the source image tag.
     114     *
     115     * @param \simple_html_dom_node $image_element Image element.
     116     *
     117     * @return bool|string Source set attribute value, or false if not found.
     118     */
     119    protected function parseSourceImageTag($image_element)
     120    {
     121        // Check if the element has a parent picture
     122        if ($image_element->parent->tag == 'picture') {
     123            // Get child elements of the picture tag
     124            $children_elements = $image_element->parent->children;
     125            foreach ($children_elements as $child_element) {
     126                if ($child_element->tag == 'source') {
     127                    if (array_key_exists('srcset', $child_element->attr)) {
     128                        return $child_element->attr['srcset'];
     129                    }
     130                    if (array_key_exists('data-srcset', $child_element->attr)) {
     131                        return $child_element->attr['data-srcset'];
     132                    }
    109133                }
    110                 if ($el_data['content']!==false) {
    111                     $body[]=$el_data;
    112                 }
    113         };
    114             return $body;
     134            }
     135        }
     136
     137        return false;
     138    }
     139
     140    /**
     141     * Split the srcset string and return the last element.
     142     *
     143     * @param string $srcSetString The srcset string.
     144     *
     145     * @return string The last element of the srcset array.
     146     */
     147    protected function srcSetSplit($srcSetString)
     148    {
     149        // Split the string into an array using ',' as the separator
     150        $array = explode(',', $srcSetString);
     151
     152        // Iterate over each element in the array
     153        foreach ($array as &$element) {
     154            // Remove the part of the string that is separated by a space
     155            $parts = explode(' ', trim($element));
     156            $element = $parts[0];
     157        }
     158
     159        return end($array);
     160    }
     161
     162    /**
     163     * Check if the image fits the content based on keywords form the post title.
     164     *
     165     * @param \simple_html_dom_node $image_element Image element.
     166     *
     167     * @return bool Whether the image fits the content based on keywords.
     168     */
     169    protected function isImageFitToContext($image_element)
     170    {
     171        $pattern = '/\b(Or|And|It|Is|Are|Was|Were|Then|There|Here|If|Could|,|\.)\b/';
     172        $replacement = '';
     173        $keywords = preg_split('/\s+/', trim(preg_replace($pattern, $replacement, $this->post['title'])));
     174        $image_alt = array_key_exists('alt', $image_element->attr) ? $image_element->attr['alt'] : '';
     175        foreach ($keywords as $keyword) {
     176            if (stripos($image_alt, $keyword) !== false) {
     177                return true;
     178            }
     179        }
     180        return false;
    115181    }
    116182}
  • news-parser/trunk/inc/Parser/HTMLRaw.php

    r2265315 r2977790  
    2323    public function __construct($cache_expiration = 600)
    2424    {
     25        $this->url='http://site.com';
    2526        parent::__construct($cache_expiration);
    2627    }
     
    3334    protected function parse($data)
    3435    {
     36       
     37        $data=apply_filters('htmlRaw:parse',array($data,$this->url));
     38       
    3539        if (is_array($this->options)&&array_key_exists('remove_scripts', $this->options)&&$this->options['remove_scripts']) {
    3640            return $this->removeScriptTags($data);
  • news-parser/trunk/inc/Parser/XMLParser.php

    r2265315 r2977790  
    3939     *
    4040     * @param string $xml
    41      * @return array of StdClass
     41     * @return object of StdClass
    4242     *
    4343     */
     
    6666        if (!empty($errors)) {
    6767            libxml_clear_errors();
    68             throw new MyException(Errors::text('XML_PARSING'), Errors::code('BAD_REQUEST'));
     68            throw new MyException(Errors::text('XML_PARSING'), Errors::code('UNSUPPORTED_MEDIA_TYPE'));
    6969        }
    7070
     
    8484     * @param \SimpleXMLElement $data object created by simplexml_load_string() function;
    8585     *
    86      * @return object parsed data
     86     * @return array|array<mixed,object> parsed data
    8787     */
    8888    protected function formatData($data)
     
    218218     * Parse image from description using regular expression
    219219     *
    220      * @param $text text of description
     220     * @param string $text text of description
    221221     * @return string|false
    222222     */
     
    234234     *
    235235     * @param \SimpleXMLElement $xml
    236      * @return void
     236     * @return string|false
    237237     */
    238238    public function parseImageMediaTag($xml)
  • news-parser/trunk/inc/Traits/SanitizeDataTrait.php

    r2265315 r2977790  
    4040                case 'saveParsingTemplate':
    4141                case 'addSource':
     42                case 'addSrcSetAndSizes':
     43                case 'groupImagesRow':
    4244                //use json_decode to prevent "false" string converted to boolean true
    4345                    $clean_data[$key]=boolval(json_decode($option));
     
    5153    }
    5254    /**
    53      * Sanitize template pattern array.
     55     * Sanitize  HTML template pattern array.
    5456     *
    5557     * @param array $template ['tagName','className','searchTemplate','children']
    5658     * @return array
    5759     */
    58     public function sanitizeTemplate($template)
     60    public function sanitizeHTMLtemplate($html_template)
    5961    {
    60         $clean_data=$this->sanitizeTemplateElement($template);
     62        $clean_data=$this->sanitizeTemplateElement($html_template);
    6163        $clean_data['children']=array();
    62         foreach ($template['children'] as $child) {
     64        foreach ($html_template['children'] as $child) {
    6365            array_push($clean_data['children'], $this->sanitizeTemplateElement($child));
    6466        }
    6567        return $clean_data;
     68    }
     69    public function sanitizeTemplate($template)
     70    {
     71        return $clean_data=array(
     72            'template'=>$this->sanitizeHTMLtemplate($template['template']),
     73            'extraOptions'=>$this->sanitizeExtraOptions($template['extraOptions']),
     74            'url'=>\esc_url($template['url']),
     75            'postOptions'=>$this->sanitizePostOptions($template['postOptions'])
     76        );
     77    }
     78    protected function sanitizePostOptions($post_options){
     79        //ToDo: Implement post options sanitizing
     80        return $post_options;
    6681    }
    6782    /**
     
    6984     *
    7085     * @param array $el  ['tagName','className','searchTemplate','position']
    71      * @return void
     86     * @return array
    7287     */
    7388    protected function sanitizeTemplateElement($el)
     
    91106        return $clean_data;
    92107    }
     108    public function sanitizeInteger($value){
     109        return intval($value);
     110    }
     111    /**
     112     * @return array
     113     */
     114    public function sanitizeCronOptions($option){
     115        $clean_data=array();
     116        $clean_data['maxCronCalls']=intval($option['maxCronCalls']);
     117        $clean_data['maxCronCalls']=$clean_data['maxCronCalls']>100?100:$clean_data['maxCronCalls'];
     118        $clean_data['maxPostsParsed']=intval($option['maxPostsParsed']);
     119        $clean_data['maxPostsParsed']=$clean_data['maxPostsParsed']>100?100:$clean_data['maxCronCalls'];
     120        $clean_data['interval']=preg_replace('/[^h,o,u,r,l,y,t,w,i,c,e,d,a,k]/i','',$option['interval']);
     121        return $clean_data;
     122    }
    93123}
  • news-parser/trunk/inc/Traits/ValidateDataTrait.php

    r2265315 r2977790  
    3131    public function validateImageUrl($input_url)
    3232    {
    33         $filetype=wp_check_filetype($input_url);
     33        $imageFileTypes = array(
     34            'jpg|jpeg' => 'image/jpeg',
     35            'png' => 'image/png',
     36            'gif' => 'image/gif',
     37            'bmp' => 'image/bmp',
     38            'svg' => 'image/svg+xml',
     39            'webp' => 'image/webp',
     40            'ico' => 'image/x-icon'
     41        );
     42       
     43        $filetype=wp_check_filetype($input_url,$imageFileTypes);
    3444        $mime_type=$filetype['type'];
    3545        if (false!==strpos($mime_type, 'image')) {
    3646            return true;
    3747        }
    38         return new \WP_Error(400, 'Given url is not a valid image url.URL:'.esc_url_raw($input_url));
     48        return new \WP_Error(400, 'Given url is not a valid image url.URL: '.esc_url_raw($input_url));
    3949    }
    4050    /**
     
    5565        return true;
    5666    }
     67
    5768    /**
    5869     * Validate structure of input extra options.
     
    6677        $extra_option_should_have_keys=array(
    6778            'addSource',
     79            'groupImagesRow',
    6880            'addFeaturedMedia',
    69             'saveParsingTemplate'
     81            'addSrcSetAndSizes'
    7082        );
    7183   
     
    7991     * @return true|/WP_Error
    8092     */
    81     public function validateTemplate($template)
     93    public function validateHTMLTemplate($html_template)
    8294    {
    8395        $container_should_have_keys=array(
     
    89101        $child_should_have_keys=array_slice($container_should_have_keys, 0, -2);
    90102        array_push($child_should_have_keys, 'position');
    91         if (!$this->checkArrayKeys($container_should_have_keys, $template)) {
     103        if (!$this->checkArrayKeys($container_should_have_keys, $html_template)) {
    92104            return false;
    93105        }
    94         if (!is_array($template['children'])) {
     106        if (!is_array($html_template['children'])) {
    95107            return new \WP_Error(400, 'Template patterns array should have children section.');
    96108        }
    97         foreach ($template['children'] as $child) {
     109        foreach ($html_template['children'] as $child) {
    98110            if (is_wp_error($result = $this->checkArrayKeys($child_should_have_keys, $child))) {
    99111                return $result;
     
    119131        return new \WP_Error(400, 'No needed parameters in extraOptions parsing options array.Missing keys:'.implode(',', $has_difference));
    120132    }
     133    public function validateTemplate($template){
     134        $template_should_have_keys=array(
     135            'url',
     136            'extraOptions',
     137            'template',
     138            'postOptions'
     139        );
     140        if (!$this->checkArrayKeys($template_should_have_keys, $template)) {
     141            return false;
     142        }
     143        return $this->validateExtraOptions($template['extraOptions'])&&$this->validateHTMLTemplate($template['template']);
     144    }
    121145}
  • news-parser/trunk/inc/Utils/Pipe.php

    r2265315 r2977790  
    6767        return $this;
    6868    }
     69    /**
     70     * @return \NewsParserPlugin\Utils\Pipe
     71     */
    6972    protected function callFunc($function_name, $args)
    7073    {
  • news-parser/trunk/inc/Utils/ResponseFormatter.php

    r2265315 r2977790  
    11<?php
    22namespace NewsParserPlugin\Utils;
     3
    34
    45/**
     
    1314 */
    1415
    15 class ResponseFormatter
    16 {
     16class ResponseFormatter {
    1717
    1818    /**
     
    2727     * @var array
    2828     */
    29     protected $data=array('code'=>200,'msg'=>false);
    30     /**
    31      * Return new instance of ResponseFormatter
    32      *
    33      * @return ResponseFormatter
    34      */
    35     public static function getInstance()
    36     {
    37         return new static();
    38     }
     29    protected $data=array();
    3930    /**
    4031     * Format answer after post draw was created
     
    7263    public function dialog($type, $data)
    7364    {
    74         $this->data['dialog']=array(
     65        $this->data['data']=array(
    7566            'type'=>$type,
    76             'data'=>$data
     67            'dialogData'=>$data
    7768        );
    7869            return $this;
     
    125116       
    126117        if ($status=='none') {
    127             $this->data['msg']=false;
     118            $this->data['message']=false;
    128119        } else {
    129             $this->data['msg']=array(
     120            $this->data['message']=array(
    130121           
    131122                    'type'=>esc_html($status),
     
    135126            );
    136127        }
     128        return $this;
     129    }
     130    /**
     131     * Template options
     132     *
     133     * @param string $options array of template-options
     134     * @return ResponseFormatter return this for chain building
     135     */
     136    public function options($options)
     137    {
     138        $this->data['data']=$options;
    137139        return $this;
    138140    }
     
    150152        $this->data['data'][$escaped_field_name]=$escaped_value;
    151153        return $this;
     154    }
     155    /**
     156     * Returns status code
     157     */
     158    public function getCode()
     159    {
     160        return $this->data['code'];
    152161    }
    153162    /**
  • news-parser/trunk/news-parser.php

    r2287195 r2977790  
    44Plugin URI: https://github.com/zalevsk1y/news-parser
    55Description: Parse full text news from RSS Feed
    6 Version: 1.0.2
     6Version: 2.0.0
    77Author: Evgeny S.Zalevskiy <[email protected]>
    88Author URI: https://github.com/zalevsk1y/
     
    1212?>
    1313<?php
    14 namespace NewsParserPlugin;
    1514
    1615
    17 define('NEWS_PARSER_PLUGIN_VERSION', '1.0.2');
     16
     17define('NEWS_PARSER_PLUGIN_VERSION', '2.0.0');
    1818define("NEWS_PARSER_PLUGIN_SLUG", 'news-parser');
    1919define("NEWS_PARSER_PLUGIN_ROOT_NAMESPACE", 'NewsParserPlugin');
     
    2828define ("NEWS_PARSER_PLUGIN_VISUAL_CONSTRUCTOR","visual-constructor");
    2929define ("NEWS_PARSER_PLUGIN_PARSER_RSS","parser-rss");
     30define ("NEWS_PURSER_PLUGIN_TEMPLATE_OPTIONS_NAME","news_parser_plugin_template_options");
     31define ("NEWS_PURSER_PLUGIN_CRON_OPTIONS_NAME","news_parser_plugin_cron_options");
     32define ("NEWS_PARSER_CRON_ACTION_PREFIX","news_parser_cron_");
    3033
    3134
    3235require 'autoload.php';
    3336if(\file_exists(NEWS_PARSER_PLUGIN_DIR.'vendor/autoload.php')) require NEWS_PARSER_PLUGIN_DIR.'vendor/autoload.php';
     37require 'bootstrap.php';
    3438
     39add_action('init','NewsParserPlugin\news_parser_init');
    3540
    36 
    37 
    38 
    39 $container_builder=new \DI\ContainerBuilder();
    40 $container_builder->addDefinitions(NEWS_PARSER_PLUGIN_DIR.'di-config.php');
    41 $container=$container_builder->build();
    42 $event_controller=$container->make(Controller\EventController::class,array($container));
    43 
    44 $event_controller->on('media:create',array(Controller\MediaController::class,'create'));
    45 $event_controller->on('template:create',array(Controller\TemplateController::class,'create'));
    46 $event_controller->on('list:get',array(Controller\ListController::class,'get'));
    47 $event_controller->on('html:get',array(Controller\VisualConstructorController::class,'get'));
    48 $event_controller->on('post:create',array(Controller\PostController::class,'create'));
    49 
    50 Controller\AjaxController::create($event_controller);
    51 
    52 Core\Main::start($container->get(Menu\Admin\MenuPage::class),$container->get(Utils\MenuConfig::class));
    53 
    54 \register_uninstall_hook(__FILE__, 'Utils\Settings::deleteSettings');
     41 
     42require 'tear-down.php';
  • news-parser/trunk/public/css/about-news-parser.css

    r2265315 r2977790  
    66    min-width:350px;
    77    width:700px;
     8    font-size: 1rem;
    89}
    9 .container-about li{
    10     list-style:initial;
     10.container-about p{
     11    font-size: 1rem;
    1112}
    1213.youtube-video-container{
     
    2122    height: 100%;
    2223}
     24.styled-list{
     25    list-style: inside;
     26}
  • news-parser/trunk/public/css/frame-style.css

    r2265315 r2977790  
    1 .mouse-over{
    2     outline: 2px dotted rgb(107, 214, 204);
    3     background-color: rgba(107, 214, 204,0.5);
    4 }
    5 .parser-select{
     1.mouse-over {
     2  outline: rgba(107, 214, 204, 0.5) dotted 3px;
     3    background-color: rgba(107, 214, 204, 0.5);
    64    box-sizing: border-box;
    7     border: 3px solid rgb(107, 214, 204);
    8     background-color: rgba(107, 214, 204,0.8);
    9 }
     5  }
     6 
     7  img.parser-select {
     8    background-color: rgba(107, 214, 204, 0.8);
     9    opacity: 50%;
     10  }
     11  .parser-select{
     12    box-sizing: border-box;
     13    background-color:rgba(107, 214, 204, 0.8);
     14    outline: rgba(107, 214, 204, 0.8) solid 3px;
     15  }
     16 
    1017.news-parser-youtube{
    1118    width: 100%;
  • news-parser/trunk/readme.txt

    r2287195 r2977790  
    44Author: Evgeniy Zalevskiy
    55Tags: scraper,parser,rss,news,autopilot
    6 Requires PHP: 5.6
    7 Requires at least: 3.5.0
    8 Tested up to: 5.3.2
    9 Stable tag: 1.0.2
     6Requires PHP: 7.2
     7Requires at least: 5.2.0
     8Tested up to: 6.3.1
     9Stable tag: 2.0.0
    1010License: MIT
    1111License URI: https://opensource.org/licenses/MIT
     
    1919
    2020*   Gutenberg editor support.
     21*   Autopilot Function for Automatic RSS Parsing
    2122*   Visual content extractor.
    2223*   Flexible template creation system to speed up parsing.
     
    2526== Future plans ==
    2627
    27 *   Add auto-pilot feature.
    2828*   Parsing videos from other(than YouTube) sources.
    2929*   Saving images to the Media Library .
     
    4545Watch this short video to learn HOW TO PARSE FROM RSS with news-parser plugin:
    4646
    47 https://www.youtube.com/watch?v=xrZdkV0xA08
     47https://www.youtube.com/watch?v=Aiye15Cp5_8
    4848
    4949To parse several posts, select posts and press the Parse Selected button. Wait for the data to be saved,you`ll be notified by the message at the top of the screen. The icon at the bottom of the post allows you to go on to edit or publish a saved draft.Note that parsing selected post could be done only if you created parsing template!
     
    5151Watch this short video to learn HOW TO PARSE SEVERAL POSTS with news-parser plugin:
    5252
    53 https://www.youtube.com/watch?v=1LttLG9n4t4
     53https://www.youtube.com/watch?v=m85PExDeAMA
    5454
    5555= Visual Constructor. =
     
    6464Watch this short video to learn HOW TO USE VISUAL CONSTRUCTOR:
    6565
    66 https://www.youtube.com/watch?v=gGqbRBnGeNE
     66https://www.youtube.com/watch?v=0yS0ptvBpzY
    6767
    6868= Create Parsing Template =
     
    7272Watch this short video to learn HOW TO CREATE PARSING TEMPLATE:
    7373
    74 https://www.youtube.com/watch?v=gWo2aRTGttM
     74https://www.youtube.com/watch?v=0awSRLWsP
    7575
    7676= Parse single page. =
     
    8080Watch this short video to learn HOW TO PARSE SINGLE PAGE with news-parser plugin:
    8181
    82 https://www.youtube.com/watch?v=9x56djil-b0
     82https://www.youtube.com/watch?v=Sbke_LF-TFA
     83
     84= Autopilot Function for Automatic RSS Parsing =
     85
     86The autopilot function is now available to automatically parse posts from an RSS feed. Please note that the wp-cron (`https://developer.wordpress.org/plugins/cron/`) is used for scheduling the autopilot function, which triggers the task scheduler only when the website is visited. If you encounter issues with this function, you can add the following option to the wp-config.php file: `define('ALTERNATE_WP_CRON', true);`
     87
     88To configure the autopilot settings, follow these steps:
     89
     901. Navigate to the Autopilot tab in the menu (News Parser -> Autopilot).
     912. In the Schedule Options, select the URL that corresponds to the RSS source from which parsing will take place.
     923. Click on the Select button.
     934. After the data is loaded, the following options will be available:
     94
     95   - Status: Determines whether the autopilot is activated for this source.
     96   - Maximum Number of Posts: Sets the maximum number of posts to be parsed from this source.
     97   - Maximum Number of Autopilot Runs: Specifies the maximum number of times the autopilot should run for this source.
     98   - Parsing Frequency: Defines the frequency at which parsing should occur from this source.
     99
     1005. Additionally, in this menu, you can delete previously saved parsing templates.
     101
     102
     103Watch this short video to learn HOW TO USE AUTOPILOT with news-parser plugin:
     104
     105https://www.youtube.com/watch?v=Eu_5GR32nB0
    83106
    84107== Dependencies ==
     
    88111== Bugs ==
    89112
    90 If you find an issue, let us know [here](https://github.com/zalevsk1y/news-parser/issues?state=open)!
     113If you find an issue, let us know [here](https://github.com/zalevsk1y/news-parser/issues?state=open) or [Discord](https://discord.gg/mxhJ9hE4)
     114
     115== Contacts ==
     116
     117*   [GitHub](https://github.com/zalevsk1y/news-parser)
     118*   [Discord](https://discord.gg/mxhJ9hE4)
     119*   [Instagram](https://www.instagram.com/wp_news_parser)
    91120
    92121== Changelog ==
     122
     123
     124= 2.0.0 - 11-10-23
     125
     126* Added: Autopilot functions for automate post parsing.
     127* Added: Post options system
     128* Fix: some bugs.
    93129
    94130= 1.0.2 - 20-04-21 =
  • news-parser/trunk/template/menu/about-menu.php

    r2265315 r2977790  
    11<div class='wrap wrap-about-news-parser'>
    22<div class="container-about">
    3     <h1>Welcome to News-Parser <?php echo NEWS_PARSER_PLUGIN_VERSION ?></h1>
     3    <h2>Welcome to News-Parser <?php echo NEWS_PARSER_PLUGIN_VERSION ?></h2>
    44    <br>
    55   
     
    1515                draft,which you can just publish or edit at your discretion. This makes it easy to create content for
    1616                your site.</p>
    17             <h2>Features</h2>
    18             <ul>
     17            <h3>Features</h3>
     18            <ul class='styled-list'>
    1919                <li>Support of Gutenberg editor</li>
     20                <li>Autopilot Function for Automatic RSS Parsing</li>
    2021                <li>Visual content extractor</li>
    2122                <li>Flexible template creation system to speed up parsing</li>
    2223                <li>Ability to parse not only from RSS XML source but also </li>
    2324            </ul>
    24             <h2>Future plans</h2>
    25             <ul>
    26                 <li>Add auto-pilot feature.</li>
     25            <h3>Future plans</h3>
     26            <ul class='styled-list'>
    2727                <li>Parsing videos from other(than YouTube) sources</li>
    2828                <li>Saving images to the Media Library</li>
    2929                <li>Have an idea? – Please, feel free to let me know. Let’s make News-Parser even better!</li>
    3030            </ul>
    31             <h2>Installing</h2>
     31            <h3>Installing</h3>
    3232            <ol>
    3333                <li>You can clone the GitHub repository: <code>https://github.com/zalevsk1y/news-parser.git</code></li>
     
    3636            </ol>
    3737            <p>This will download the latest developer copy of News-parser.</p>
    38             <h2>How to use News-Parser plugin?</h2>
    39             <h3>Parsing RSS.</h3>
    40             <p>To parse RSS, go to the News-Parsing->Parsing RSS menu in the admin panel of your site. Enter the RSS feed address in the search bar. Click on the Parse RSS Feed button. When parsed data is fetched from the server,it will appear on your screen. You can open the visual extractor by clicking on the icon and create a template for parsing posts from this RSS source or simply select the content you are interested in and save it as a draft.</p>
    41 
     38            <h3>How to use News-Parser plugin?</h3>
     39            <h4>Parsing RSS</h4>
     40            <p>To parse RSS, follow these steps in the admin panel of your website under the News Parsing -> Parsing RSS menu:</p>
     41            <ul class='styled-list'>
     42                <li>Enter the RSS feed address in the search bar.</li>
     43                <li>Click on the "Parse RSS Feed" button.</li>
     44            </ul>
     45            <p>Once the parsed data is fetched from the server, it will appear on your screen.
     46            You can open the visual extractor by clicking on the icon. The visual extractor allows you to create a template for parsing posts from this RSS source.
     47            Alternatively, you can manually select the content you are interested in and save it as a draft.
     48            In the visual editor, you'll also find several options available:</p>
     49            <ul class='styled-list'>
     50                <li>Categories: You can assign categories to the parsed posts. This helps organize the content and make it easier for users to navigate.</li>
     51                <li>Tags: You can add tags to the parsed posts. Tags provide additional metadata to describe the content and make it more discoverable.</li>
     52                <li>Publishing Options: You can choose whether the post should be published immediately after parsing or saved as a draft. This gives you control over when the content goes live on your website.</li>
     53            </ul>
     54            <p>After selecting the desired content, you need to click on the "Create Post" button. Once the data is processed, the post will be created. If necessary, you can continue editing the post in the built-in WordPress editor by clicking on the "Edit post" icon. This will open the saved post in the built-in editor in a separate browser tab. After saving the changes, you can check the result on your website to ensure that the post appears as intended.</p>
    4255            <p>Watch this short video to learn HOW TO PARSE FROM RSS with news-parser plugin:</p>
    43             <div class="youtube-video-container"><iframe  src="https://www.youtube.com/embed/xrZdkV0xA08" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
     56            <div class="youtube-video-container mb-4 "><iframe  src="https://www.youtube.com/embed/Aiye15Cp5_8" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
    4457            <p>To parse several posts, select posts and press the Parse Selected button. Wait for the data to be saved,you`ll be notified by the message at the top of the screen. The icon at the bottom of the post allows you to go on to edit or publish a saved draft.Note that parsing selected post could be done only if you created parsing template!</p>
    4558
    4659            <p>Watch this short video to learn HOW TO PARSE SEVERAL POSTS:</p>
    47             <div class="youtube-video-container"><iframe  src="https://www.youtube.com/embed/1LttLG9n4t4" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
     60            <div class="youtube-video-container mb-4"><iframe  src="https://www.youtube.com/embed/m85PExDeAMA" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
    4861           
    49             <h3>Visual Constructor.</h3>
     62            <h4>Visual Constructor</h4>
    5063
    5164            <p>To create a template or simply select the content you are interested in, use the visual constructor. You can open visual constructor by clicking icon at the bottom of post box. 
    5265                To select content, click on the block that you need in the main window and it will be marked with a turquoise frame. When you hover over the content, the expected area will be painted in turquoise color.
    53                 To cancel the selection, click on the block again. Try to separate different types of content (pictures, video, text) into separate blocks. The YouTube video will be replaced with a picture of the YouTube logo. You can extrude it and this video will be inserted into your post. Parsing videos from other sources is not yet supported. Pictures are inserted into your post as a link; the exception is a featured image which is saved in your media library.
    54                 In the sidebar, you can change the featured image of your post. Just select the appropriate image on the left side of the designer and click the Change Image button. The last image you selected will be selected as featured image. You can also create a post without featured image. Just click on No featured image.
    55                 You can change the name of the post in the next submenu 'Post title'. Write your version of the post title in textaria and click the Change Title button.
     66                To cancel the selection, click on the block again.</p>
     67            <p>Try to separate different types of content (pictures, video, text) into separate blocks. The YouTube video will be replaced with a picture of the YouTube logo. You can extrude it and this video will be inserted into your post. Parsing videos from other sources is not yet supported. Pictures are inserted into your post as a link; the exception is a featured image which is saved in your media library.
     68                In the sidebar, you can change the featured image of your post. Just select the appropriate image on the left side of the designer and click the Change Image button. The last image you selected will be selected as featured image. You can also create a post without featured image. Just click on No featured image.</p>
     69            <p>You can change the name of the post in the next submenu 'Post title'. Write your version of the post title in textaria and click the Change Title button.
    5670                To add a source link, check the box labeled 'Add source link' to the post. in the 'Extra Options' submenu.</p>
    5771
    5872            <p>Watch this short video to learn HOW TO USE VISUAL CONSTRUCTOR:</p>
    59             <div class="youtube-video-container"><iframe  src="https://www.youtube.com/embed/gGqbRBnGeNE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
     73            <div class="youtube-video-container mb-4"><iframe  src="https://www.youtube.com/embed/0yS0ptvBpzY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
    6074
    61             <h3>Create Parsing Template</h3>
     75            <h4>Create Parsing Template</h4>
    6276            <p>To save the template, it is necessary to mark the content in the main window of the visual constructor, select the 'Save parsing template that you can use in automatic parsing from this source item.' and click the Save Tempalte button. It is important to understand that individual posts even from one source can be very different, therefore parsed pages may not contain the content you need.</p>
    6377            <p>Watch this short video to learn HOW TO CREATE PARSING TEMPLATE:</p>
    64             <div class="youtube-video-container"><iframe  src="https://www.youtube.com/embed/gWo2aRTGttM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
    65             <h3>Parsing single page.</h3>
     78            <div class="youtube-video-container mb-4"><iframe  src="https://www.youtube.com/embed/0awSRLWsP-I" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
     79            <h4>Parsing single page.</h4>
    6680            <p>To parse a single page, select News-Parsing-> Parse Page in the admin panel of your site. In the search bar, enter the site address URL and press Parse Page button. Visual constructor will open. In the visual constructor, select the content and click the Create Post Draft button. The draft will be automatically created and you can edit it in the Posts editor.If everything suits you, you can simply publish this post or edit it at your discretion.</p>
    6781            <p>Watch this short video to learn HOW TO PARSE SINGLE PAGE with news-parser plugin:</p>
    68             <div class="youtube-video-container"><iframe  src="https://www.youtube.com/embed/9x56djil-b0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
    69        
    70             <h2>Dependencies</h2>
     82            <div class="youtube-video-container mb-4"><iframe  src="https://www.youtube.com/embed/Sbke_LF-TFA" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
     83           
     84            <h4>Autopilot Function for Automatic RSS Parsing</h4>
     85                <p>The autopilot function is now available to automatically parse posts from an RSS feed. Please note that the <a href="https://developer.wordpress.org/plugins/cron/">wp-cron</a> is used for scheduling the autopilot function, which triggers the task scheduler only when the website is visited. If you encounter issues with this function, you can add the following option to the <code>wp-config.php</code> file: <code>define('ALTERNATE_WP_CRON', true);</code></p>
     86                <p>To configure the autopilot settings, follow these steps:</p>
     87                <ol type='1' start='1'>
     88                    <li>Navigate to the Autopilot tab in the menu (News Parser -> Autopilot).</li>
     89                    <li>In the Schedule Options, select the URL that corresponds to the RSS source from which parsing will take place.</li>
     90                    <li>Click on the Select button.</li>
     91                    <li>After the data is loaded, the following options will be available:
     92                    <ul class='styled-list'>
     93                        <li>Status: Determines whether the autopilot is activated for this source.</li>
     94                        <li>Maximum Number of Posts: Sets the maximum number of posts to be parsed from this source.</li>
     95                        <li>Maximum Number of Autopilot Runs: Specifies the maximum number of times the autopilot should run for this source.</li>
     96                        <li>Parsing Frequency: Defines the frequency at which parsing should occur from this source.</li>
     97                    </ul>
     98                    </li>
     99                    <li>Additionally, in this menu, you can delete previously saved parsing templates.</li>
     100                </ol>
     101                <p>Watch this short video to learn HOW TO USE AUTOPILOT with news-parser plugin.</p>
     102            <div class="youtube-video-container mb-4"><iframe  src="https://www.youtube.com/embed/Eu_5GR32nB0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>
     103            <h3>Dependencies</h3>
    71104            <ul>
    72105                <li>php-simple-html-dom-parser <a
     
    74107                </li>
    75108            </ul>
    76             <h2>If you find an issue, let us know <a
    77                     href="https://github.com/zalevsk1y/news-parser/issues?state=open">here</a>!</p>
     109            <p>
     110                If you have any thoughts, feedback, or proposals, feel free to connect with the author:
     111            </p>
     112            <ul className='list-unstyled list-inline'>
     113                <li class="list-inline-item">
     114                <img alt='Instagram icon' className='me-2' height="20px" src=<?php echo NEWS_PARSER_PLUGIN_URL.'/public/images/clipart1375168_d6sh2a.png'?> />
     115                    <a href="https://www.instagram.com/wp_news_parser" aria-label="Instagram - Connect with the author">
     116                       
     117                        Instagram
     118                    </a>
     119                </li>
     120                <li class="list-inline-item">
     121                <img alt='Discord icon' className='me-2' height="25px" src=<?php echo  NEWS_PARSER_PLUGIN_URL.'/public/images/discord-icon-43742_qoe0fc.png'?> />
     122                    <a href="https://discord.gg/mxhJ9hE4" aria-label="Discord - Connect with the author">
     123                       
     124                        Discord
     125                    </a>
     126                </li>
     127            </ul>
     128           
    78129        </article>
    79130
  • news-parser/trunk/template/menu/parsing-rss-menu.php

    r2265315 r2977790  
    11
    2 <div class='wrap wrap-parsing' id="parsing-rss-app"  data-lang="<?php echo get_locale(); ?>">
     2<div class="main-parsing-container">
     3
     4    <div class='wrap wrap-parsing' id="parsing-rss-app"  data-lang="<?php echo get_locale(); ?>">
     5
     6    </div>
     7    <div class="left-main-sidebar sidebar-width"  id="parser-sidebar-left"></div>
    38</div>
    4 
    59       
  • news-parser/trunk/vendor/autoload.php

    r2265315 r2977790  
    33// autoload.php @generated by Composer
    44
     5if (PHP_VERSION_ID < 50600) {
     6    if (!headers_sent()) {
     7        header('HTTP/1.1 500 Internal Server Error');
     8    }
     9    $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
     10    if (!ini_get('display_errors')) {
     11        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
     12            fwrite(STDERR, $err);
     13        } elseif (!headers_sent()) {
     14            echo $err;
     15        }
     16    }
     17    trigger_error(
     18        $err,
     19        E_USER_ERROR
     20    );
     21}
     22
    523require_once __DIR__ . '/composer/autoload_real.php';
    624
    7 return ComposerAutoloaderInitc5537c9966d2012b1bdd902c7c2b0215::getLoader();
     25return ComposerAutoloaderInit2a5deef53365ace058e7e02595992282::getLoader();
  • news-parser/trunk/vendor/composer/ClassLoader.php

    r2265315 r2977790  
    3838 * @author Fabien Potencier <[email protected]>
    3939 * @author Jordi Boggiano <[email protected]>
    40  * @see    http://www.php-fig.org/psr/psr-0/
    41  * @see    http://www.php-fig.org/psr/psr-4/
     40 * @see    https://www.php-fig.org/psr/psr-0/
     41 * @see    https://www.php-fig.org/psr/psr-4/
    4242 */
    4343class ClassLoader
    4444{
     45    /** @var \Closure(string):void */
     46    private static $includeFile;
     47
     48    /** @var string|null */
     49    private $vendorDir;
     50
    4551    // PSR-4
     52    /**
     53     * @var array<string, array<string, int>>
     54     */
    4655    private $prefixLengthsPsr4 = array();
     56    /**
     57     * @var array<string, list<string>>
     58     */
    4759    private $prefixDirsPsr4 = array();
     60    /**
     61     * @var list<string>
     62     */
    4863    private $fallbackDirsPsr4 = array();
    4964
    5065    // PSR-0
     66    /**
     67     * List of PSR-0 prefixes
     68     *
     69     * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
     70     *
     71     * @var array<string, array<string, list<string>>>
     72     */
    5173    private $prefixesPsr0 = array();
     74    /**
     75     * @var list<string>
     76     */
    5277    private $fallbackDirsPsr0 = array();
    5378
     79    /** @var bool */
    5480    private $useIncludePath = false;
     81
     82    /**
     83     * @var array<string, string>
     84     */
    5585    private $classMap = array();
     86
     87    /** @var bool */
    5688    private $classMapAuthoritative = false;
     89
     90    /**
     91     * @var array<string, bool>
     92     */
    5793    private $missingClasses = array();
     94
     95    /** @var string|null */
    5896    private $apcuPrefix;
    5997
     98    /**
     99     * @var array<string, self>
     100     */
     101    private static $registeredLoaders = array();
     102
     103    /**
     104     * @param string|null $vendorDir
     105     */
     106    public function __construct($vendorDir = null)
     107    {
     108        $this->vendorDir = $vendorDir;
     109        self::initializeIncludeClosure();
     110    }
     111
     112    /**
     113     * @return array<string, list<string>>
     114     */
    60115    public function getPrefixes()
    61116    {
    62117        if (!empty($this->prefixesPsr0)) {
    63             return call_user_func_array('array_merge', $this->prefixesPsr0);
     118            return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
    64119        }
    65120
     
    67122    }
    68123
     124    /**
     125     * @return array<string, list<string>>
     126     */
    69127    public function getPrefixesPsr4()
    70128    {
     
    72130    }
    73131
     132    /**
     133     * @return list<string>
     134     */
    74135    public function getFallbackDirs()
    75136    {
     
    77138    }
    78139
     140    /**
     141     * @return list<string>
     142     */
    79143    public function getFallbackDirsPsr4()
    80144    {
     
    82146    }
    83147
     148    /**
     149     * @return array<string, string> Array of classname => path
     150     */
    84151    public function getClassMap()
    85152    {
     
    88155
    89156    /**
    90      * @param array $classMap Class to filename map
     157     * @param array<string, string> $classMap Class to filename map
     158     *
     159     * @return void
    91160     */
    92161    public function addClassMap(array $classMap)
     
    103172     * appending or prepending to the ones previously set for this prefix.
    104173     *
    105      * @param string       $prefix  The prefix
    106      * @param array|string $paths   The PSR-0 root directories
    107      * @param bool         $prepend Whether to prepend the directories
     174     * @param string              $prefix  The prefix
     175     * @param list<string>|string $paths   The PSR-0 root directories
     176     * @param bool                $prepend Whether to prepend the directories
     177     *
     178     * @return void
    108179     */
    109180    public function add($prefix, $paths, $prepend = false)
    110181    {
     182        $paths = (array) $paths;
    111183        if (!$prefix) {
    112184            if ($prepend) {
    113185                $this->fallbackDirsPsr0 = array_merge(
    114                     (array) $paths,
     186                    $paths,
    115187                    $this->fallbackDirsPsr0
    116188                );
     
    118190                $this->fallbackDirsPsr0 = array_merge(
    119191                    $this->fallbackDirsPsr0,
    120                     (array) $paths
     192                    $paths
    121193                );
    122194            }
     
    127199        $first = $prefix[0];
    128200        if (!isset($this->prefixesPsr0[$first][$prefix])) {
    129             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
     201            $this->prefixesPsr0[$first][$prefix] = $paths;
    130202
    131203            return;
     
    133205        if ($prepend) {
    134206            $this->prefixesPsr0[$first][$prefix] = array_merge(
    135                 (array) $paths,
     207                $paths,
    136208                $this->prefixesPsr0[$first][$prefix]
    137209            );
     
    139211            $this->prefixesPsr0[$first][$prefix] = array_merge(
    140212                $this->prefixesPsr0[$first][$prefix],
    141                 (array) $paths
     213                $paths
    142214            );
    143215        }
     
    148220     * appending or prepending to the ones previously set for this namespace.
    149221     *
    150      * @param string       $prefix  The prefix/namespace, with trailing '\\'
    151      * @param array|string $paths   The PSR-4 base directories
    152      * @param bool         $prepend Whether to prepend the directories
     222     * @param string              $prefix  The prefix/namespace, with trailing '\\'
     223     * @param list<string>|string $paths   The PSR-4 base directories
     224     * @param bool                $prepend Whether to prepend the directories
    153225     *
    154226     * @throws \InvalidArgumentException
     227     *
     228     * @return void
    155229     */
    156230    public function addPsr4($prefix, $paths, $prepend = false)
    157231    {
     232        $paths = (array) $paths;
    158233        if (!$prefix) {
    159234            // Register directories for the root namespace.
    160235            if ($prepend) {
    161236                $this->fallbackDirsPsr4 = array_merge(
    162                     (array) $paths,
     237                    $paths,
    163238                    $this->fallbackDirsPsr4
    164239                );
     
    166241                $this->fallbackDirsPsr4 = array_merge(
    167242                    $this->fallbackDirsPsr4,
    168                     (array) $paths
     243                    $paths
    169244                );
    170245            }
     
    176251            }
    177252            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
    178             $this->prefixDirsPsr4[$prefix] = (array) $paths;
     253            $this->prefixDirsPsr4[$prefix] = $paths;
    179254        } elseif ($prepend) {
    180255            // Prepend directories for an already registered namespace.
    181256            $this->prefixDirsPsr4[$prefix] = array_merge(
    182                 (array) $paths,
     257                $paths,
    183258                $this->prefixDirsPsr4[$prefix]
    184259            );
     
    187262            $this->prefixDirsPsr4[$prefix] = array_merge(
    188263                $this->prefixDirsPsr4[$prefix],
    189                 (array) $paths
     264                $paths
    190265            );
    191266        }
     
    196271     * replacing any others previously set for this prefix.
    197272     *
    198      * @param string       $prefix The prefix
    199      * @param array|string $paths  The PSR-0 base directories
     273     * @param string              $prefix The prefix
     274     * @param list<string>|string $paths  The PSR-0 base directories
     275     *
     276     * @return void
    200277     */
    201278    public function set($prefix, $paths)
     
    212289     * replacing any others previously set for this namespace.
    213290     *
    214      * @param string       $prefix The prefix/namespace, with trailing '\\'
    215      * @param array|string $paths  The PSR-4 base directories
     291     * @param string              $prefix The prefix/namespace, with trailing '\\'
     292     * @param list<string>|string $paths  The PSR-4 base directories
    216293     *
    217294     * @throws \InvalidArgumentException
     295     *
     296     * @return void
    218297     */
    219298    public function setPsr4($prefix, $paths)
     
    235314     *
    236315     * @param bool $useIncludePath
     316     *
     317     * @return void
    237318     */
    238319    public function setUseIncludePath($useIncludePath)
     
    257338     *
    258339     * @param bool $classMapAuthoritative
     340     *
     341     * @return void
    259342     */
    260343    public function setClassMapAuthoritative($classMapAuthoritative)
     
    277360     *
    278361     * @param string|null $apcuPrefix
     362     *
     363     * @return void
    279364     */
    280365    public function setApcuPrefix($apcuPrefix)
     
    297382     *
    298383     * @param bool $prepend Whether to prepend the autoloader or not
     384     *
     385     * @return void
    299386     */
    300387    public function register($prepend = false)
    301388    {
    302389        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
     390
     391        if (null === $this->vendorDir) {
     392            return;
     393        }
     394
     395        if ($prepend) {
     396            self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
     397        } else {
     398            unset(self::$registeredLoaders[$this->vendorDir]);
     399            self::$registeredLoaders[$this->vendorDir] = $this;
     400        }
    303401    }
    304402
    305403    /**
    306404     * Unregisters this instance as an autoloader.
     405     *
     406     * @return void
    307407     */
    308408    public function unregister()
    309409    {
    310410        spl_autoload_unregister(array($this, 'loadClass'));
     411
     412        if (null !== $this->vendorDir) {
     413            unset(self::$registeredLoaders[$this->vendorDir]);
     414        }
    311415    }
    312416
     
    315419     *
    316420     * @param  string    $class The name of the class
    317      * @return bool|null True if loaded, null otherwise
     421     * @return true|null True if loaded, null otherwise
    318422     */
    319423    public function loadClass($class)
    320424    {
    321425        if ($file = $this->findFile($class)) {
    322             includeFile($file);
     426            $includeFile = self::$includeFile;
     427            $includeFile($file);
    323428
    324429            return true;
    325430        }
     431
     432        return null;
    326433    }
    327434
     
    368475    }
    369476
     477    /**
     478     * Returns the currently registered loaders keyed by their corresponding vendor directories.
     479     *
     480     * @return array<string, self>
     481     */
     482    public static function getRegisteredLoaders()
     483    {
     484        return self::$registeredLoaders;
     485    }
     486
     487    /**
     488     * @param  string       $class
     489     * @param  string       $ext
     490     * @return string|false
     491     */
    370492    private function findFileWithExtension($class, $ext)
    371493    {
     
    433555        return false;
    434556    }
     557
     558    /**
     559     * @return void
     560     */
     561    private static function initializeIncludeClosure()
     562    {
     563        if (self::$includeFile !== null) {
     564            return;
     565        }
     566
     567        /**
     568         * Scope isolated include.
     569         *
     570         * Prevents access to $this/self from included files.
     571         *
     572         * @param  string $file
     573         * @return void
     574         */
     575        self::$includeFile = \Closure::bind(static function($file) {
     576            include $file;
     577        }, null, null);
     578    }
    435579}
    436 
    437 /**
    438  * Scope isolated include.
    439  *
    440  * Prevents access to $this/self from included files.
    441  */
    442 function includeFile($file)
    443 {
    444     include $file;
    445 }
  • news-parser/trunk/vendor/composer/autoload_classmap.php

    r2265315 r2977790  
    33// autoload_classmap.php @generated by Composer
    44
    5 $vendorDir = dirname(dirname(__FILE__));
     5$vendorDir = dirname(__DIR__);
    66$baseDir = dirname($vendorDir);
    77
    88return array(
     9    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
    910);
  • news-parser/trunk/vendor/composer/autoload_namespaces.php

    r2265315 r2977790  
    33// autoload_namespaces.php @generated by Composer
    44
    5 $vendorDir = dirname(dirname(__FILE__));
     5$vendorDir = dirname(__DIR__);
    66$baseDir = dirname($vendorDir);
    77
  • news-parser/trunk/vendor/composer/autoload_psr4.php

    r2265315 r2977790  
    33// autoload_psr4.php @generated by Composer
    44
    5 $vendorDir = dirname(dirname(__FILE__));
     5$vendorDir = dirname(__DIR__);
    66$baseDir = dirname($vendorDir);
    77
    88return array(
    9     'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
    10     'PhpDocReader\\' => array($vendorDir . '/php-di/phpdoc-reader/src/PhpDocReader'),
    11     'Invoker\\' => array($vendorDir . '/php-di/invoker/src'),
    12     'Interop\\Container\\' => array($vendorDir . '/container-interop/container-interop/src/Interop/Container'),
    13     'DI\\' => array($vendorDir . '/php-di/php-di/src/DI'),
     9    'ContainerBuilder\\' => array($vendorDir . '/zalevsk1y/container-builder/src'),
    1410);
  • news-parser/trunk/vendor/composer/autoload_real.php

    r2265315 r2977790  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInitc5537c9966d2012b1bdd902c7c2b0215
     5class ComposerAutoloaderInit2a5deef53365ace058e7e02595992282
    66{
    77    private static $loader;
     
    1414    }
    1515
     16    /**
     17     * @return \Composer\Autoload\ClassLoader
     18     */
    1619    public static function getLoader()
    1720    {
     
    2023        }
    2124
    22         spl_autoload_register(array('ComposerAutoloaderInitc5537c9966d2012b1bdd902c7c2b0215', 'loadClassLoader'), true, true);
    23         self::$loader = $loader = new \Composer\Autoload\ClassLoader();
    24         spl_autoload_unregister(array('ComposerAutoloaderInitc5537c9966d2012b1bdd902c7c2b0215', 'loadClassLoader'));
     25        require __DIR__ . '/platform_check.php';
    2526
    26         $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
    27         if ($useStaticLoader) {
    28             require_once __DIR__ . '/autoload_static.php';
     27        spl_autoload_register(array('ComposerAutoloaderInit2a5deef53365ace058e7e02595992282', 'loadClassLoader'), true, true);
     28        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
     29        spl_autoload_unregister(array('ComposerAutoloaderInit2a5deef53365ace058e7e02595992282', 'loadClassLoader'));
    2930
    30             call_user_func(\Composer\Autoload\ComposerStaticInitc5537c9966d2012b1bdd902c7c2b0215::getInitializer($loader));
    31         } else {
    32             $map = require __DIR__ . '/autoload_namespaces.php';
    33             foreach ($map as $namespace => $path) {
    34                 $loader->set($namespace, $path);
    35             }
    36 
    37             $map = require __DIR__ . '/autoload_psr4.php';
    38             foreach ($map as $namespace => $path) {
    39                 $loader->setPsr4($namespace, $path);
    40             }
    41 
    42             $classMap = require __DIR__ . '/autoload_classmap.php';
    43             if ($classMap) {
    44                 $loader->addClassMap($classMap);
    45             }
    46         }
     31        require __DIR__ . '/autoload_static.php';
     32        call_user_func(\Composer\Autoload\ComposerStaticInit2a5deef53365ace058e7e02595992282::getInitializer($loader));
    4733
    4834        $loader->register(true);
    49 
    50         if ($useStaticLoader) {
    51             $includeFiles = Composer\Autoload\ComposerStaticInitc5537c9966d2012b1bdd902c7c2b0215::$files;
    52         } else {
    53             $includeFiles = require __DIR__ . '/autoload_files.php';
    54         }
    55         foreach ($includeFiles as $fileIdentifier => $file) {
    56             composerRequirec5537c9966d2012b1bdd902c7c2b0215($fileIdentifier, $file);
    57         }
    5835
    5936        return $loader;
    6037    }
    6138}
    62 
    63 function composerRequirec5537c9966d2012b1bdd902c7c2b0215($fileIdentifier, $file)
    64 {
    65     if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
    66         require $file;
    67 
    68         $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
    69     }
    70 }
  • news-parser/trunk/vendor/composer/autoload_static.php

    r2265315 r2977790  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInitc5537c9966d2012b1bdd902c7c2b0215
     7class ComposerStaticInit2a5deef53365ace058e7e02595992282
    88{
    9     public static $files = array (
    10         'bbf73f3db644d3dced353b837903e74c' => __DIR__ . '/..' . '/php-di/php-di/src/DI/functions.php',
    11     );
    12 
    139    public static $prefixLengthsPsr4 = array (
    14         'P' =>
     10        'C' =>
    1511        array (
    16             'Psr\\Container\\' => 14,
    17             'PhpDocReader\\' => 13,
    18         ),
    19         'I' =>
    20         array (
    21             'Invoker\\' => 8,
    22             'Interop\\Container\\' => 18,
    23         ),
    24         'D' =>
    25         array (
    26             'DI\\' => 3,
     12            'ContainerBuilder\\' => 17,
    2713        ),
    2814    );
    2915
    3016    public static $prefixDirsPsr4 = array (
    31         'Psr\\Container\\' =>
     17        'ContainerBuilder\\' =>
    3218        array (
    33             0 => __DIR__ . '/..' . '/psr/container/src',
    34         ),
    35         'PhpDocReader\\' =>
    36         array (
    37             0 => __DIR__ . '/..' . '/php-di/phpdoc-reader/src/PhpDocReader',
    38         ),
    39         'Invoker\\' =>
    40         array (
    41             0 => __DIR__ . '/..' . '/php-di/invoker/src',
    42         ),
    43         'Interop\\Container\\' =>
    44         array (
    45             0 => __DIR__ . '/..' . '/container-interop/container-interop/src/Interop/Container',
    46         ),
    47         'DI\\' =>
    48         array (
    49             0 => __DIR__ . '/..' . '/php-di/php-di/src/DI',
     19            0 => __DIR__ . '/..' . '/zalevsk1y/container-builder/src',
    5020        ),
    5121    );
     
    6131    );
    6232
     33    public static $classMap = array (
     34        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
     35    );
     36
    6337    public static function getInitializer(ClassLoader $loader)
    6438    {
    6539        return \Closure::bind(function () use ($loader) {
    66             $loader->prefixLengthsPsr4 = ComposerStaticInitc5537c9966d2012b1bdd902c7c2b0215::$prefixLengthsPsr4;
    67             $loader->prefixDirsPsr4 = ComposerStaticInitc5537c9966d2012b1bdd902c7c2b0215::$prefixDirsPsr4;
    68             $loader->prefixesPsr0 = ComposerStaticInitc5537c9966d2012b1bdd902c7c2b0215::$prefixesPsr0;
     40            $loader->prefixLengthsPsr4 = ComposerStaticInit2a5deef53365ace058e7e02595992282::$prefixLengthsPsr4;
     41            $loader->prefixDirsPsr4 = ComposerStaticInit2a5deef53365ace058e7e02595992282::$prefixDirsPsr4;
     42            $loader->prefixesPsr0 = ComposerStaticInit2a5deef53365ace058e7e02595992282::$prefixesPsr0;
     43            $loader->classMap = ComposerStaticInit2a5deef53365ace058e7e02595992282::$classMap;
    6944
    7045        }, null, ClassLoader::class);
  • news-parser/trunk/vendor/composer/installed.json

    r2265315 r2977790  
    1 [
    2     {
    3         "name": "caophihung94/php-simple-html-dom-parser",
    4         "version": "v1.7.3",
    5         "version_normalized": "1.7.3.0",
    6         "source": {
    7             "type": "git",
    8             "url": "https://github.com/caophihung94/php-simple-html-dom-parser.git",
    9             "reference": "84876d96cb39518ca2a1a5a1ac560d3531a9cc95"
     1{
     2    "packages": [
     3        {
     4            "name": "caophihung94/php-simple-html-dom-parser",
     5            "version": "v1.7.3",
     6            "version_normalized": "1.7.3.0",
     7            "source": {
     8                "type": "git",
     9                "url": "https://github.com/caophihung94/php-simple-html-dom-parser.git",
     10                "reference": "84876d96cb39518ca2a1a5a1ac560d3531a9cc95"
     11            },
     12            "dist": {
     13                "type": "zip",
     14                "url": "https://api.github.com/repos/caophihung94/php-simple-html-dom-parser/zipball/84876d96cb39518ca2a1a5a1ac560d3531a9cc95",
     15                "reference": "84876d96cb39518ca2a1a5a1ac560d3531a9cc95",
     16                "shasum": ""
     17            },
     18            "require": {
     19                "php": ">=5.3.2"
     20            },
     21            "time": "2019-02-27T11:00:03+00:00",
     22            "type": "library",
     23            "installation-source": "dist",
     24            "autoload": {
     25                "psr-0": {
     26                    "HungCP\\PhpSimpleHtmlDom\\HtmlDomParser": "src/"
     27                }
     28            },
     29            "notification-url": "https://packagist.org/downloads/",
     30            "license": [
     31                "MIT"
     32            ],
     33            "authors": [
     34                {
     35                    "name": "S.C. Chen",
     36                    "email": "[email protected]"
     37                },
     38                {
     39                    "name": "Cao Phi Hung",
     40                    "email": "[email protected]"
     41                }
     42            ],
     43            "description": "PHP Simple HTML DOM Parser with namespace and PHP 7.3 compatible",
     44            "homepage": "http://simplehtmldom.sourceforge.net/",
     45            "keywords": [
     46                "Simple",
     47                "dom",
     48                "html",
     49                "html dom parser"
     50            ],
     51            "support": {
     52                "issues": "https://github.com/caophihung94/php-simple-html-dom-parser/issues",
     53                "source": "https://github.com/caophihung94/php-simple-html-dom-parser/tree/v1.7.3"
     54            },
     55            "install-path": "../caophihung94/php-simple-html-dom-parser"
    1056        },
    11         "dist": {
    12             "type": "zip",
    13             "url": "https://api.github.com/repos/caophihung94/php-simple-html-dom-parser/zipball/84876d96cb39518ca2a1a5a1ac560d3531a9cc95",
    14             "reference": "84876d96cb39518ca2a1a5a1ac560d3531a9cc95",
    15             "shasum": ""
    16         },
    17         "require": {
    18             "php": ">=5.3.2"
    19         },
    20         "time": "2019-02-27T11:00:03+00:00",
    21         "type": "library",
    22         "installation-source": "dist",
    23         "autoload": {
    24             "psr-0": {
    25                 "HungCP\\PhpSimpleHtmlDom\\HtmlDomParser": "src/"
    26             }
    27         },
    28         "notification-url": "https://packagist.org/downloads/",
    29         "license": [
    30             "MIT"
    31         ],
    32         "authors": [
    33             {
    34                 "name": "S.C. Chen",
    35                 "email": "[email protected]"
     57        {
     58            "name": "zalevsk1y/container-builder",
     59            "version": "v1.0.2",
     60            "version_normalized": "1.0.2.0",
     61            "source": {
     62                "type": "git",
     63                "url": "https://github.com/zalevsk1y/container-builder.git",
     64                "reference": "f7d6a7cf6bcadc8c796882b839cfe4c0b5c4837d"
    3665            },
    37             {
    38                 "name": "Cao Phi Hung",
    39                 "email": "[email protected]"
    40             }
    41         ],
    42         "description": "PHP Simple HTML DOM Parser with namespace and PHP 7.3 compatible",
    43         "homepage": "http://simplehtmldom.sourceforge.net/",
    44         "keywords": [
    45             "Simple",
    46             "dom",
    47             "html",
    48             "html dom parser"
    49         ]
    50     },
    51     {
    52         "name": "container-interop/container-interop",
    53         "version": "1.2.0",
    54         "version_normalized": "1.2.0.0",
    55         "source": {
    56             "type": "git",
    57             "url": "https://github.com/container-interop/container-interop.git",
    58             "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
    59         },
    60         "dist": {
    61             "type": "zip",
    62             "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
    63             "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
    64             "shasum": ""
    65         },
    66         "require": {
    67             "psr/container": "^1.0"
    68         },
    69         "time": "2017-02-14T19:40:03+00:00",
    70         "type": "library",
    71         "installation-source": "dist",
    72         "autoload": {
    73             "psr-4": {
    74                 "Interop\\Container\\": "src/Interop/Container/"
    75             }
    76         },
    77         "notification-url": "https://packagist.org/downloads/",
    78         "license": [
    79             "MIT"
    80         ],
    81         "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
    82         "homepage": "https://github.com/container-interop/container-interop",
    83         "abandoned": "psr/container"
    84     },
    85     {
    86         "name": "php-di/invoker",
    87         "version": "1.3.3",
    88         "version_normalized": "1.3.3.0",
    89         "source": {
    90             "type": "git",
    91             "url": "https://github.com/PHP-DI/Invoker.git",
    92             "reference": "1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7"
    93         },
    94         "dist": {
    95             "type": "zip",
    96             "url": "https://api.github.com/repos/PHP-DI/Invoker/zipball/1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7",
    97             "reference": "1f4ca63b9abc66109e53b255e465d0ddb5c2e3f7",
    98             "shasum": ""
    99         },
    100         "require": {
    101             "container-interop/container-interop": "~1.1"
    102         },
    103         "require-dev": {
    104             "athletic/athletic": "~0.1.8",
    105             "phpunit/phpunit": "~4.5"
    106         },
    107         "time": "2016-07-14T13:09:58+00:00",
    108         "type": "library",
    109         "installation-source": "dist",
    110         "autoload": {
    111             "psr-4": {
    112                 "Invoker\\": "src/"
    113             }
    114         },
    115         "notification-url": "https://packagist.org/downloads/",
    116         "license": [
    117             "MIT"
    118         ],
    119         "description": "Generic and extensible callable invoker",
    120         "homepage": "https://github.com/PHP-DI/Invoker",
    121         "keywords": [
    122             "callable",
    123             "dependency",
    124             "dependency-injection",
    125             "injection",
    126             "invoke",
    127             "invoker"
    128         ]
    129     },
    130     {
    131         "name": "php-di/php-di",
    132         "version": "5.4.6",
    133         "version_normalized": "5.4.6.0",
    134         "source": {
    135             "type": "git",
    136             "url": "https://github.com/PHP-DI/PHP-DI.git",
    137             "reference": "3f9255659595f3e289f473778bb6c51aa72abbbd"
    138         },
    139         "dist": {
    140             "type": "zip",
    141             "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/3f9255659595f3e289f473778bb6c51aa72abbbd",
    142             "reference": "3f9255659595f3e289f473778bb6c51aa72abbbd",
    143             "shasum": ""
    144         },
    145         "require": {
    146             "container-interop/container-interop": "~1.2",
    147             "php": ">=5.5.0",
    148             "php-di/invoker": "^1.3.2",
    149             "php-di/phpdoc-reader": "^2.0.1",
    150             "psr/container": "~1.0"
    151         },
    152         "provide": {
    153             "container-interop/container-interop-implementation": "^1.0",
    154             "psr/container-implementation": "^1.0"
    155         },
    156         "replace": {
    157             "mnapoli/php-di": "*"
    158         },
    159         "require-dev": {
    160             "doctrine/annotations": "~1.2",
    161             "doctrine/cache": "~1.4",
    162             "mnapoli/phpunit-easymock": "~0.2.0",
    163             "ocramius/proxy-manager": "~1.0|~2.0",
    164             "phpbench/phpbench": "@dev",
    165             "phpunit/phpunit": "~4.5"
    166         },
    167         "suggest": {
    168             "doctrine/annotations": "Install it if you want to use annotations (version ~1.2)",
    169             "doctrine/cache": "Install it if you want to use the cache (version ~1.4)",
    170             "ocramius/proxy-manager": "Install it if you want to use lazy injection (version ~1.0 or ~2.0)"
    171         },
    172         "time": "2017-12-03T08:20:27+00:00",
    173         "type": "library",
    174         "installation-source": "dist",
    175         "autoload": {
    176             "psr-4": {
    177                 "DI\\": "src/DI/"
     66            "dist": {
     67                "type": "zip",
     68                "url": "https://api.github.com/repos/zalevsk1y/container-builder/zipball/f7d6a7cf6bcadc8c796882b839cfe4c0b5c4837d",
     69                "reference": "f7d6a7cf6bcadc8c796882b839cfe4c0b5c4837d",
     70                "shasum": ""
    17871            },
    179             "files": [
    180                 "src/DI/functions.php"
    181             ]
    182         },
    183         "notification-url": "https://packagist.org/downloads/",
    184         "license": [
    185             "MIT"
    186         ],
    187         "description": "The dependency injection container for humans",
    188         "homepage": "http://php-di.org/",
    189         "keywords": [
    190             "container",
    191             "dependency injection",
    192             "di"
    193         ]
    194     },
    195     {
    196         "name": "php-di/phpdoc-reader",
    197         "version": "2.1.1",
    198         "version_normalized": "2.1.1.0",
    199         "source": {
    200             "type": "git",
    201             "url": "https://github.com/PHP-DI/PhpDocReader.git",
    202             "reference": "15678f7451c020226807f520efb867ad26fbbfcf"
    203         },
    204         "dist": {
    205             "type": "zip",
    206             "url": "https://api.github.com/repos/PHP-DI/PhpDocReader/zipball/15678f7451c020226807f520efb867ad26fbbfcf",
    207             "reference": "15678f7451c020226807f520efb867ad26fbbfcf",
    208             "shasum": ""
    209         },
    210         "require": {
    211             "php": ">=5.4.0"
    212         },
    213         "require-dev": {
    214             "phpunit/phpunit": "~4.6"
    215         },
    216         "time": "2019-09-26T11:24:58+00:00",
    217         "type": "library",
    218         "installation-source": "dist",
    219         "autoload": {
    220             "psr-4": {
    221                 "PhpDocReader\\": "src/PhpDocReader"
    222             }
    223         },
    224         "notification-url": "https://packagist.org/downloads/",
    225         "license": [
    226             "MIT"
    227         ],
    228         "description": "PhpDocReader parses @var and @param values in PHP docblocks (supports namespaced class names with the same resolution rules as PHP)",
    229         "keywords": [
    230             "phpdoc",
    231             "reflection"
    232         ]
    233     },
    234     {
    235         "name": "psr/container",
    236         "version": "1.0.0",
    237         "version_normalized": "1.0.0.0",
    238         "source": {
    239             "type": "git",
    240             "url": "https://github.com/php-fig/container.git",
    241             "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
    242         },
    243         "dist": {
    244             "type": "zip",
    245             "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
    246             "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
    247             "shasum": ""
    248         },
    249         "require": {
    250             "php": ">=5.3.0"
    251         },
    252         "time": "2017-02-14T16:28:37+00:00",
    253         "type": "library",
    254         "extra": {
    255             "branch-alias": {
    256                 "dev-master": "1.0.x-dev"
    257             }
    258         },
    259         "installation-source": "dist",
    260         "autoload": {
    261             "psr-4": {
    262                 "Psr\\Container\\": "src/"
    263             }
    264         },
    265         "notification-url": "https://packagist.org/downloads/",
    266         "license": [
    267             "MIT"
    268         ],
    269         "authors": [
    270             {
    271                 "name": "PHP-FIG",
    272                 "homepage": "http://www.php-fig.org/"
    273             }
    274         ],
    275         "description": "Common Container Interface (PHP FIG PSR-11)",
    276         "homepage": "https://github.com/php-fig/container",
    277         "keywords": [
    278             "PSR-11",
    279             "container",
    280             "container-interface",
    281             "container-interop",
    282             "psr"
    283         ]
    284     }
    285 ]
     72            "require": {
     73                "php": ">=5.6"
     74            },
     75            "require-dev": {
     76                "phpunit/phpunit": "5.7.2"
     77            },
     78            "time": "2023-10-09T11:59:22+00:00",
     79            "type": "library",
     80            "installation-source": "dist",
     81            "autoload": {
     82                "psr-4": {
     83                    "ContainerBuilder\\": "src/"
     84                }
     85            },
     86            "notification-url": "https://packagist.org/downloads/",
     87            "license": [
     88                "MIT"
     89            ],
     90            "authors": [
     91                {
     92                    "name": "Evgeny Zalevsky"
     93                }
     94            ],
     95            "description": "Container Builder, provides a simple implementation of a Dependency Injection Container. It allows for easy management of object instances and their dependencies, allowing for more flexible and maintainable code. The module includes methods for adding definition files, retrieving instances, and calling methods on instances with specified arguments. This can help improve code organization and reduce coupling between classes, leading to a more robust and scalable application.",
     96            "support": {
     97                "issues": "https://github.com/zalevsk1y/container-builder/issues",
     98                "source": "https://github.com/zalevsk1y/container-builder/tree/v1.0.2"
     99            },
     100            "install-path": "../zalevsk1y/container-builder"
     101        }
     102    ],
     103    "dev": true,
     104    "dev-package-names": []
     105}
Note: See TracChangeset for help on using the changeset viewer.