Zebra_cURL::_process PHP Method

_process() private method

@return void
private _process ( ) : void
return void
    private function _process()
    {
        // if caching is enabled but path doesn't exist, or is not writable
        if ($this->cache !== false && (!is_dir($this->cache['path']) || !is_writable($this->cache['path']))) {
            // trigger an error and stop execution
            trigger_error('Cache path does not exists or is not writable', E_USER_ERROR);
        }
        // iterate through the requests to process
        foreach ($this->_requests as $index => $request) {
            // if callback function is defined but it doesn't exists
            if ($request['callback'] != '' && !is_callable($request['callback'])) {
                // trigger an error and stop execution
                // the check is for when callback functions are defined as methods of a class
                trigger_error('Callback function "' . (is_array($request['callback']) ? array_pop($request['callback']) : $request['callback']) . '" does not exist', E_USER_ERROR);
            }
            // if caching is enabled
            if ($this->cache !== false) {
                // get the name to be used for the cache file associated with the request
                $cache_file = $this->_get_cache_file_name($request);
                // if cache file exists and is not expired
                if (file_exists($cache_file) && filemtime($cache_file) + $this->cache['lifetime'] > time()) {
                    // if we have a callback
                    if ($request['callback'] != '') {
                        // prepare the arguments to pass to the callback function
                        $arguments = array_merge(array(unserialize($this->cache['compress'] ? gzuncompress(file_get_contents($cache_file)) : file_get_contents($cache_file))), (array) $request['arguments']);
                        // feed them as arguments to the callback function
                        call_user_func_array($request['callback'], $arguments);
                        // remove this request from the list so it doesn't get processed
                        unset($this->_requests[$index]);
                    }
                }
            }
        }
        // if there are any requests to process
        if (!empty($this->_requests)) {
            // initialize the multi handle
            // this will allow us to process multiple handles in parallel
            $this->_multi_handle = curl_multi_init();
            // queue the first batch of requests
            // (as many as defined by the "threads" property, or less if there aren't as many requests)
            $this->_queue_requests();
            // a flag telling the library if there are any requests currently processing
            $running = null;
            // loop
            do {
                // get status update
                while (($status = curl_multi_exec($this->_multi_handle, $running)) == CURLM_CALL_MULTI_PERFORM) {
                }
                // if no request has finished yet, keep looping
                if ($status != CURLM_OK) {
                    break;
                }
                // if a request was just completed, we'll have to find out which one
                while ($info = curl_multi_info_read($this->_multi_handle)) {
                    // get handle of the completed request
                    $handle = $info['handle'];
                    // get content associated with the handle
                    $content = curl_multi_getcontent($handle);
                    // get the handle's ID
                    $resource_number = preg_replace('/Resource id #/', '', $handle);
                    // get the information associated with the request
                    $request = $this->_running['fh' . $resource_number];
                    // create a new object in which we will store all the data associated with the handle,
                    // as properties of this object
                    $result = new stdClass();
                    // get information about the request
                    $result->info = curl_getinfo($handle);
                    // extend the "info" property with the original URL
                    $result->info = array('original_url' => $request['url']) + $result->info;
                    // if request was a POST
                    if (isset($request['options'][CURLOPT_POSTFIELDS]) && $request['options'][CURLOPT_POSTFIELDS]) {
                        // put POST parameters in the response
                        $result->post = $request['options'][CURLOPT_POSTFIELDS];
                    }
                    // last request headers
                    $result->headers['last_request'] = isset($request['options'][CURLINFO_HEADER_OUT]) && $request['options'][CURLINFO_HEADER_OUT] == 1 && isset($result->info['request_header']) ? $this->_parse_headers($result->info['request_header'], true) : '';
                    // remove request headers information from its previous location
                    unset($result->info['request_header']);
                    // get headers (unless we were explicitly told not to)
                    $result->headers['responses'] = isset($request['options'][CURLOPT_HEADER]) && $request['options'][CURLOPT_HEADER] == 1 ? $this->_parse_headers(substr($content, 0, $result->info['header_size'])) : '';
                    // get output (unless we were explicitly told not to)
                    $result->body = !isset($request['options'][CURLOPT_NOBODY]) || $request['options'][CURLOPT_NOBODY] == 0 ? isset($request['options'][CURLOPT_HEADER]) && $request['options'][CURLOPT_HEADER] == 1 ? substr($content, $result->info['header_size']) : $content : '';
                    // if _htmlentities is set to TRUE, we're not doing a binary transfer and we have a body, run htmlentities() on it
                    if ($this->_htmlentities && !isset($request['options'][CURLOPT_BINARYTRANSFER]) && $result->body != '') {
                        // since PHP 5.3.0, htmlentities will return an empty string if the input string contains an
                        // invalid code unit sequence within the given encoding (utf-8 in our case)
                        // so take care of that
                        if (defined(ENT_IGNORE)) {
                            $result->body = htmlentities($result->body, ENT_IGNORE, 'utf-8');
                        } else {
                            htmlentities($result->body);
                        }
                    }
                    // get CURLs response code and associated message
                    $result->response = array($this->_response_messages[$info['result']], $info['result']);
                    // if we have a callback
                    if (isset($request['callback']) && $request['callback'] != '') {
                        // prepare the arguments to pass to the callback function
                        $arguments = array_merge(array($result), $request['arguments']);
                        // feed them as arguments to the callback function
                        // and save the callback's response, if any
                        $callback_response = call_user_func_array($request['callback'], $arguments);
                        // if no callback function, we assume the response is TRUE
                    } else {
                        $callback_response = true;
                    }
                    // if caching is enabled and the callback function did not return FALSE
                    if ($this->cache !== false && $callback_response !== false) {
                        // get the name of the cache file associated with the request
                        $cache_file = $this->_get_cache_file_name($request);
                        // cache the result
                        file_put_contents($cache_file, $this->cache['compress'] ? gzcompress(serialize($result)) : serialize($result));
                        // set rights on the file
                        chmod($cache_file, intval($this->cache['chmod'], 8));
                    }
                    // if there are more URLs to process, queue the next one
                    if (!empty($this->_requests)) {
                        $this->_queue_requests();
                    }
                    // remove the handle that we finished processing
                    // this needs to be done *after* we've already queued a new URL for processing
                    curl_multi_remove_handle($this->_multi_handle, $handle);
                    // make sure the handle gets closed
                    curl_close($handle);
                    // if we downloaded a file
                    if (isset($request['options'][CURLOPT_BINARYTRANSFER]) && $request['options'][CURLOPT_BINARYTRANSFER]) {
                        // close the associated file pointer
                        fclose($this->_running['fh' . $resource_number]['file_handler']);
                    }
                    // we don't need the information associated with this request anymore
                    unset($this->_running['fh' . $resource_number]);
                }
                // waits until curl_multi_exec() returns CURLM_CALL_MULTI_PERFORM or until the timeout, whatever happens first
                // call usleep() if a select returns -1 - workaround for PHP bug: https://bugs.php.net/bug.php?id=61141
                if ($running && curl_multi_select($this->_multi_handle) === -1) {
                    usleep(100);
                }
                // as long as there are threads running
            } while ($running);
            // close the multi curl handle
            curl_multi_close($this->_multi_handle);
        }
    }