Exemplo n.º 1
0
 /**
  * Wrapper to fetch all elements besides some from podio imposed maxresult.
  * 
  * Examples:
  * 
  * $result = PodioFetchAll::iterateApiCall('PodioFile::get_for_app', "YOUR_APP_ID", array('attached_to' => 'item'));
  * $result = PodioFetchAll::iterateApiCall('PodioItem::filter', "YOUR_APP_ID", array(), "items");
  * 
  * @param type $function e.g. 'PodioFile::get_for_app'
  * @param type $id first parameter of function
  * @param type $params
  * @param int $limit no of elements fetched on each call
  * @param String $resulttype if set, the result of the call is suspected to be in $result[$resulttype]
  * @return type array of all fetched elements
  */
 static function iterateApiCall($function, $id, $params = array(), $limit = 100, $resulttype = null)
 {
     $completed = false;
     $iteration = 0;
     $result = array();
     while (!$completed) {
         #$tmp_result = $function($id, array_merge($params, array("limit" => $limit, 'offset' => $limit * $iteration)));
         $tmp_result = call_user_func($function, $id, array_merge($params, array('limit' => $limit, 'offset' => $limit * $iteration)));
         RateLimitChecker::preventTimeOut();
         #echo "done iteration $iteration\n";
         $iteration++;
         if ($tmp_result instanceof PodioCollection) {
             $result = array_merge($result, $tmp_result->_get_items());
             if ($tmp_result instanceof PodioItemCollection) {
                 echo "filtered: {$tmp_result->filtered}, total: {$tmp_result->total} (limit: {$limit})\n";
                 if (sizeof($tmp_result->_get_items()) < $limit) {
                     $completed = true;
                 }
             } else {
                 echo "WARNING unexpected collection: " . get_class($tmp_result);
             }
         } else {
             if (isset($resulttype)) {
                 if (is_array($tmp_result) && isset($tmp_result[$resulttype]) && is_array($tmp_result[$resulttype])) {
                     $result = array_merge($result, $tmp_result[$resulttype]);
                     if (sizeof($tmp_result[$resulttype]) < $limit) {
                         $completed = true;
                     }
                 } else {
                     $completed = true;
                 }
             } else {
                 if (is_array($tmp_result)) {
                     $result = array_merge($result, $tmp_result);
                     if (sizeof($tmp_result) < $limit) {
                         $completed = true;
                     }
                 } else {
                     $completed = true;
                 }
             }
         }
         unset($tmp_result);
     }
     return $result;
 }
/**
 * If $file represents a file hosted by podio, it is downloaded to $folder.
 * In any case a link to the file is returned (relative to $folder).
 * $folder is assumed to be without trailing '/'.
 * (The problem with files not hosted by podio is that mostly you need a login,
 * i.e. you wont get the file but an html login page.)
 *
 * Uses the file $config['backupTo'].'/filestore.php' to assure no file is downloaded twice.
 * (over incremental backups). Creates a (sym)link to the original file in case.
 *
 * @param type $folder
 * @param type $file
 * @return String link relative to $folder or weblink
 */
function downloadFileIfHostedAtPodio($folder, $file)
{
    global $config;
    $link = $file->link;
    if ($file->hosted_by == "podio") {
        //$filestore: Stores fileid->path_to_file_relative to backupTo-folder.
        //this is loaded on every call to assure files from interrupted runs are preserved.
        $filestore = array();
        $filenameFilestore = $config['backupTo'] . '/filestore.php';
        if (file_exists($filenameFilestore)) {
            $filestore = unserialize(file_get_contents($filenameFilestore));
        }
        $filename = fixDirName($file->name);
        while (file_exists($folder . '/' . $filename)) {
            $filename = 'Z' . $filename;
        }
        if (array_key_exists($file->file_id, $filestore)) {
            echo "DEBUG: Detected duplicate download for file: {$file->file_id}\n";
            $existing_file = realpath($config['backupTo'] . '/' . $filestore[$file->file_id]);
            $link = RelativePaths::getRelativePath($folder, $existing_file);
            link($existing_file, $folder . '/' . $filename);
            #symlink($existing_file, $folder.'/'.$filename);
        } else {
            try {
                file_put_contents($folder . '/' . $filename, $file->get_raw());
                RateLimitChecker::preventTimeOut();
                $link = $filename;
                $filestore[$file->file_id] = RelativePaths::getRelativePath($config['backupTo'], $folder . '/' . $filename);
                file_put_contents($filenameFilestore, serialize($filestore));
            } catch (PodioBadRequestError $e) {
                echo $e->body;
                # Parsed JSON response from the API
                echo $e->status;
                # Status code of the response
                echo $e->url;
                # URI of the API request
                // You normally want this one, a human readable error description
                echo $e->body['error_description'];
            }
        }
    } else {
        #echo "Warning: Not downloading file hosted by ".$file->hosted_by."\n";
    }
    unset($filestore);
    return $link;
}
 /**
  * If getting close to hitting the rate limit, this method blocks until the
  * rate-limit count is resetted.
  *
  * One might want to call this method before/after every call to the podio api.
  *
  * This is a devensive approach as it supspects a rate limited call every time
  * the header "x-rate-limit-remaining" is not set. E.g. after PodioFile->get_raw().
  *
  * @global boolean $verbose
  */
 public static function preventTimeOut()
 {
     global $verbose;
     if (!isset(self::$start)) {
         echo "init RateLimitChecker..\n";
         self::$start = time();
     }
     //Note: after PodioFile->get_raw() Podio::rate_limit_remaining() leads to errors, since the header is not set.
     if (array_key_exists('x-rate-limit-remaining', Podio::$last_response->headers)) {
         $remaining = Podio::$last_response->headers['x-rate-limit-remaining'];
         $limit = Podio::$last_response->headers['x-rate-limit-limit'];
         if ($limit == 250) {
             self::$no_of_estimations = 0;
         }
     } else {
         $remaining = --self::$rate_limit_lower;
         self::$no_of_estimations++;
         $limit = 250;
     }
     if ($limit == 250) {
         self::$rate_limit_lower = $remaining;
     } else {
         self::$rate_limit = $remaining;
     }
     if (isset($verbose) && $verbose) {
         echo "DEBUG: rate_limit={$limit} remaining={$remaining} " . (array_key_exists('x-rate-limit-remaining', Podio::$last_response->headers) ? "" : "(estimate)") . "\n";
     }
     if ($remaining < self::$stop_limit) {
         echo "running since " . date('H:i', self::$start) . "\n";
         $minutes_till_reset = 60 - (time() - self::$start) / 60 + 1;
         echo "sleeping {$minutes_till_reset} minutes to prevent rate limit violation.\n";
         sleep(60 * $minutes_till_reset);
         self::$rate_limit_lower = 250;
         self::$rate_limit = 5000;
         self::$start = time();
     } else {
         if (self::dummyCallNeccessary($remaining)) {
             return;
         }
     }
 }