PHP Classes

File: MultiCurl.class.php

Recommend this page to a friend!
  Classes of V   MultiCurl   MultiCurl.class.php   Download  
File: MultiCurl.class.php
Role: Class source
Content type: text/plain
Description: MultiCurl class
Class: MultiCurl
Retrieve multiple pages simultaneously
Author: By
Last change: changed
Date: 6 years ago
Size: 7,102 bytes
 

Contents

Class file image Download
<?php
/**
 * MultiCurl class provides a convenient way to execute parallel HTTP(S)
 * requests via PHP MULTI CURL extension with additional restrictions.
 * For example: start 100 downloads with 2 parallel sessions, and get only
 * first 100 Kb per session.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3.0 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 */
abstract class MultiCurl {
   
/**
     * Maximal number of CURL multi sessions. Default: 10 sessions.
     *
     * @var integer
     */
   
private $maxSessions = 10;

   
/**
     * Maximal size of downloaded content. Default: 10 Mb (10 * 1024 * 1024).
     *
     * @var integer
     */
   
private $maxSize = 10485760;

   
/**
     * Common CURL options (used for all requests).
     *
     * @var array
     */
   
private $curlOptions;

   
/**
     * Current CURL multi sessions.
     *
     * @var array
     */
   
private $sessions = array();

   
/**
     * Class constructor. Setup primary parameters.
     *
     * @param array $curlOptions Common CURL options.
     */
   
public function __construct($curlOptions = array()) {
       
$this->setCurlOptions($curlOptions);
    }

   
/**
     * Class destructor. Close opened sessions.
     */
   
public function __destruct() {
        foreach (
$this->sessions as $i => $sess) {
           
$this->destroySession($i);
        }
    }

   
/**
     * Adds new URL to query.
     *
     * @param mixed $url URL for downloading.
     * @param array $curlOptions CURL options for current request.
     */
   
public function addUrl($url, $curlOptions = array()) {
       
// Check URL
       
if (!$url) {
            throw new
Exception('URL is empty!');
        }

       
// Check array of URLs
       
if (is_array($url)) {
            foreach (
$url as $s) {
               
$this->addUrl($s, $curlOptions);
            }
            return;
        }

       
// Check query
       
while (count($this->sessions) == $this->maxSessions) {
           
$this->checkSessions();
        }

       
// Init new CURL session
       
$ch = curl_init($url);
        foreach (
$this->curlOptions as $option => $value) {
           
curl_setopt($ch, $option, $value);
        }
        foreach (
$curlOptions as $option => $value) {
           
curl_setopt($ch, $option, $value);
        }

       
// Init new CURL multi session
       
$mh = curl_multi_init();
       
curl_multi_add_handle($mh, $ch);
       
$this->sessions[] = array($mh, $ch, $url);
       
$this->execSession(array_pop(array_keys($this->sessions)));
    }

   
/**
     * Waits CURL milti sessions.
     */
   
public function wait() {
        while (
count($this->sessions)) {
           
$this->checkSessions();
        }
    }

   
/**
     * Executes all active CURL multi sessions.
     */
   
protected function checkSessions() {
        foreach (
$this->sessions as $i => $sess) {
            if (
curl_multi_select($sess[0]) != -1) {
               
$this->execSession($i);
            }
        }
    }

   
/**
     * Executes CURL multi session, check session status and downloaded size.
     *
     * @param integer $i A session id.
     */
   
protected function execSession($i) {
        list(
$mh, $ch) = $this->sessions[$i];

        while ((
$mrc = curl_multi_exec($mh, $act)) == CURLM_CALL_MULTI_PERFORM);

        if (!
$act || $mrc != CURLM_OK ||
            
curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD) >= $this->maxSize) {
           
$this->closeSession($i);
        }
    }

   
/**
     * Closes session.
     *
     * @param integer $i A session id.
     */
   
protected function closeSession($i) {
        list(,
$ch, $url) = $this->sessions[$i];

       
$content = !curl_error($ch) ? curl_multi_getcontent($ch) : null;
       
$info = curl_getinfo($ch);
       
$this->destroySession($i);
       
$this->onLoad($url, $content, $info);
    }

   
/**
     * Destroys session.
     *
     * @param integer $i A session id.
     */
   
protected function destroySession($i) {
        list(
$mh, $ch,) = $this->sessions[$i];

       
curl_multi_remove_handle($mh, $ch);
       
curl_close($ch);
       
curl_multi_close($mh);

        unset(
$this->sessions[$i]);
    }

   
/**
     * Gets maximal number of CURL multi sessions.
     *
     * @return integer Maximal number of CURL multi sessions.
     */
   
public function getMaxSessions() {
        return
$this->maxSessions;
    }

   
/**
     * Sets maximal number of CURL multi sessions.
     *
     * @param integer $maxSessions Maximal number of CURL multi sessions.
     */
   
public function setMaxSessions($maxSessions) {
        if ((int)
$maxSessions <= 0) {
            throw new
Exception('Max sessions number must be bigger then zero!');
        }

       
$this->maxSessions = (int)$maxSessions;
    }

   
/**
     * Gets maximal size limit for downloaded content.
     *
     * @return integer Maximal size limit for downloaded content.
     */
   
public function getMaxSize() {
        return
$this->maxSize;
    }

   
/**
     * Sets maximal size limit for downloaded content.
     *
     * @param integer $maxSize Maximal size limit for downloaded content.
     */
   
public function setMaxSize($maxSize) {
        if ((int)
$maxSize <= 0) {
            throw new
Exception('Max size limit must be bigger then zero!');
        }

       
$this->maxSize = (int)$maxSize;
    }

   
/**
     * Gets CURL options for all requests.
     *
     * @return array CURL options.
     */
   
public function getCurlOptions() {
        return
$this->curlOptions;
    }

   
/**
     * Sets CURL options for all requests.
     *
     * @param array $curlOptions CURL options.
     */
   
public function setCurlOptions($curlOptions) {
        if (!
array_key_exists(CURLOPT_FOLLOWLOCATION, $curlOptions)) {
           
$curlOptions[CURLOPT_FOLLOWLOCATION] = 1;
        }
       
$curlOptions[CURLOPT_RETURNTRANSFER] = 1;
       
$this->curlOptions = $curlOptions;
    }

   
/**
     * OnLoad callback event.
     *
     * @param string $url URL for downloading.
     * @param string $content Downloaded content.
     * @param array $info CURL session information.
     */
   
protected abstract function onLoad($url, $content, $info);

   
/**
     * Checks CURL extension, etc.
     */
   
public static function checkEnvironment() {
        if (!
extension_loaded('curl')) {
            throw new
Exception('CURL extension not loaded');
        }
    }
}