ActionApps PHP Cross Reference Groupware Applications

Source: /include/grabber.class.php3 - 1075 lines - 42055 bytes - Summary - Text - Print

Description: PHP versions 4 and 5

   1  <?php
   2  /**
   3   *
   4   * PHP versions 4 and 5
   5   *
   6   * LICENSE: This program is free software; you can redistribute it and/or modify
   7   * it under the terms of the GNU General Public License as published by
   8   * the Free Software Foundation; either version 2 of the License, or
   9   * (at your option) any later version.
  10   *
  11   * This program is distributed in the hope that it will be useful,
  12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14   * GNU General Public License for more details.
  15   *
  16   * You should have received a copy of the GNU General Public License
  17   * along with this program (LICENSE); if not, write to the Free Software
  18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19   *
  20   * @version   $Id: xmlclient.php3,v 1.23 2005/06/23 16:21:23 honzam Exp $
  21   * @author    Honza Malik <honza.malik@ecn.cz>
  22   * @license   http://opensource.org/licenses/gpl-license.php GNU Public License
  23   * @copyright Copyright (C) 1999, 2000 Association for Progressive Communications
  24   * @link      http://www.apc.org/ APC
  25   *
  26  */
  27  
  28  /** Saver / Grabber API
  29   *
  30   *   Defines AA_Grabber base class, which is used as abstraction for data input
  31   *   From this class we derive concrete data grabbers, like RSS, AARSS, CSV, ...
  32   */
  33  
  34  
  35  /** Saver class - Used for filling items into AA
  36   *  @param grabber          - provides source for item data
  37   *  @param $transformations - defines, how the source item should be transformed
  38   *                            into destination item
  39   */
  40  class AA_Saver {
  41      var $grabber;            /** the object which deliveres the data */
  42      var $transformations;    /** describes, what to do with data before storing */
  43      var $slice_id;           /** id of destination slice */
  44      var $store_mode;         /** store-policy - how to store - overwrite | insert_if_new | by_grabber */
  45      var $id_mode;            /** id-policy    - how to construct id - old | new | combined */
  46  
  47      var $_new_ids;           /** array of newly inserted ids (after run()) - the long ones */
  48      var $_updated_ids;       /** array of ids of rewritten items (after run()) - the long ones */
  49  
  50      /** AA_Saver function
  51       * @param $grabber
  52       * @param $transformations
  53       * @param $slice_id
  54       * @param $store_mode
  55       * @param $id_mode
  56       */
  57      function AA_Saver(&$grabber, &$transformations, $slice_id=null, $store_mode='overwrite', $id_mode='old') {
  58          $this->grabber         = $grabber;
  59          $this->transformations = $transformations;
  60          $this->slice_id        = $slice_id;
  61          $this->store_mode      = $store_mode;
  62          $this->id_mode         = $id_mode;
  63          $this->_new_ids        = array();
  64          $this->_updated_ids    = array();
  65      }
  66  
  67      /** run function
  68       * Now import all items to the slice
  69       */
  70      function run() {
  71          global $debugfeed;
  72  
  73          $this->grabber->prepare();    // maybe some initialization in grabber
  74          while ($content4id = $this->grabber->getItem()) {
  75  
  76              if ($debugfeed >= 8) {
  77                  print("\n<br>AA_Saver->run(): we have item to store, hurray! -- ". $content4id->getItemID());
  78              }
  79  
  80              $id_mode    = ($this->id_mode    == 'by_grabber') ? $this->grabber->getIdMode()    : $this->id_mode;
  81              $store_mode = ($this->store_mode == 'by_grabber') ? $this->grabber->getStoreMode() : $this->store_mode;
  82  
  83              switch ($id_mode) {
  84                  // Create new item id (always the same for item-slice pair)
  85                  case 'combined' : $new_item_id = string2id($content4id->getItemID(). $this->slice_id); break;
  86  
  87                  // Use id from source
  88                  case 'old'      : $new_item_id = $content4id->getItemID(); break;
  89  
  90                  // Generate completely new id
  91                  default         :
  92                  case 'new'      : $new_item_id = new_id();                 break;
  93              }
  94  
  95              $old_item_id = $content4id->getItemID();
  96  
  97              // set the item to be recevied from remote node
  98              $content4id->setItemID($new_item_id);
  99  
 100              // @todo - move to translations
 101              if ( !is_null($this->slice_id) ) {
 102                  // for AA_Grabber_Form we have the slice_id already filled
 103                  $content4id->setSliceID($this->slice_id);
 104              }
 105              if ( $content4id->getPublishDate() <= 0 ) {
 106                  $content4id->setPublishDate(now());
 107              }
 108              if ( $content4id->getExpiryDate() <= 0 ) {
 109                  $content4id->setExpiryDate(now()+(60*60*24*365*10));
 110              }
 111  
 112  
 113              if ($debugfeed >= 3) {
 114                  print("\n<br>      ". $content4id->getValue('headline........'));
 115              }
 116              if ($debugfeed >= 8) {
 117                  print("\n<br>xmlUpdateItems:content4id="); huhl($content4id);
 118              }
 119  
 120              // id_mode - overwrite or insert_if_new
 121              // (the $new_item_id should not be changed by storeItem)
 122              if (!($new_item_id = $content4id->storeItem($store_mode))) {     // invalidatecache, feed
 123                  print("\n<br>AA_Saver->run(): storeItem failed or skiped duplicate");
 124              } else {
 125                  if ($debugfeed >= 1) {
 126                      print("\n<br>  + stored OK: ". $content4id->getValue('headline........'));
 127                  }
 128  
 129                  // @todo better check of new ids
 130                  if ($store_mode == 'insert') {
 131                      $this->_new_ids[] = $new_item_id;
 132                  } else {
 133                      $this->_updated_ids[] = $new_item_id;
 134                  }
 135  
 136  
 137                  // Update relation table to show where came from
 138                  if ($new_item_id AND $old_item_id AND ($new_item_id != $old_item_id)) {
 139                      AddRelationFeed($new_item_id, $content4id->getItemID());
 140                  }
 141              }
 142          } // while grabber->getItem()
 143          $this->grabber->finish();    // maybe some finalization in grabber
 144      }
 145  
 146      /** Returns array of long new saved ids */
 147      function newIds() {
 148          return $this->_new_ids;
 149      }
 150  
 151      /** toexecutelater function
 152       *  Toexecutelater - special function called from toexecute class
 153       *  - used for queued tasks (runed from cron)
 154       *  You can use $toexecute->later($saver, array(), 'feed_external') instead
 155       *  of calling $saver->run() - the saving will be planed for future
 156       */
 157      function toexecutelater() {
 158          return $this->run();
 159      }
 160  }
 161  
 162  
 163  /** AA_Grabber - Base class, which is used as abstraction for data input
 164   *  From this class we derive concrete data grabbers, like RSS, AARSS, CSV, ...
 165   *
 166   *  @todo this class should be abstract after we switch to PHP5
 167   */
 168  class AA_Grabber {
 169      var $messages = array();
 170  
 171      /** name function
 172       *  Name of the grabber - used for grabber selection box
 173       */
 174      function name() {}
 175  
 176      /** description function
 177       *  Description of the grabber - used as help text for the users.
 178       *  Description is in in HTML
 179       */
 180      function description() {}
 181  
 182      /** htmlSetting function
 183       *  HTML code for parameters - defines parameters of this grabber.
 184       *  Each grabber could have its own parameters (like separator for CSV, ...)
 185       * @param $input_prefix
 186       * @param $params
 187       */
 188      function htmlSetting($input_prefix, $params) {}
 189  
 190      /** getItem function
 191       *  Method called by the AA_Saver to get next item from the data input
 192       */
 193      function getItem() {}
 194  
 195      /** If AA_Saver::store_mode is 'by_grabber' then this method tells Saver,
 196       *  how to store the item.
 197       *  @see also getStoreMode() method
 198       */
 199      function getIdMode() {
 200          return 'combined';
 201      }
 202  
 203      /** If AA_Saver::store_mode is 'by_grabber' then this method tells Saver,
 204       *  how to store the item.
 205       *  @see also getIdMode() method
 206       */
 207      function getStoreMode() {
 208          return 'insert_if_new';
 209      }
 210  
 211      /** prepare function
 212       *  Possibly preparation of grabber - it is called directly before getItem()
 213       *  method is called - it means "we are going really to grab the data
 214       */
 215      function prepare() {}
 216  
 217      /** finish function
 218       *  Function called by AA_Saver after we get the last item from the data
 219       *  input
 220       */
 221      function finish()  {}
 222  
 223      /** message function
 224       *  Records Error/Information message
 225       * @param $text
 226       */
 227      function message($text) {
 228          $this->messages[] = $text;
 229      }
 230  
 231      /** report function
 232       * Print Error/Information messaages
 233       */
 234      function report()       {
 235          return join('<br>', $this->messages);
 236      }
 237      /** clear_report function
 238       *
 239       */
 240      function clear_report() {
 241          unset($this->messages);
 242          $this->messages = array();
 243      }
 244  }
 245  
 246  /** AA_Grabber_Csv - CSV (Comma Separated Values) format grabber
 247   *  From this class we derive concrete data grabbers, like RSS, AARSS, CSV, ...
 248   *
 249   *  @todo this class should be abstract after we switch to PHP5
 250   */
 251  class AA_Grabber_Csv {
 252  
 253      /** name function
 254       * Name of the grabber - used for grabber selection box
 255       */
 256      function name() {
 257          return _m('CSV');
 258      }
 259  
 260      /** description function
 261       *  Description of the grabber - used as help text for the users.
 262       *  Description is in in HTML
 263       */
 264      function description() {
 265          return _m('Import data from CSV (Comma Separated Values) format');
 266      }
 267  
 268      /** getItem function
 269       * Method called by the AA_Saver to get next item from the data input
 270       */
 271      function getItem() {}
 272  
 273      /** prepare function
 274       *  Possibly preparation of grabber - it is called directly before getItem()
 275       *  method is called - it means "we are going really to grab the data
 276       */
 277      function prepare() {}
 278  
 279      /** finish function
 280       *  Function called by AA_Saver after we get the last item from the data
 281       *  input
 282       */
 283      function finish()  {}
 284  }
 285  
 286  
 287  class AA_Grabber_Aarss extends AA_Grabber {
 288      var $feed_id;
 289      var $feed;
 290      var $name;
 291      var $slice_id;
 292      var $aa_rss;
 293      var $channel;
 294      var $map;
 295      var $cat_field_id;
 296      var $status_code_id;
 297      var $ext_categs;
 298      var $l_categs;
 299      var $r_slice_id;
 300      var $fire;
 301      /** AA_Grabber_Aarss function
 302       * @param $feed_id
 303       * @param $feed
 304       * @param $fire
 305       */
 306      function AA_Grabber_Aarss($feed_id, &$feed, $fire) {
 307          global $debugfeed;
 308  
 309          /** Process one feed and returns parsed RSS (both AA and other)
 310           *  in $this->aa_rss */
 311          $this->slice_id   = unpack_id128($feed['slice_id']);        // local slice id
 312          $this->r_slice_id = unpack_id128($feed['remote_slice_id']); // remote slice id
 313          $this->feed_id    = $feed_id;
 314          $this->feed       = $feed;
 315          $this->fire       = $fire;
 316      }
 317  
 318      /** name function
 319       *
 320       */
 321      function name() {
 322          return _m("AA RSS");
 323      }
 324      /** description function
 325       *
 326       */
 327      function description() {
 328          return _m("Grabs data from generic RSS or AA RSS (used for item exchange between different AA installations)");
 329      }
 330      /** setUrl function
 331       * @param $url
 332       */
 333      function setUrl($url) {
 334          $this->feed['server_url']  = $url;
 335      }
 336      /** setTime function
 337       * @param $time
 338       */
 339      function setTime($time) {
 340          $this->feed['newest_item'] = $time;
 341      }
 342      /** _getRssData function
 343       *
 344       */
 345      function _getRssData() {
 346          return http_fetch($this->feed['server_url']);
 347      }
 348      /** _getApcData function
 349       *
 350       */
 351      function _getApcData() {
 352          // for APC feeds we need to list all categories, which we want receive
 353          $this->ext_categs = GetExternalCategories($this->feed_id); // we will need it later
 354  
 355          // select external categories in format
 356          // array('unpacked_cat_id'=> array( 'value'=>, 'name'=>, 'approved'=>, 'target_category_id'=>))
 357          $cat_ids = array();
 358          if ($this->ext_categs AND is_array($this->ext_categs)) {
 359              foreach ( $this->ext_categs as $ext_cat_id => $ext_cat ) {
 360                  if ( $ext_cat['target_category_id'] ) {  // the feeding is set for this categor
 361                      $cat_ids[] = $ext_cat_id;
 362                  }
 363              }
 364          }
 365  
 366          /* Mention, that $cat_ids now contain also AA_Other_Categor, which is
 367             used on oposite site of feeding as command to send all categories.
 368             The category list is sent from historical reasons (AA before 2.8
 369             do not send category informations without this array().
 370             Current AA use another approach for APC feeds - we will get all items
 371             regardless on category. The filtering we will do after that.
 372             This approach means more data to be transfered, but on the other hand
 373             there is no need to update filters after any category addition
 374             (Honzam 04/26/04) */
 375  
 376          // now we have cat_ids[] array => we can ask for data
 377          $categories2fed = implode(" ", $cat_ids);
 378  
 379          return xml_fetch($this->feed['server_url'], ORG_NAME, $this->feed['password'], $this->feed['user_id'], $this->r_slice_id, $this->feed['newest_item'], $categories2fed);
 380      }
 381      /** _getExactData function
 382       *
 383       */
 384      function _getExactData() {
 385          global $debugfeed;
 386  
 387          // get local item list (with last edit times)
 388          $slice       = AA_Slices::getSlice($this->slice_id);
 389          $local_list  = new LastEditList();
 390          $local_list->setFromSlice('', $slice);  // no conditions - all items
 391          $local_pairs = $local_list->getPairs();
 392  
 393          if ($debugfeed > 8) {
 394              huhl('_getExactData() - Local pairs:', $local_pairs);
 395          }
 396  
 397          $base["node_name"]       = ORG_NAME;
 398          $base["password"]        = $this->feed['password'];
 399          $base["user"]            = $this->feed['user_id'];
 400          $base["slice_id"]        = $this->r_slice_id;
 401          $base["start_timestamp"] = $this->feed['newest_item'];
 402          $base["exact"]           = 1;
 403  
 404          $init = $base;
 405          $init['conds[0][last_edit.......]'] = 1;
 406          $init['conds[0][value]']            = iso8601_to_unixstamp($this->feed['newest_item']);
 407          $init['conds[0][operator]']         = '>=';
 408  
 409          $remote_list  = new LastEditList();
 410          $remote_list->setList(http_fetch($this->feed['server_url'], $init));
 411          $remote_pairs = $remote_list->getPairs();
 412  
 413          if ($debugfeed > 8) {
 414              huhl('_getExactData() - Remote pairs:', $remote_pairs);
 415          }
 416  
 417          // Get all ids, which was updated later than items in local slice
 418          $ids = array();   // initialize
 419          foreach ($remote_pairs as $id => $time) {
 420              if (!isset($local_pairs[$id]) OR ($local_pairs[$id] < $time)) {
 421                  $ids[] = $id;  // array of ids to ask for
 422              }
 423          }
 424  
 425          if ($debugfeed >= 2) {
 426              huhl(' Local items: ', count($local_pairs), ' Remote items: ', count($remote_pairs), ' Asked for update: ', count($ids));
 427          }
 428  
 429          // No items to fed?
 430          if (count($ids) <= 0) {
 431              return '';
 432          }
 433  
 434          $finish        = $base;
 435          $finish['ids'] = implode('-',$ids);
 436  
 437          if ($debugfeed > 8) {
 438              huhl('_getExactData() - http_fetch:', $this->feed['server_url'], $finish);
 439          }
 440  
 441          return http_fetch($this->feed['server_url'], $finish);
 442      }
 443  
 444      /** prepare function
 445       *  Fetch data and parse it
 446       */
 447      function prepare() {
 448          global $DEFAULT_RSS_MAP, $debugfeed;
 449  
 450          // just shortcut
 451          $feed_type = $this->feed['feed_type'];
 452  
 453          set_time_limit(240); // Allow 4 minutes per feed
 454  
 455          $slice           = AA_Slices::getSlice($this->slice_id);
 456          $feed_debug_name = 'Feed #'. $this->feed_id .' ('. getFeedTypeName($feed_type).'): '.
 457                             $this->feed['name'] .' : ' .$this->feed['remote_slice_name'].
 458                             ' -> '.$slice->name();
 459          // Get XML Data
 460          if ($debugfeed >= 1) {
 461              print("\n<br>$feed_debug_name");
 462          }
 463  
 464          switch($feed_type) {
 465              case FEEDTYPE_RSS:   $xml_data = $this->_getRssData();   break;
 466              case FEEDTYPE_EXACT: $xml_data = $this->_getExactData(); break;
 467              case FEEDTYPE_APC:
 468              default:             $xml_data = $this->_getApcData();   break;
 469          }
 470  
 471          // Special option - it only dispays fed data
 472          if ($this->fire == 'display') {
 473              echo $xml_data;
 474              return false;
 475          }
 476  
 477          if (!$xml_data) {
 478              AA_Log::write("CSN","No data returned for $feed_debug_name");
 479              if ($debugfeed >= 1) print("\n<br>$feed_debug_name: no data returned");
 480              return false;
 481          }
 482          if ($debugfeed >= 8) huhl("Fetched data=",htmlspecialchars($xml_data));
 483  
 484          // if an error occured, write it to the LOG
 485          if (substr($xml_data,0,1) != "<") {
 486              AA_Log::write("CSN","Feeding mode ($feed_debug_name): $xml_data");
 487              if ($debugfeed >= 1) {
 488                  print("\n<br>$feed_debug_name:bad data returned: $xml_data");
 489              }
 490              return false;
 491          }
 492  
 493          /** $g_slice_encoding is passed to aa_rss_parse() - it defines output character encoding */
 494          $GLOBALS['g_slice_encoding'] = getSliceEncoding($this->slice_id);
 495  
 496          if (!( $this->aa_rss = aa_rss_parse( $xml_data ))) {
 497              AA_Log::write("CSN","Feeding mode ($feed_debug_name): Unable to parse XML data");
 498              if ($debugfeed >= 1) print("\n<br>$feed_debug_name:".$feed['server_url'].":unparsable: <hr>".htmlspecialchars($xml_data)."<hr>");
 499              return false;
 500          }
 501  
 502          if ($debugfeed >= 5) {
 503              print("\n<br>Parses ok");
 504          }
 505  
 506          //  --- output parsed - great! - we are going to store
 507  
 508          $this->l_categs   = GetGroupConstants($this->slice_id);       // category definitions
 509                                                            // - used only for FEEDTYPE_APC
 510  
 511          if ($feed_type == FEEDTYPE_APC) {
 512              // Update the slice categories in the ef_categories table,
 513              // that is, if the set of possible slice categories has changed
 514              updateCategories($this->feed_id, $this->l_categs, $this->ext_categs, $this->aa_rss['channels'][$this->r_slice_id]['categories'], $this->aa_rss['categories']);
 515          }
 516  
 517          if (($feed_type == FEEDTYPE_APC) OR ($feed_type == FEEDTYPE_EXACT)) {
 518              //Update the field names and add new fields to feedmap table
 519              updateFieldsMapping($this->feed_id, $this->slice_id, $this->r_slice_id, $this->aa_rss['channels'][$this->r_slice_id]['fields'],$this->aa_rss['fields']);
 520          }
 521  
 522          // Find channel definition
 523          if (!($this->channel = $aa_rss['channels'][$this->r_slice_id])) {
 524              while (list(,$this->channel) = each($this->aa_rss['channels'])) {
 525                  if ($this->channel) {
 526                     break;
 527                  }
 528              }
 529          }
 530  
 531          list(,$map) = GetExternalMapping($this->slice_id,$this->r_slice_id);
 532          if (!$map && ($feed_type == FEEDTYPE_RSS)) {
 533              $map = $DEFAULT_RSS_MAP;
 534          }
 535          $this->map = $map;
 536  
 537          // Use the APC specific fields from the item
 538          if ($feed_type == FEEDTYPE_APC) {
 539              $this->cat_field_id   = GetBaseFieldId( $this->aa_rss['fields'], "category" );
 540              $this->status_code_id = GetBaseFieldId( $this->aa_rss['fields'], "status_code" );
 541          }
 542  
 543          if (is_array($this->aa_rss['items'])) {
 544              reset($this->aa_rss['items']);
 545          }
 546  
 547      }
 548      /** getItem function
 549       *
 550       */
 551      function getItem() {
 552          if (!is_array($this->aa_rss['items'])) {
 553              return false;
 554          }
 555  
 556          if (!($item = current($this->aa_rss['items']))) {
 557              return false;
 558          }
 559          $item_id = key($this->aa_rss['items']);
 560  
 561          // A series of steps to make field specific edits
 562          // set fulltext field back from the content field, where it was put by
 563          // APC for RSS compatability
 564          if ($fulltext_field_id = GetBaseFieldId($this->aa_rss['fields'],"full_text")) {
 565              $item['fields_content'][$fulltext_field_id][0] = contentvalue($item);
 566          }
 567  
 568          /** Apply filters - rename categories and bin (approved/holding/trash) */
 569          if ($this->feed['feed_type'] == FEEDTYPE_APC) { // Use the APC specific fields from the item
 570  
 571              // apply categories mapping. $item is updated accordingly
 572              $approved = translateCategories( $this->cat_field_id, $item, $this->ext_categs, $this->l_categs );
 573  
 574              // set status_code - according to the settings of ef_categories table
 575              // RSS feeds have approved set from DEFAULT_RSS_MAP
 576              $item['fields_content'][$this->status_code_id][0]['value'] = $approved ? 1 : 2;
 577          }
 578  
 579  
 580          // create item from source data (in order we can unalias)
 581          $item2fed = new AA_Item($item['fields_content'], array());
 582  
 583          foreach ( $this->map as $to_field_id => $v) {
 584              switch ($v['feedmap_flag']) {
 585                  case FEEDMAP_FLAG_VALUE:
 586                              // value could contain {switch()} and other {constructs}
 587                              $content4id[$to_field_id][0]['value'] = $item2fed->unalias($v['value']);
 588                              break;
 589                  case FEEDMAP_FLAG_EXTMAP:   // Check this really works when val in from_field_id
 590                  case FEEDMAP_FLAG_RSS:
 591                              $values = map1field($v['value'],$item,$this->channel);
 592                              if (isset($values) && is_array($values)) {
 593                                  while (list($k,$v2) = each($values)) {
 594                                      $values[$k]['value'] = $v2['value'];
 595                                  }
 596                                  $content4id[$to_field_id] = $values;
 597                              }
 598                              break;
 599              } // switch
 600          } // while each($map)
 601  
 602          next($this->aa_rss['items']);
 603  
 604          $ic = new ItemContent($content4id);
 605          $ic->setItemValue('externally_fed', $this->feed['name']);  // TODO - move one layer up - to saver transactions
 606          $ic->setItemId($item_id);
 607          return $ic;
 608      }
 609      /** finish function
 610       *
 611       */
 612      function finish() {
 613          if ($this->feed['feed_type'] == FEEDTYPE_APC) {
 614              $db = getDB();
 615              //update the newest item
 616              $SQL = "UPDATE external_feeds SET newest_item='".quote($this->aa_rss['channels'][$this->r_slice_id]['timestamp'])."'
 617                       WHERE feed_id='".quote($this->feed_id)."'";
 618              $db->tquery($SQL);
 619              freeDB($db);
 620          }
 621      }
 622  }
 623  
 624  /** AA_Grabber_Form - Grabbs data POSTed by AA form
 625  *
 626  *  The format of the data is followiing
 627  *  (this is new format, which allows to fill or modify more items at once
 628  *
 629  *   Format is:
 630  *       aa[i<long_item_id>][modified_field_id][]
 631  *   Note:
 632  *      first brackets contain
 633  *          'u'+long_item_id when item is edited (the field is rewriten, rest
 634  *                           of item is untouched)
 635  *          'i'+long_item_id when item is edited (the value is added to current
 636  *                           value of the field, rest of item is untouched)
 637  *          'n<number>_long_slice_id' if you want to add the item to slice_id
 638  *                                    <number> is used to add more than one
 639  *                                    item at the time
 640  *      modified_field_id is field_id, where all dots are replaced by '_'
 641  *      we always add [] at the end, so it becames array at the end
 642  *   Example:
 643  *       aa[u63556a45e4e67b654a3a986a548e8bc9][headline________][]
 644  *       aa[i63556a45e4e67b654a3a986a548e8bc9][relation_______1][]
 645  *       aa[n1_54343ea876898b6754e3578a8cc544e6][publish_date____][]
 646  *
 647  *   There could be also compound widgets, which consists from more than one
 648  *   input - just like date selector. In such case we use following syntax:
 649  *       aa[n1_54343ea876898b6754e3578a8cc544e6][publish_date____][dte][d][]
 650  *       aa[n1_54343ea876898b6754e3578a8cc544e6][publish_date____][dte][m][]
 651  *       aa[n1_54343ea876898b6754e3578a8cc544e6][publish_date____][dte][y][]
 652  *   where "dte" points to the AA_Widget_Dte. The method AA_Widget_Dte::getValue()
 653  *   is called to grab the value (or multivalues) from the submitted form
 654  */
 655  class AA_Grabber_Form {
 656      var $_items;
 657      var $_last_store_mode;
 658  
 659      function AA_Grabber_Form() {
 660          $_items = array();
 661      }
 662  
 663      /** Name of the grabber - used for grabber selection box */
 664      function name() { return _m('Form'); }
 665  
 666      /** Description of the grabber - used as help text for the users.
 667       *  Description is in in HTML
 668       */
 669      function description() { return _m('Grabbs data POSTed by AA form'); }
 670  
 671      /** If AA_Saver::store_mode is 'by_grabber' then this method tells Saver,
 672       *  how to store the item.
 673       *  @see also getStoreMode() method
 674       */
 675      function getIdMode() {
 676          return 'old';
 677      }
 678  
 679      /** If AA_Saver::store_mode is 'by_grabber' then this method tells Saver,
 680       *  how to store the item.
 681       *  @see also getIdMode() method
 682       */
 683      function getStoreMode() {
 684          switch ($this->_last_store_mode) {
 685              case 'add':    return 'add';
 686              case 'update': return 'update';
 687          }
 688          // case 'new':
 689          return 'insert';
 690      }
 691  
 692      /** Method called by the AA_Saver to get next item from the data input */
 693      function getItem() {
 694          if (!($tostore = current($this->_items))) {
 695              return false;
 696          }
 697          next($this->_items);
 698          $this->_last_store_mode = $tostore[1];
 699          return $tostore[0];
 700      }
 701  
 702      /** Possibly preparation of grabber - it is called directly before getItem()
 703       *  method is called - it means "we are going really to grab the data
 704       */
 705      function prepare() {
 706          $this->_items = array();
 707          if (!isset($_POST['aa']) OR !is_array($_POST['aa'])) {
 708              return;
 709          }
 710  
 711          /** the item ids are in the form of i<item_id> for edited items,
 712           *  or n<number>_<slice_id> for new item.
 713           *  We have to construct translation table of the ids
 714           */
 715          $id_trans_table = array();
 716  
 717          $aa = $_POST['aa'];
 718  
 719          // just prepare ids, in order we can expand
 720          // You can use _#n1_623553373823736362372726 as value, which stands for
 721          // item id of the item
 722          foreach ( $aa as $dirty_item_id => $item_fields) {
 723              if ( $dirty_item_id{0} == 'n' ) {
 724                  $id_trans_table['_#'.$dirty_item_id] = new_id();
 725              }
 726          }
 727          $trans_item_alias = array_keys($id_trans_table);
 728          $trans_item_ids   = array_values($id_trans_table);
 729  
 730          foreach ( $aa as $dirty_item_id => $item_fields) {
 731  
 732              // common fields
 733              if ($dirty_item_id == 'all' ) {
 734                  continue;
 735              }
 736              // edited item - update = field content is changed to new value
 737              elseif ( $dirty_item_id{0} == 'u' ) {
 738                  $item_id    = substr($dirty_item_id, 1);
 739                  $store_mode = 'update';
 740                  $item = AA_Item::getItem($item_id);
 741                  $item_fields['slice_id________'] = pack_id($item->getSliceId());
 742              }
 743              // edited item - insert = field content is added to the existing content of the field
 744              elseif ( $dirty_item_id{0} == 'i' ) {
 745                  $item_id    = substr($dirty_item_id, 1);
 746                  $store_mode = 'add';
 747                  $item = AA_Item::getItem($item_id);
 748                  $item_fields['slice_id________'] = pack_id($item->getSliceId());
 749              }
 750              // new items
 751              else {
 752                  $item_id    = $id_trans_table['_#'.$dirty_item_id];
 753                  $store_mode = 'new';
 754  
 755                  //grabb slice_id of new item
 756                  $item_slice_id = substr($dirty_item_id, strpos($dirty_item_id, '_')+1);
 757                  // and add slice_id field to the item
 758                  $item_fields['slice_id________'] = array(pack_id($item_slice_id));
 759              }
 760              $id_trans_table[$dirty_item_id] = $item_id;
 761  
 762              // now fill the ItemContent for each item and tepmorary store it into $this->_items[]
 763              $item = new ItemContent();
 764              $item->setItemID($item_id);
 765  
 766              // join common fields (the specific fields win in the battle of common and specific content)
 767              if ( isset($aa['all']) ) {
 768                  $item_fields = array_merge($aa['all'], $item_fields);
 769              }
 770              foreach ($item_fields as $dirty_field_id => $val_array) {
 771                  // get the content of the field (values and flags)
 772                  $aa_value = AA_Widget::getValue($val_array);
 773  
 774                  $aa_value->replaceInValues($trans_item_alias, $trans_item_ids);
 775  
 776                  // create full_text......1 from full_text______1
 777                  $field_id = AA_Field::getFieldIdFromVar($dirty_field_id);
 778                  $item->setFieldValue($field_id, $aa_value);
 779              }
 780              $this->_items[] = array($item, $store_mode);
 781          }
 782  
 783          reset ($this->_items);
 784      }
 785  
 786  
 787      /** Function called by AA_Saver after we get the last item from the data
 788       *  input
 789       */
 790      function finish()  {
 791          $this->_items = array();
 792      }
 793  }
 794  
 795  
 796  /** AA_Grabber_Iekis_Xml - grabs data from XML files in one directory
 797   */
 798  class AA_Grabber_Iekis_Xml extends AA_Grabber {
 799  
 800      var $dir;                   /** directory, where teh files are */
 801      var $_files;                /** list if files to grab - internal array */
 802  
 803      function AA_Grabber_Iekis_Xml($dir) {
 804          $this->dir = $dir;
 805      }
 806  
 807      /** Name of the grabber - used for grabber selection box */
 808      function name() { return _m('iEKIS XML files'); }
 809  
 810      /** Description of the grabber - used as help text for the users.
 811       *  Description is in in HTML
 812       */
 813      function description() { return _m('special iEKIS XML files in one directory'); }
 814  
 815       /** Possibly preparation of grabber - it is called directly before getItem()
 816       *  method is called - it means "we are going really to grab the data
 817       */
 818      function prepare() {
 819          $this->_files = array();
 820          // instance of class iCalFile (external file ical.php)
 821          if ($handle = opendir($this->dir)) {
 822              while (false !== ($file = readdir($handle))) {
 823                  if ($file != "." && $file != "..") {
 824                      $this->_files[] = $file;
 825                  }
 826              }
 827              closedir($handle);
 828          }
 829          sort($this->_files);
 830      }
 831  
 832      /** Method called by the AA_Saver to get next item from the data input */
 833      function getItem() {
 834          if (!($file = current($this->_files))) {
 835              return false;
 836          }
 837          next($this->_files);
 838  
 839          $xml = simplexml_load_file($this->dir .$file);
 840          $att = $xml->attributes();
 841  
 842          foreach ($xml->text as $key => $text) {
 843              $text_att = $text->attributes();
 844              switch ($text_att['typ']) {
 845                  case 'otazka':  $t0a = $text_att; $t0 = (string)$text; break;
 846                  case 'odpoved': $t1a = $text_att; $t1 = (string)$text; break;
 847              }
 848          }
 849  
 850          $item = new ItemContent();
 851          $item->setValue('number.........1', $att['idp']);
 852          $item->setValue('unspecified.....', $att['obor']);
 853          $item->setValue('publish_date....', strtotime($att['datum'].' '.$att['cas']));
 854          $item->setValue('post_date.......', strtotime($att['datum'].' '.$att['cas']));
 855          $item->setValue('unspecified....1', $att['stav']);
 856          $item->setValue('unspecified....2', $att['kod']);
 857          $item->setValue('unspecified....3', $att['pristupne']);
 858          $item->setValue('headline........', $att['predmet']);
 859          $item->setValue('text...........1', $t0a['jmeno']);
 860          $item->setValue('con_email.......', $t0a['email']);
 861          $item->setValue('address.........', $t0a['kontakt']);
 862          $item->setValue('unspecified....4', $t0a['predmet']);
 863          $item->setValue('start_date......', strtotime($t1a['datum'].' '.$t1a['cas']));
 864          $item->setValue('unspecified....5', $t1a['expert']);
 865          $item->setValue('unspecified....6', $t1a['predmet']);
 866          $item->setValue('text...........4', $t0);
 867          $item->setValue('text...........5', $t1);
 868          $item->setValue('edit_note.......', 'importovano ze stareho i-ekis.cz - '. $file);
 869          $item->setValue('switch.........2', '1');  // ulozit pro mpo
 870          $item->setValue('switch..........', '0');  // storno
 871  
 872          $TEMAS = array(
 873                       '1' => 'b2269049caf8e47737b718e62ccc905c',   // Územní energetické koncepce
 874                       '2' => 'b2269049caf8e47737b718e62ccc905c',   // Akční plány
 875                       '3' => 'afbab0cf8bfb524ce48e50862fb8fa88',   // Energetické audity a průkazy (99)
 876                       '4' => 'b2325f0658cab17838f8ce6e49a26688',   // Kotle a kotelny (524)
 877                       '5' => '09952314df2e76d4fc9cd1dc8baec9ae',   // Energie slunce (237)
 878                       '6' => '144f1726c94eb7e86a491dea2bc84021',   // Energie vody (131)
 879                       '7' => 'ae02cc88721e77af713d30c766834e9f',   // Energie větru (180)
 880                       '8' => '1754f99f9d83562c81d99a28818cf585',   // Energie biomasy (332)
 881                       '9' => '1754f99f9d83562c81d99a28818cf585',   // Využití bioplynů (35)
 882                      '10' => '18804c2b8e611fba74ceb46038494e68',   // Využití odpadního tepla (13)
 883                      '11' => '442340d0d7ff8a68c76902a2da083d44',   // Tepelná čerpadla (153)
 884                      '12' => '5f4fe6025c68814d449f29e3f1cdd01a',   // Palivové články (6)
 885                      '13' => '49282fdb6ee5d9c524cd5552417b855a',   // Elektrické vytápění (247)
 886                      '14' => '1b2fbed9465f609835c51841620d8b6a',   // Kogenerace, trigenerace (35)
 887                      '15' => '5941e5f49d61ac033130660ea394122d',   // Měření a regulace (594)
 888                      '16' => 'b2269049caf8e47737b718e62ccc905c',   // Rekonstrukce rozvodů sídlištního celku
 889                      '17' => 'b2269049caf8e47737b718e62ccc905c',   // Rekonstrukce otopné soustavy v objektu
 890                      '18' => '5f93ea7654fafea8cf29ddb8b80351ef',   // Úsporná opatření v průmyslu (12)
 891                      '19' => 'b2269049caf8e47737b718e62ccc905c',   // Monitoring a targeting (1)
 892                      '20' => 'b2269049caf8e47737b718e62ccc905c',   // Moderní postupy, technologie a materiály
 893                      '21' => 'a8e078b5bf57ec58a2c7245f71f0d3d4',   // Zateplování objektů (2101)
 894                      '22' => '15efaadbec739b0965a098da205a0d31',   // Nízkoenergetické a pasivní domy (179)
 895                      '23' => '3c3e0d17813eccc67afd3a267329595a',   // Projekty energetických služeb se zárukou
 896                      '24' => '3c3e0d17813eccc67afd3a267329595a',   // Financování z fondů Evropské unie
 897                      '25' => 'b2269049caf8e47737b718e62ccc905c'    // Ostatní (536)
 898                      );
 899  
 900          if ($TEMAS[(string)$att['obor']]) {
 901              $item->setValue('relation.......2', $TEMAS[(string)$att['obor']]);
 902          }
 903  
 904          return $item;
 905      }
 906  
 907  }
 908  
 909  /** AA_Grabber_Slice - grabs data from slice based on AA_Set
 910   *  Right now we use it mainly for apc-aa/admin/se_export.php
 911   */
 912  class AA_Grabber_Slice extends AA_Grabber {
 913  
 914      var $set;                 /** AA_Set specifies the slice, conds and sort */
 915      var $_longids;            /** list if files to grab - internal array */
 916      var $_content_cache;      /**  */
 917      var $_index;              /**  */
 918  
 919      function AA_Grabber_Slice($set) {
 920          $this->set            = $set;
 921          $this->_longids       = array();
 922          $this->_content_cache = array();
 923          $this->_index         = 0;
 924      }
 925  
 926      /** Name of the grabber - used for grabber selection box */
 927      function name() { return _m('Items from slice'); }
 928  
 929      /** Description of the grabber - used as help text for the users.
 930       *  Description is in in HTML
 931       */
 932      function description() { return _m('grabs items form some slice'); }
 933  
 934       /** Possibly preparation of grabber - it is called directly before getItem()
 935       *  method is called - it means "we are going really to grab the data
 936       */
 937      function prepare() {
 938          $zids                 = QuerySet($this->set);
 939          $this->_longids       = $zids->longids();
 940          $this->_content_cache = array();
 941          $this->_index         = 0;
 942          reset($this->_longids);   // go to first long id
 943      }
 944  
 945      /** Method called by the AA_Saver to get next item from the data input */
 946      function getItem() {
 947          if (!($longid = $this->_longids[$this->_index])) {
 948              return false;
 949          }
 950          if (empty($this->_content_cache[$longid])) {
 951              $this->_fillCache();
 952          }
 953  
 954          $this->_index++;
 955          return new ItemContent($this->_content_cache[$longid]);
 956      }
 957  
 958      /** speedup */
 959      function _fillCache() {
 960          // read next 100 items (we can laborate with cache sice in future to get even better performance)
 961          $this->_content_cache = GetItemContent(new zids( array_slice($this->_longids, $this->_index, 100), 'l'));
 962      }
 963  
 964      function finish() {
 965          $this->_longids = array();
 966      }
 967  }
 968  
 969  
 970  /** AA_Grabber_Ical - iCal  calendar format grabber
 971   *  could be called like
 972   *     $a = new AA_Grabber_Ical('http://example.org/calendar.ics');
 973   */
 974  class AA_Grabber_Ical extends AA_Grabber {
 975  
 976      var $url;                   /** URL of .ics file */
 977      var $ical;                  /** instance iCalFile */
 978      var $vCalPos;               /** pointer of vCalendar */
 979      var $vComponentsTypePos;    /** pointer of type components */
 980      var $vComponentsPos;        /** pointer of components */
 981  
 982  
 983      function AA_Grabber_Ical($url){
 984          $this->url=$url;
 985      }
 986        /** Name of the grabber - used for grabber selection box */
 987      function name() { return _m('iCal'); }
 988  
 989      /** Description of the grabber - used as help text for the users.
 990       *  Description is in in HTML
 991       */
 992      function description() { return _m('Import data from iCal (.ics) format'); }
 993  
 994       /** Possibly preparation of grabber - it is called directly before getItem()
 995       *  method is called - it means "we are going really to grab the data
 996       */
 997      function prepare() {
 998          // instance of class iCalFile (external file ical.php)
 999          $this->ical = new iCalFile($this->url);
1000          // set pointers
1001          $this->vCalPos = 0;
1002          $this->vComponentsPos =0;
1003          $this->vComponentsTypePos =0;
1004      }
1005  
1006      /** Method called by the AA_Saver to get next item from the data input */
1007      function getItem() {
1008          // set pointers
1009          $vCalPos =0;
1010          $vComponentsPos =0;
1011          $vComponentsTypePos =0;
1012  
1013          //TODO solve empty ical->components exception ( case of empty or wrong ics file)
1014  
1015          //check if ical->components isn't empty (case of empty or wrong ics file)
1016          if (isset($this->ical->components['VCALENDAR'])){
1017              //get $vcalendar index
1018              foreach ($this->ical->components['VCALENDAR'] as $vcalKey => $vcalItem ) {
1019                  if ($vCalPos < $this->vCalPos) {$vCalPos++; continue;}
1020                      //chek if vcalItem-> isn't empty
1021                      if (isset($vcalItem->components)){
1022                          //get keys of components type
1023                          foreach ($vcalItem->components as $componentTypeKey => $componentTypeItem) {
1024  
1025                              if ($vComponentsTypePos < $this->vComponentsTypePos)  { $vComponentsTypePos++; $vComponentsPos=0; continue;}
1026                              //insert type of component
1027                              $content4id['type'][0]['value']=$componentTypeKey;
1028                                  //get index of components key
1029                              foreach ($componentTypeItem as $componentKey => $componentItem) {
1030  
1031                                  if ($vComponentsPos < $this->vComponentsPos) {$vComponentsPos++;  continue; }
1032                                  //check if is set componentItem->components
1033                                  if (isset( $componentItem->components )) {
1034                                      //get keys of properties
1035                                      foreach ($componentItem->components as $valueKey => $valueArray) {
1036                                          //get index of properties
1037                                          foreach ($valueArray as $valueIndex => $valueItem) {
1038                                              //check if exists method get_value()
1039                                              if (method_exists($valueItem, 'get_value')) {
1040                                                  //fill array $content4id
1041                                                  $content4id[$valueKey][$valueIndex]['value']=$valueItem->get_value();
1042                                              }
1043                                          }
1044                                      }
1045  
1046                                      // instance of ItemContent with array content4id
1047                                      $ic = new ItemContent($content4id);
1048                                      //unset array content4id
1049                                      unset($content4id);
1050  
1051                                      $vComponentsPos++;
1052                                      $this->vCalPos=$vCalPos;
1053                                      $this->vComponentsPos=$vComponentsPos;
1054                                      $this->vComponentsTypePos=$vComponentsTypePos;
1055                                      return $ic;
1056                                  }
1057  
1058                                  $vComponentsPos++;
1059                              }
1060  
1061                              $vComponentsTypePos++;
1062                              $vComponentsPos=0;
1063                              if ($vComponentsTypePos > $this->vComponentsTypePos) {$this->vComponentsPos=0;}
1064                          }
1065  
1066                      }
1067                      $vCalPos++;
1068                      $vComponentsPos=0;
1069                      $vComponentsTypePos =0;
1070              }
1071          }
1072          return 0;
1073      }
1074  }
1075  ?>

title

Description

title

Description

title

Description

title

title

Body