• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List

system/classes/update.php

00001 <?php
00007 namespace Habari;
00008 
00016 class Update extends Singleton
00017 {
00018   const UPDATE_URL = 'https://beacon.habariproject.org/';
00019   
00020   private $beacons = array();
00021   private $update; // SimpleXMLElement
00022 
00028   protected static function instance()
00029   {
00030     return self::getInstanceOf( get_class() );
00031   }
00032 
00042   public static function add( $name, $beaconid, $current_version )
00043   {
00044     try {
00045       if ( empty( $name ) || empty( $beaconid ) || empty( $current_version ) ) {
00046         if ( empty( $name ) ) {
00047           $name = "Unnamed plugin";
00048         }
00049         // @locale Signifies the plugin or theme is missing needed information to check for an update
00050         throw new \Exception( _t( 'Invalid Beacon updater information added for %s. The plugin or theme cannot be identified. Check your plugin\'s or theme\'s XML.', array($name) ) );
00051       }
00052     
00053       self::instance()->beacons[ (string) $beaconid] = array( 'name' => (string) $name, 'version' => (string) $current_version );
00054     }
00055     catch ( \Exception $e ) {
00056       // catch any exceptions generated by missing beacon information
00057       EventLog::log( _t( 'Beacon updater failed! %s', array($e->getMessage())), 'err', 'update', 'habari' );
00058       
00059       // tell cron the check failed
00060       return false;
00061     }
00062   }
00063 
00070   public static function filter_unchanged( $beacon )
00071   {
00072     return isset( $beacon['latest_version'] );
00073   }
00074 
00075 
00082   public static function check()
00083   {
00084     
00085     try {
00086       
00087       // get a local version of the instance to save typing
00088       $instance = self::instance();
00089       
00090       // load beacons
00091       self::register_beacons();
00092 
00093       // setup the remote request
00094       $request = new RemoteRequest( self::UPDATE_URL, 'POST' );
00095       
00096       // add all the beacon versions as parameters
00097       $request->set_params(
00098         Utils::array_map_field($instance->beacons, 'version')
00099       );
00100       // we're not desperate enough to wait too long
00101       $request->set_timeout( 5 );
00102       
00103       // execute the request
00104       $result = $request->execute();
00105       
00106       // grab the body of the response, which has our xml in it
00107       $update_data = $request->get_response_body();
00108       
00109       // i don't know why we hold the XML in a class variable, but we'll keep doing that in this rewrite
00110       $instance->update = new \SimpleXMLElement( $update_data );
00111       
00112       foreach ( $instance->update as $beacon ) {
00113         
00114         $beacon_id = (string)$beacon['id'];
00115         $beacon_url = (string)$beacon['url'];
00116         $beacon_type = isset( $beacon['type'] ) ? (string)$beacon['type'] : 'addon';
00117         
00118         // do we have this beacon? if not, don't process it
00119         // even though we POST all our beacons to the update script right now, it still hands back the whole list
00120         if ( empty( $instance->beacons[ $beacon_id ] ) ) {
00121           continue;
00122         }
00123         
00124         // add the beacon's basic info
00125         $instance->beacons[ $beacon_id ]['id'] = $beacon_id;
00126         $instance->beacons[ $beacon_id ]['url'] = $beacon_url;
00127         $instance->beacons[ $beacon_id ]['type'] = $beacon_type;
00128         
00129         foreach ( $beacon->update as $update ) {
00130 
00131           // pick out and cast all the values from the XML
00132           $u = array(
00133             'severity' => (string)$update['severity'],
00134             'version' => (string)$update['version'],
00135             'date' => isset( $update['date'] ) ? (string)$update['date'] : '',
00136             'url' => isset( $update['url'] ) ? (string)$update['url'] : '',
00137             'text' => (string)$update,
00138           );
00139           
00140           
00141           // if the remote update info version is newer... we want all newer versions
00142           if ( version_compare( $u['version'], $instance->beacons[ $beacon_id ]['version'] ) > 0 ) {
00143             
00144             // if this version is more recent than all the other versions
00145             if ( !isset( $instance->beacons[ $beacon_id ]['latest_version'] ) || version_compare( $u['version'], $instance->beacons[ $beacon_id ]['latest_version'] ) > 0 ) {
00146               
00147               // set this as the latest version
00148               $instance->beacons[ $beacon_id ]['latest_version'] = $u['version'];
00149               
00150             }
00151             
00152             // add the version to the list
00153             $instance->beacons[ $beacon_id ]['updates'][ $u['version'] ] = $u;
00154             
00155           }
00156           
00157         }
00158         
00159       }
00160       
00161       // return an array of beacons that have updates
00162       return array_filter( $instance->beacons, Method::create( '\Habari\Update', 'filter_unchanged' ) );
00163       
00164     }
00165     catch ( \Exception $e ) {
00166       // catches any RemoteRequest errors or XML parsing problems, etc.
00167       // bubble up
00168       throw $e;
00169     }
00170     
00171   }
00172   
00176   private static function add_plugins()
00177   {
00178     
00179     $plugins = Plugins::get_active();
00180     
00181     foreach ( $plugins as $plugin ) {
00182       
00183       // name and version are required in the XML file, make sure GUID is set
00184       if ( !isset( $plugin->info->guid ) ) {
00185         continue;
00186       }
00187       
00188       Update::add( $plugin->info->name, $plugin->info->guid, $plugin->info->version );
00189       
00190     }
00191     
00192   }
00193   
00201   public static function cron( $cronjob = null )
00202   {
00203     
00204     // register the beacons
00205     self::register_beacons();
00206     
00207     // save the list of beacons we are using to check with
00208     Options::set( 'updates_beacons', self::instance()->beacons );
00209     
00210     try {
00211       // run the check
00212       $updates = Update::check();
00213       
00214       // save the list of updates
00215       Options::set( 'updates_available', $updates );
00216       
00217       EventLog::log( _t( 'Updates check CronJob completed successfully.' ), 'info', 'update', 'habari' );
00218       
00219       // return true, we succeeded
00220       return true;
00221     }
00222     catch ( \Exception $e ) {
00223       // catch any exceptions generated by RemoteRequest or XML parsing
00224       
00225       EventLog::log( _t( 'Updates check CronJob failed!' ), 'err', 'update', 'habari', $e->getMessage() );
00226       
00227       // tell cron the check failed
00228       return false;
00229     }
00230     
00231   }
00232   
00237   private static function register_beacons()
00238   {
00239     
00240     // if there are already beacons, don't run again
00241     if ( count( self::instance()->beacons ) > 0 ) {
00242       return;
00243     }
00244     
00245     Update::add( 'Habari', '7a0313be-d8e3-11db-8314-0800200c9a66', Version::get_habariversion() );
00246     
00247     // add the active theme
00248     self::add_theme();
00249         
00250     // add all active plugins
00251     self::add_plugins();
00252     
00253     Plugins::act( 'update_check' );
00254     
00255   }
00256   
00260   private static function add_theme()
00261   {
00262     
00263     // get the active theme
00264     $theme = Themes::get_active_data( true );
00265     
00266     // name and version are required in the XML file, make sure GUID is set
00267     if ( isset( $theme['info']->guid ) ) {
00268       Update::add( $theme['info']->name, $theme['info']->guid, $theme['info']->version );
00269     }
00270     
00271   }
00272   
00277   public static function check_plugins()
00278   {
00279     
00280     // register the beacons
00281     self::register_beacons();
00282     
00283     // get the list we checked last time
00284     $checked_list = Options::get( 'updates_beacons' );
00285     
00286     // if the lists are different
00287     if ( $checked_list != self::instance()->beacons ) {
00288       
00289       // remove any stored updates, just to avoid showing stale data
00290       Options::delete( 'updates_available' );
00291       
00292       // schedule an update check the next time cron runs
00293       CronTab::add_single_cron( 'update_check_single', Method::create( '\Habari\Update', 'cron' ), DateTime::create()->int, _t( 'Perform a single check for plugin updates, the plugin set has changed.' ) );
00294       
00295     }
00296     
00297   }
00298   
00307   public static function updates_available( $guid = null )
00308   {
00309     
00310     $updates = Options::get( 'updates_available', array() );
00311     
00312     if ( $guid == null ) {
00313       return $updates;
00314     }
00315     else {
00316       
00317       if ( isset( $updates[ $guid ] ) ) {
00318         return $updates[ $guid ];
00319       }
00320       else {
00321         return false;
00322       }
00323       
00324     }
00325     
00326   }
00327 
00328 }
00329 
00330 ?>

Generated on Sun Aug 4 2013 12:51:43 for Habari by  doxygen 1.7.1