Back to index

d-push  2.0
syncobject.php
Go to the documentation of this file.
00001 <?php
00002 /***********************************************
00003 * File      :   syncobjects.php
00004 * Project   :   Z-Push
00005 * Descr     :   Defines general behavoir of sub-WBXML
00006 *               entities (Sync* objects) that can be parsed
00007 *               directly (as a stream) from WBXML.
00008 *               They are automatically decoded
00009 *               according to $mapping by the Streamer,
00010 *               and the Sync WBXML mappings.
00011 *
00012 * Created   :   01.10.2007
00013 *
00014 * Copyright 2007 - 2011 Zarafa Deutschland GmbH
00015 *
00016 * This program is free software: you can redistribute it and/or modify
00017 * it under the terms of the GNU Affero General Public License, version 3,
00018 * as published by the Free Software Foundation with the following additional
00019 * term according to sec. 7:
00020 *
00021 * According to sec. 7 of the GNU Affero General Public License, version 3,
00022 * the terms of the AGPL are supplemented with the following terms:
00023 *
00024 * "Zarafa" is a registered trademark of Zarafa B.V.
00025 * "Z-Push" is a registered trademark of Zarafa Deutschland GmbH
00026 * The licensing of the Program under the AGPL does not imply a trademark license.
00027 * Therefore any rights, title and interest in our trademarks remain entirely with us.
00028 *
00029 * However, if you propagate an unmodified version of the Program you are
00030 * allowed to use the term "Z-Push" to indicate that you distribute the Program.
00031 * Furthermore you may use our trademarks where it is necessary to indicate
00032 * the intended purpose of a product or service provided you use it in accordance
00033 * with honest practices in industrial or commercial matters.
00034 * If you want to propagate modified versions of the Program under the name "Z-Push",
00035 * you may only do so if you have a written permission by Zarafa Deutschland GmbH
00036 * (to acquire a permission please contact Zarafa at trademark@zarafa.com).
00037 *
00038 * This program is distributed in the hope that it will be useful,
00039 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00040 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00041 * GNU Affero General Public License for more details.
00042 *
00043 * You should have received a copy of the GNU Affero General Public License
00044 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00045 *
00046 * Consult LICENSE file for details
00047 ************************************************/
00048 
00049 
00050 abstract class SyncObject extends Streamer {
00051     const STREAMER_CHECKS = 6;
00052     const STREAMER_CHECK_REQUIRED = 7;
00053     const STREAMER_CHECK_ZEROORONE = 8;
00054     const STREAMER_CHECK_NOTALLOWED = 9;
00055     const STREAMER_CHECK_ONEVALUEOF = 10;
00056     const STREAMER_CHECK_SETZERO = "setToValue0";
00057     const STREAMER_CHECK_SETONE = "setToValue1";
00058     const STREAMER_CHECK_SETTWO = "setToValue2";
00059     const STREAMER_CHECK_SETEMPTY = "setToValueEmpty";
00060     const STREAMER_CHECK_CMPLOWER = 13;
00061     const STREAMER_CHECK_CMPHIGHER = 14;
00062     const STREAMER_CHECK_LENGTHMAX = 15;
00063     const STREAMER_CHECK_EMAIL   = 16;
00064 
00065     protected $unsetVars;
00066 
00067 
00068     public function SyncObject($mapping) {
00069         $this->unsetVars = array();
00070         parent::Streamer($mapping);
00071     }
00072 
00082     public function emptySupported($supportedFields) {
00083         if ($supportedFields === false || !is_array($supportedFields))
00084             return false;
00085 
00086         foreach ($supportedFields as $field) {
00087             if (!isset($this->mapping[$field])) {
00088                 ZLog::Write(LOGLEVEL_WARN, sprintf("Field '%s' is supposed to be emptied but is not defined for '%s'", $field, get_class($this)));
00089                 continue;
00090             }
00091             $var = $this->mapping[$field][self::STREAMER_VAR];
00092             // add var to $this->unsetVars if $var is not set
00093             if (!isset($this->$var))
00094                 $this->unsetVars[] = $var;
00095         }
00096         ZLog::Write(LOGLEVEL_DEBUG, sprintf("Supported variables to be unset: %s", implode(',', $this->unsetVars)));
00097         return true;
00098     }
00099 
00100 
00109     public function equals($odo, $log = false) {
00110         if ($odo === false)
00111             return false;
00112 
00113         // check objecttype
00114         if (! ($odo instanceof SyncObject)) {
00115             ZLog::Write(LOGLEVEL_DEBUG, "SyncObject->equals() the target object is not a SyncObject");
00116             return false;
00117         }
00118 
00119         // check for mapped fields
00120         foreach ($this->mapping as $v) {
00121             $val = $v[self::STREAMER_VAR];
00122             // array of values?
00123             if (isset($v[self::STREAMER_ARRAY])) {
00124                 // seek for differences in the arrays
00125                 if (is_array($this->$val) && is_array($odo->$val)) {
00126                     if (count(array_diff($this->$val, $odo->$val)) + count(array_diff($odo->$val, $this->$val)) > 0) {
00127                         ZLog::Write(LOGLEVEL_DEBUG, sprintf("SyncObject->equals() items in array '%s' differ", $val));
00128                         return false;
00129                     }
00130                 }
00131                 else {
00132                     ZLog::Write(LOGLEVEL_DEBUG, sprintf("SyncObject->equals() array '%s' is set in one but not the other object", $val));
00133                     return false;
00134                 }
00135             }
00136             else {
00137                 if (isset($this->$val) && isset($odo->$val)) {
00138                     if ($this->$val != $odo->$val){
00139                         ZLog::Write(LOGLEVEL_DEBUG, sprintf("SyncObject->equals() false on field '%s': '%s' != '%s'", $val, Utils::PrintAsString($this->$val), Utils::PrintAsString($odo->$val)));
00140                         return false;
00141                     }
00142                 }
00143                 else if (!isset($this->$val) && !isset($odo->$val)) {
00144                     continue;
00145                 }
00146                 else {
00147                     ZLog::Write(LOGLEVEL_DEBUG, sprintf("SyncObject->equals() false because field '%s' is only defined at one obj: '%s' != '%s'", $val, Utils::PrintAsString(isset($this->$val)), Utils::PrintAsString(isset($odo->$val))));
00148                     return false;
00149                 }
00150             }
00151         }
00152 
00153         return true;
00154     }
00155 
00161     public function __toString() {
00162         $str = get_class($this) . " (\n";
00163 
00164         $streamerVars = array();
00165         foreach ($this->mapping as $k=>$v)
00166             $streamerVars[$v[self::STREAMER_VAR]] = (isset($v[self::STREAMER_TYPE]))?$v[self::STREAMER_TYPE]:false;
00167 
00168         foreach (get_object_vars($this) as $k=>$v) {
00169             if ($k == "mapping") continue;
00170 
00171             if (array_key_exists($k, $streamerVars))
00172                 $strV = "(S) ";
00173             else
00174                 $strV = "";
00175 
00176             // self::STREAMER_ARRAY ?
00177             if (is_array($v)) {
00178                 $str .= "\t". $strV . $k ."(Array) size: " . count($v) ."\n";
00179                 foreach ($v as $value) $str .= "\t\t". Utils::PrintAsString($value) ."\n";
00180             }
00181             else if ($v instanceof SyncObject) {
00182                 $str .= "\t". $strV .$k ." => ". str_replace("\n", "\n\t\t\t", $v->__toString()) . "\n";
00183             }
00184             else
00185                 $str .= "\t". $strV .$k ." => " . (isset($this->$k)? Utils::PrintAsString($this->$k) :"null") . "\n";
00186         }
00187         $str .= ")";
00188 
00189         return $str;
00190     }
00191 
00198     public function getUnsetVars() {
00199         return $this->unsetVars;
00200     }
00201 
00221     public function Check($logAsDebug = false) {
00222         $defaultLogLevel = LOGLEVEL_WARN;
00223 
00224         // in some cases non-false checks should not provoke a WARN log but only a DEBUG log
00225         if ($logAsDebug)
00226             $defaultLogLevel = LOGLEVEL_DEBUG;
00227 
00228         $objClass = get_class($this);
00229         foreach ($this->mapping as $k=>$v) {
00230 
00231             // check sub-objects recursively
00232             if (isset($v[self::STREAMER_TYPE]) && isset($this->$v[self::STREAMER_VAR])) {
00233                 if ($this->$v[self::STREAMER_VAR] instanceof SyncObject) {
00234                     if (! $this->$v[self::STREAMER_VAR]->Check($logAsDebug))
00235                         return false;
00236                 }
00237                 else if (is_array($this->$v[self::STREAMER_VAR])) {
00238                     foreach ($this->$v[self::STREAMER_VAR] as $subobj)
00239                         if ($subobj instanceof SyncObject && !$subobj->Check($logAsDebug))
00240                             return false;
00241                 }
00242             }
00243 
00244             if (isset($v[self::STREAMER_CHECKS])) {
00245                 foreach ($v[self::STREAMER_CHECKS] as $rule => $condition) {
00246                     // check REQUIRED settings
00247                     if ($rule === self::STREAMER_CHECK_REQUIRED && (!isset($this->$v[self::STREAMER_VAR]) || $this->$v[self::STREAMER_VAR] === '' ) ) {
00248                         // parameter is not set but ..
00249                         // requested to set to 0
00250                         if ($condition === self::STREAMER_CHECK_SETZERO) {
00251                             $this->$v[self::STREAMER_VAR] = 0;
00252                             ZLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Fixed object from type %s: parameter '%s' is set to 0", $objClass, $v[self::STREAMER_VAR]));
00253                         }
00254                         // requested to be set to 1
00255                         else if ($condition === self::STREAMER_CHECK_SETONE) {
00256                             $this->$v[self::STREAMER_VAR] = 1;
00257                             ZLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Fixed object from type %s: parameter '%s' is set to 1", $objClass, $v[self::STREAMER_VAR]));
00258                         }
00259                         // requested to be set to 2
00260                         else if ($condition === self::STREAMER_CHECK_SETTWO) {
00261                             $this->$v[self::STREAMER_VAR] = 2;
00262                             ZLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Fixed object from type %s: parameter '%s' is set to 2", $objClass, $v[self::STREAMER_VAR]));
00263                         }
00264                         // requested to be set to ''
00265                         else if ($condition === self::STREAMER_CHECK_SETEMPTY) {
00266                             if (!isset($this->$v[self::STREAMER_VAR])) {
00267                                 $this->$v[self::STREAMER_VAR] = '';
00268                                 ZLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Fixed object from type %s: parameter '%s' is set to ''", $objClass, $v[self::STREAMER_VAR]));
00269                             }
00270                         }
00271                         // there is another value !== false
00272                         else if ($condition !== false) {
00273                             $this->$v[self::STREAMER_VAR] = $condition;
00274                             ZLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Fixed object from type %s: parameter '%s' is set to '%s'", $objClass, $v[self::STREAMER_VAR], $condition));
00275 
00276                         }
00277                         // no fix available!
00278                         else {
00279                             ZLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Unmet condition in object from type %s: parameter '%s' is required but not set. Check failed!", $objClass, $v[self::STREAMER_VAR]));
00280                             return false;
00281                         }
00282                     } // end STREAMER_CHECK_REQUIRED
00283 
00284 
00285                     // check STREAMER_CHECK_ZEROORONE
00286                     if ($rule === self::STREAMER_CHECK_ZEROORONE && isset($this->$v[self::STREAMER_VAR])) {
00287                         if ($this->$v[self::STREAMER_VAR] != 0 && $this->$v[self::STREAMER_VAR] != 1) {
00288                             $newval = $condition === self::STREAMER_CHECK_SETZERO ? 0:1;
00289                             $this->$v[self::STREAMER_VAR] = $newval;
00290                             ZLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): Fixed object from type %s: parameter '%s' is set to '%s' as it was not 0 or 1", $objClass, $v[self::STREAMER_VAR], $newval));
00291                         }
00292                     }// end STREAMER_CHECK_ZEROORONE
00293 
00294 
00295                     // check STREAMER_CHECK_ONEVALUEOF
00296                     if ($rule === self::STREAMER_CHECK_ONEVALUEOF && isset($this->$v[self::STREAMER_VAR])) {
00297                         if (!in_array($this->$v[self::STREAMER_VAR], $condition)) {
00298                             ZLog::Write($defaultLogLevel, sprintf("SyncObject->Check(): object from type %s: parameter '%s'->'%s' is not in the range of allowed values.", $objClass, $v[self::STREAMER_VAR], $this->$v[self::STREAMER_VAR]));
00299                             return false;
00300                         }
00301                     }// end STREAMER_CHECK_ONEVALUEOF
00302 
00303 
00304                     // Check value compared to other value or literal
00305                     if ($rule === self::STREAMER_CHECK_CMPHIGHER || $rule === self::STREAMER_CHECK_CMPLOWER) {
00306                         if (isset($this->$v[self::STREAMER_VAR])) {
00307                             $cmp = false;
00308                             // directly compare against literals
00309                             if (is_int($condition)) {
00310                                 $cmp = $condition;
00311                             }
00312                             // check for invalid compare-to
00313                             else if (!isset($this->mapping[$condition])) {
00314                                 ZLog::Write(LOGLEVEL_ERROR, sprintf("SyncObject->Check(): Can not compare parameter '%s' against the other value '%s' as it is not defined object from type %s. Please report this! Check skipped!", $objClass, $v[self::STREAMER_VAR], $condition));
00315                                 continue;
00316                             }
00317                             else {
00318                                 $cmpPar = $this->mapping[$condition][self::STREAMER_VAR];
00319                                 if (isset($this->$cmpPar))
00320                                     $cmp = $this->$cmpPar;
00321                             }
00322 
00323                             if ($cmp === false) {
00324                                 ZLog::Write(LOGLEVEL_WARN, sprintf("SyncObject->Check(): Unmet condition in object from type %s: parameter '%s' can not be compared, as the comparable is not set. Check failed!", $objClass, $v[self::STREAMER_VAR]));
00325                                 return false;
00326                             }
00327                             if ( ($rule == self::STREAMER_CHECK_CMPHIGHER && $this->$v[self::STREAMER_VAR] < $cmp) ||
00328                                  ($rule == self::STREAMER_CHECK_CMPLOWER  && $this->$v[self::STREAMER_VAR] > $cmp)
00329                                 ) {
00330 
00331                                 ZLog::Write(LOGLEVEL_WARN, sprintf("SyncObject->Check(): Unmet condition in object from type %s: parameter '%s' is %s than '%s'. Check failed!",
00332                                                                     $objClass,
00333                                                                     $v[self::STREAMER_VAR],
00334                                                                     (($rule === self::STREAMER_CHECK_CMPHIGHER)?'LOWER':'HIGHER'),
00335                                                                     ((isset($cmpPar)?$cmpPar:$condition))  ));
00336                                 return false;
00337                             }
00338                         }
00339                     } // STREAMER_CHECK_CMP*
00340 
00341 
00342                     // check STREAMER_CHECK_LENGTHMAX
00343                     if ($rule === self::STREAMER_CHECK_LENGTHMAX && isset($this->$v[self::STREAMER_VAR])) {
00344 
00345                         if (is_array($this->$v[self::STREAMER_VAR])) {
00346                             // implosion takes 2bytes, so we just assume ", " here
00347                             $chkstr = implode(", ", $this->$v[self::STREAMER_VAR]);
00348                         }
00349                         else
00350                             $chkstr = $this->$v[self::STREAMER_VAR];
00351 
00352                         if (strlen($chkstr) > $condition) {
00353                             ZLog::Write(LOGLEVEL_WARN, sprintf("SyncObject->Check(): object from type %s: parameter '%s' is longer than %d. Check failed", $objClass, $v[self::STREAMER_VAR], $condition));
00354                             return false;
00355                         }
00356                     }// end STREAMER_CHECK_LENGTHMAX
00357 
00358 
00359                     // check STREAMER_CHECK_EMAIL
00360                     // if $condition is false then the check really fails. Otherwise invalid emails are removed.
00361                     // if nothing is left (all emails were false), the parameter is set to condition
00362                     if ($rule === self::STREAMER_CHECK_EMAIL && isset($this->$v[self::STREAMER_VAR])) {
00363                         if ($condition === false && ( (is_array($this->$v[self::STREAMER_VAR]) && empty($this->$v[self::STREAMER_VAR])) || strlen($this->$v[self::STREAMER_VAR]) == 0) )
00364                             continue;
00365 
00366                         $as_array = false;
00367 
00368                         if (is_array($this->$v[self::STREAMER_VAR])) {
00369                             $mails = $this->$v[self::STREAMER_VAR];
00370                             $as_array = true;
00371                         }
00372                         else {
00373                             $mails = array( $this->$v[self::STREAMER_VAR] );
00374                         }
00375 
00376                         $output = array();
00377                         foreach ($mails as $mail) {
00378                             if (! Utils::CheckEmail($mail)) {
00379                                 ZLog::Write(LOGLEVEL_WARN, sprintf("SyncObject->Check(): object from type %s: parameter '%s' contains an invalid email address '%s'. Address is removed.", $objClass, $v[self::STREAMER_VAR], $mail));
00380                             }
00381                             else
00382                                 $output[] = $mail;
00383                         }
00384                         if (count($mails) != count($output)) {
00385                             if ($condition === false)
00386                                 return false;
00387 
00388                             // nothing left, use $condition as new value
00389                             if (count($output) == 0)
00390                                 $output[] = $condition;
00391 
00392                             // if we are allowed to rewrite the attribute, we do that
00393                             if ($as_array)
00394                                 $this->$v[self::STREAMER_VAR] = $output;
00395                             else
00396                                 $this->$v[self::STREAMER_VAR] = $output[0];
00397                         }
00398                     }// end STREAMER_CHECK_EMAIL
00399 
00400 
00401                 } // foreach CHECKS
00402             } // isset CHECKS
00403         } // foreach mapping
00404 
00405         return true;
00406     }
00407 }
00408 
00409 ?>