Merge branch 'pu/2013.10-caldav' into 2013.10
authorPhilipp Schüle <p.schuele@metaways.de>
Wed, 22 Oct 2014 08:59:53 +0000 (10:59 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Wed, 22 Oct 2014 08:59:53 +0000 (10:59 +0200)
Conflicts:
tine20/Calendar/Backend/Sql.php
tine20/Calendar/Model/Rrule.php
tine20/Calendar/Setup/Update/Release8.php
tine20/Calendar/Setup/setup.xml

Change-Id: I0f2bba1f5200ed93f65f1956e8e965132cd1d8d2

14 files changed:
1  2 
tests/tine20/Calendar/JsonTests.php
tests/tine20/Felamimail/Frontend/JsonTest.php
tine20/ActiveSync/Controller/Abstract.php
tine20/ActiveSync/Controller/Calendar.php
tine20/Calendar/Backend/Sql.php
tine20/Calendar/Controller.php
tine20/Calendar/Controller/MSEventFacade.php
tine20/Calendar/Model/Rrule.php
tine20/Calendar/Setup/Update/Release8.php
tine20/Calendar/Setup/setup.xml
tine20/Tinebase/Backend/Sql/Abstract.php
tine20/Tinebase/Container.php
tine20/Tinebase/Server/WebDAV.php
tine20/Tinebase/User.php

Simple merge
@@@ -147,13 -152,10 +152,12 @@@ class Calendar_Backend_Sql extends Tine
       * @param  Tinebase_Model_Filter_FilterGroup    $_filter
       * @param  Tinebase_Model_Pagination            $_pagination
       * @param  boolean                              $_onlyIds
-      * @param  bool   $_getDeleted
       * @return Tinebase_Record_RecordSet|array
       */
-     public function search(Tinebase_Model_Filter_FilterGroup $_filter = NULL, Tinebase_Model_Pagination $_pagination = NULL, $_onlyIds = FALSE, $_getDeleted = FALSE)    
+     public function search(Tinebase_Model_Filter_FilterGroup $_filter = NULL, Tinebase_Model_Pagination $_pagination = NULL, $_onlyIds = FALSE)
      {
 +        if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Searching events ...');
 +        
          if ($_pagination === NULL) {
              $_pagination = new Tinebase_Model_Pagination();
          }
          $select->group($this->_tableName . '.' . 'id');
          Tinebase_Backend_Sql_Abstract::traitGroup($select);
          
 +        $period = $_filter->getFilter('period');
 +
 +        // filter out unnecessary YEARLY candidates for web client requests
 +        // periods < 40 days should be client web client requests.
 +        if ($period && $period->getFrom()->getClone()->addDay(40) > $period->getUntil()) {
 +            $this->_removeNonMatchingBaseEvents($select, $period);
 +        }
 +        
+         if ($calendarFilter) {
+             $select1 = clone $select;
+             $select2 = clone $select;
+             
+             $calendarFilter->appendFilterSql1($select1, $this);
+             $calendarFilter->appendFilterSql2($select2, $this);
+             
+             $select = $this->getAdapter()->select()->union(array(
+                 $select1,
+                 $select2
+             ));
+         }
+         
+         $_pagination->appendPaginationSql($select);
+         
          $stmt = $this->_db->query($select);
          $rows = (array)$stmt->fetchAll(Zend_Db::FETCH_ASSOC);
-         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ 
-                 . ' Event base rows fetched: ' . count($rows));
          
          $result = $this->_rawDataToRecordSet($rows);
 +        
 +        $this->_checkGrants($result, $grantsFilter);
 +        
 +        return $_onlyIds ? $result->{is_bool($_onlyIds) ? $this->_getRecordIdentifier() : $_onlyIds} : $result;
 +    }
 +    
 +    /**
 +     * removes non-matching rrule base events
 +     * 
 +     * @param Zend_Db_Select $select
 +     * @param Calendar_Model_PeriodFilter $period
 +     * 
 +     * TODO improve this by moving the rrules to a separate table to simplify SQL statment
 +     */
 +    protected function _removeNonMatchingBaseEvents($select, $period)
 +    {
 +        $gs = new Tinebase_Backend_Sql_Filter_GroupSelect($select);
 +        $from = $period->getFrom()->getClone()->subDay(1);
 +        $fromMonth = $from->format('n');
 +        $fromDay = $from->format('j');
 +        $until = $period->getUntil()->getClone()->addDay(1);
 +        $untilMonth = $until->format('n');
 +        $untilDay = $until->format('j');
 +        $quotedRrule = $this->_db->quoteIdentifier('rrule');
 +        
 +        $gs->where($quotedRrule . ' NOT LIKE ?', 'FREQ=YEARLY%')
 +        ->orWhere($quotedRrule . ' IS NULL');
 +        
 +        if ($fromMonth == $untilMonth && $untilDay-$fromDay <= 10) {
 +            // day|week view
 +            for($day=$fromDay; $day<=$untilDay; $day++) {
 +                $gs->orWhere($quotedRrule . ' LIKE ?', "FREQ=YEARLY;INTERVAL=1;BYMONTH={$fromMonth};BYMONTHDAY={$day}%");
 +            }
 +        } else {
 +            // monthview
 +            for ($month=$fromMonth; $month<=$untilMonth; $month++) {
 +                $gs->orWhere($quotedRrule . ' LIKE ?', "FREQ=YEARLY;INTERVAL=1;BYMONTH={$month};%");
 +            }
 +        }
 +        
 +        $gs->appendWhere(Zend_Db_Select::SQL_AND);
 +        //            Tinebase_Core::getLogger()->ERR($select);
 +    }
 +    
 +    /**
 +     * calculate event permissions and remove events that don't match
 +     * 
 +     * @param Tinebase_Record_RecordSet $result
 +     * @param Tinebase_Model_Filter_AclFilter $grantsFilter
 +     */
 +    protected function _checkGrants($result, $grantsFilter)
 +    {
          $clones = clone $result;
          
          Tinebase_Container::getInstance()->getGrantsOfRecords($clones, Tinebase_Core::getUser());
Simple merge
@@@ -638,31 -738,19 +740,35 @@@ class Calendar_Controller_MSEventFacad
       */
      protected function _filterAttendeeWithoutEmail($event)
      {
+         if (! $event->attendee instanceof Tinebase_Record_RecordSet) {
+             return;
+         }
          $this->_fillResolvedAttendeeCache($event);
          
 -        $filteredAttendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender');
 -        foreach ($event->attendee->getEmail() as $idx => $email) {
 -            if ($email) {
 -                $filteredAttendee->addRecord($event->attendee[$idx]);
 +        foreach ($event->attendee as $attender) {
 +            $cacheId = $attender['user_type'] . $attender['user_id'];
 +            
 +            // value is in array and true
 +            if (isset(self::$_attendeeEmailCache[$cacheId])) {
 +                continue;
 +            }
 +            
 +            // add value to cache if not existing already
 +            if (!array_key_exists($cacheId, self::$_attendeeEmailCache)) {
 +                self::$_attendeeEmailCache[$cacheId] = !!$attender->getEmail();
 +                
 +                // limit class cache to 100 entries
 +                if (count(self::$_attendeeEmailCache) > 100) {
 +                    array_shift(self::$_attendeeEmailCache);
 +                }
 +            }
 +            
 +            // remove entry if value is not true => attender has no email address
 +            if (!self::$_attendeeEmailCache[$cacheId]) {
 +                $event->attendee->removeRecord($attender);
              }
          }
 -        $event->attendee = $filteredAttendee;
      }
  
      /**
Simple merge
@@@ -165,26 -165,50 +165,74 @@@ class Calendar_Setup_Update_Release8 ex
      }
      
      /**
 -
+      * update to 8.4
+      * 
+      * - adds etag column
+      */
+     public function update_3()
+     {
+         $declaration = new Setup_Backend_Schema_Field_Xml('
+             <field>
+                 <name>etag</name>
+                 <type>text</type>
+                 <length>60</length>
+             </field>');
+         $this->_backend->addCol('cal_events', $declaration);
+         
+         $declaration = new Setup_Backend_Schema_Index_Xml('
+             <index>
+                 <name>etag</name>
+                 <field>
+                     <name>etag</name>
+                 </field>
+             </index>');
+         $this->_backend->addIndex('cal_events', $declaration);
+         $this->setTableVersion('cal_events', 7);
+         $this->setApplicationVersion('Calendar', '8.4');
+     }
-     public function update_3()
++    
+     /**
+      * adds external_seq col
+      * 
+      * @see 0009890: improve external event invitation support
+      */
+     public function update_4()
+     {
+         $seqCol = '<field>
+             <name>external_seq</name>
+             <type>integer</type>
+             <notnull>true</notnull>
+             <default>0</default>
+         </field>';
+         
+         $declaration = new Setup_Backend_Schema_Field_Xml($seqCol);
+         $this->_backend->addCol('cal_events', $declaration);
+         
+         $this->setTableVersion('cal_events', 8);
+         $this->setApplicationVersion('Calendar', '8.5');
+     }
++    
++    /**
 +     * add rrule index
 +     * 
 +     * @see 0010214: improve calendar performance / yearly base events
 +     */
-         $this->setTableVersion('cal_events', '7');
-         $this->setApplicationVersion('Calendar', '8.4');
++    public function update_5()
 +    {
 +        $declaration = new Setup_Backend_Schema_Index_Xml('
 +            <index>
 +                <name>rrule</name>
 +                <field>
 +                    <name>rrule</name>
 +                </field>
 +            </index>');
 +        try {
 +            $this->_backend->addIndex('cal_events', $declaration);
 +        } catch (Zend_Db_Statement_Exception $e) {
 +            Tinebase_Exception::log($e);
 +        }
 +        
++        $this->setTableVersion('cal_events', '9');
++        $this->setApplicationVersion('Calendar', '8.6');
 +    }
  }
@@@ -2,7 -2,7 +2,7 @@@
  <application>
      <name>Calendar</name>
      <!-- gettext('Calendar') -->   
-     <version>8.4</version>
 -    <version>8.5</version>
++    <version>8.6</version>
      <order>15</order>
      <status>enabled</status>
      <tables>
Simple merge
Simple merge
@@@ -574,9 -555,8 +574,9 @@@ class Tinebase_Use
       */
      protected static function _syncUserHook(Tinebase_Model_FullUser $user, $userProperties)
      {
 +        $result = true;
          $hookClass = Tinebase_Config::getInstance()->get(Tinebase_Config::SYNC_USER_HOOK_CLASS);
-         if ($hookClass) {
+         if ($hookClass && class_exists($hookClass)) {
              $hook = new $hookClass();
              if (method_exists($hook, 'syncUser')) {
                  if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__