Overview

Classes

  • CMLLanguage
  • CMLPost
  • CMLTranslations
  • CMLUtils

Functions

  • cml_dropdown_langs
  • cml_get_browser_lang
  • cml_get_menu
  • cml_get_notice
  • cml_get_the_link
  • cml_is_homepage
  • cml_show_flags
  • Overview
  • Class
  • Tree
   1: <?php
   2: if ( ! defined( 'ABSPATH' ) ) die( "Access denied" );
   3: 
   4: /*
   5:  * Ceceppa Multilingua API 1.4
   6:  */
   7: 
   8:  /**
   9:   * This class provide information about configured languages
  10:   *
  11:   * @api
  12:   * 
  13:   * The structure of language object is:
  14:   * <p>
  15:   * stdClass Object (
  16:   * <ul>
  17:   *   <li>[id] => id of language</li>
  18:   *   <li>[cml_default] => ( boolean ) - is it default?</li>
  19:   *   <li>[cml_flag] => name of flag</li>
  20:   *   <li>[cml_language] => name of language</li>
  21:   *   <li>[cml_language_slug] => language slug</li>
  22:   *   <li>[cml_locale] => wordpress locale</li>
  23:   *   <li>[cml_enabled] => enabled?</li>
  24:   *   <li>[cml_sort_id] => language order</li>
  25:   *   <li>[cml_custom_flag] => (boolean) - use custom flag?</li>
  26:   *   <li>[cml_rtl] => 0</li>
  27:   *   <li>[cml_date_format] => j M Y</li>
  28:   * )
  29:   * </p>
  30:   */
  31: class CMLLanguage {
  32:   /** @ignore */
  33:   private static $_default_language;
  34:   /** @ignore */
  35:   private static $_all_languages; //All languages (enabled and not)
  36:   /** @ignore */
  37:   private static $_all_enabled;   //Only enabled languages
  38:   /** @ignore */
  39:   private static $_all_others;    //All language except default one
  40:   /** @ignore */
  41:   private static $_all_by_slug;   //All languages indexed by slug
  42:   /** @ignore */
  43:   private static $_current_id;    //Current language id
  44: 
  45:   /**
  46:    * Tiny ~= 16x11
  47:    */
  48:   const FLAG_TINY = "tiny";
  49: 
  50:   /**  
  51:    * Small ~= 32x21
  52:    */
  53:   const FLAG_SMALL = "small";
  54: 
  55:   /**
  56:    * return object of default language 
  57:    *
  58:    * @return stdObject
  59:    */
  60:   public static function get_default() {
  61:     if( empty( self::$_all_languages ) ) self::get_all();
  62: 
  63:     return self::$_default_language;
  64:   }
  65: 
  66:   /**
  67:    * return default language id
  68:    *
  69:    * @return int
  70:    */
  71:   public static function get_default_id() {
  72:     return self::get_default()->id;
  73:   }
  74: 
  75:   /**
  76:    * return default language slug
  77:    *
  78:    * return string
  79:    */
  80:   public static function get_default_slug() {
  81:     return self::get_default()->cml_language_slug;
  82:   }
  83:   
  84:   /**
  85:    * return all configured languages, enabled or not...
  86:    *
  87:    * @return stdObject
  88:    */
  89:   public static function get_all() {
  90:     global $wpdb;
  91:   
  92:     /*
  93:      * Prevent a lot of calls to database and store the result into this class
  94:      */
  95:     if( empty( self::$_all_languages) ) {
  96:       self::$_all_languages = $wpdb->get_results( sprintf( "SELECT * FROM %s ORDER BY cml_sort_id ", CECEPPA_ML_TABLE ) );
  97: 
  98:       $all_languages_by_keys = array();
  99:       $sorted = array();
 100:       $enableds = array();
 101:       $byslug = array();
 102:       $others = array();
 103:       foreach( self::$_all_languages as $l ) {
 104:         $all_languages_by_keys[ $l->id ] = $l;
 105:         $byslug[ $l->cml_language_slug ] = $l;
 106:         $sorted[] = $l;
 107: 
 108:         if( $l->cml_default == 1 )
 109:           self::$_default_language = $l;
 110:         else
 111:           $others[ $l->id ] = $l;
 112: 
 113:         if( $l->cml_enabled == 1 ) $enableds[$l->id] = $l;
 114:       }
 115:       
 116:       if( empty( self::$_default_language ) ) {
 117:         update_option( "cml_warning_no_default_language", true );
 118:         
 119:         self::$_default_language = end( $enableds );
 120:       }
 121: 
 122:       self::$_all_enabled = $enableds;
 123:       self::$_all_others = $others;
 124:       self::$_all_languages = $all_languages_by_keys;
 125:       self::$_all_by_slug = $byslug;
 126:       
 127:       if( ! empty( self::$_default_language ) ) {
 128:         self::$_current_id = self::$_default_language->id;
 129:       }
 130:     }
 131: 
 132:     return self::$_all_languages;
 133:   }
 134: 
 135:   /**
 136:    * return all configured languages except default one
 137:    *
 138:    * @return stdObject
 139:    */
 140:   public static function get_no_default() {
 141:     if( empty( self::$_all_languages) ) self::get_all();
 142:     
 143:     return self::$_all_others;
 144:   }
 145: 
 146:   /**
 147:    * return all enabled languages
 148:    *
 149:    * @return stdObject
 150:    */
 151:   public static function get_enableds() {
 152:     if( empty( self::$_all_languages ) ) self::get_all();
 153:     
 154:     return self::$_all_enabled;
 155:   }
 156: 
 157:   /*
 158:    * return all enabled languages except current one
 159:    *
 160:    * @param boolean $only_enableds return only enabled languages
 161:    * @return stdObject
 162:    */
 163:   public static function get_others( $only_enableds = true ) {
 164:     if( empty( self::$_all_languages ) ) self::get_all();
 165:     
 166:     $langs = ( $only_enableds ) ? self::$_all_enabled : self::$_all_languages;
 167:     unset( $langs[ self::get_current_id() ] );
 168:     
 169:     return $langs;
 170:   }
 171: 
 172:   /**
 173:    * return associative array where index
 174:    * is the language slug
 175:    *
 176:    * @example
 177:    * Array (
 178:    * <ul>
 179:    *   <li>"it" => [stdObject..],</li>
 180:    *   <li>"en" => [stdObject...]</li>
 181:    * </ul>
 182:    * )
 183:    *
 184:    * @return Array
 185:    */
 186:   public static function get_slugs() {
 187:     if( empty( self::$_all_languages ) ) self::get_all();
 188:     
 189:     return self::$_all_by_slug;
 190:   }
 191: 
 192:   /**
 193:    * return current language
 194:    *
 195:    * @return stdobject
 196:    */
 197:   public static function get_current() {
 198:     if( empty( self::$_all_languages ) ) self::get_all();
 199: 
 200:     return self::$_all_languages[ self::$_current_id ];
 201:   }
 202: 
 203:   /**
 204:    * return current language id
 205:    *
 206:    * @return int
 207:    */
 208:   public static function get_current_id() {
 209:     return self::get_current()->id;
 210:   }
 211: 
 212:   /**
 213:    * return current language slug
 214:    */
 215:   public static function get_current_slug() {
 216:     return self::get_current()->cml_language_slug;
 217:   }
 218: 
 219:   /**
 220:    * return the name of language
 221:    *
 222:    * @param int/string $lang - id or slug of language
 223:    *
 224:    * @return string
 225:    */
 226:   public static function get_name( $lang ) {
 227:     if( empty( self::$_all_languages ) ) self::get_all();
 228:     if( empty( self::$_default_language ) ) self::get_default();
 229:     if( ! is_numeric( $lang ) ) $lang = self::get_id_by_slug( $lang );
 230: 
 231:     return isset( self::$_all_languages[ $lang ] ) ? self::$_all_languages[ $lang ]->cml_language : "";
 232:   }
 233: 
 234:   /**
 235:    * return the slug of language
 236:    *
 237:    * @param int/string $lang - id or slug of language
 238:    *
 239:    * @return string
 240:    */
 241:   public static function get_slug( $lang ) {
 242:     if( empty( self::$_all_languages ) ) self::get_all();
 243:     if( empty( self::$_default_language ) ) self::get_default();
 244:     if( is_object( $lang ) ) $lang = $lang->id;
 245: 
 246:     if( $lang == 0 ) return self::$_default_language->cml_language_slug;
 247: 
 248:     return @self::$_all_languages[ $lang ]->cml_language_slug;
 249:   }
 250: 
 251:   /**
 252:    * return language by id
 253:    *
 254:    * @param int/string $lang id or slug of language to search
 255:    *
 256:    * @return stdObject
 257:    */
 258:   public static function get_by_id( $id ) {
 259:     if( empty( self::$_all_languages ) ) self::get_all();
 260:     if( ! is_numeric( $id ) ) $id = CMLLanguage::get_by_slug( $id );
 261: 
 262:     return self::$_all_languages[ $id ];
 263:   }
 264: 
 265:   /**
 266:    * get language by slug
 267:    *
 268:    * @param string $slug - language slug
 269:    * @param boolean $empty - If false return default language if $slug doesn't exists.
 270:    *                           If true and $slug doesn't exists return empty array
 271:    *
 272:    * @return stdObject
 273:    */
 274:   public static function get_by_slug( $slug, $empty = false ) {
 275:     if( empty( self::$_all_languages ) ) self::get_all();
 276: 
 277:     foreach( self::$_all_languages as $lang ) {
 278:       if( $lang->cml_language_slug == $slug ) return $lang;
 279:     }
 280:     
 281:     return ( ! $empty ) ? self::get_default() : array();
 282:   }
 283: 
 284:   /**
 285:    * return language id by slug
 286:    *
 287:    * @param string $slug - language slug
 288:    *
 289:    * @return int
 290:    */
 291:   public static function get_id_by_slug( $slug ) {
 292:     $lang = self::get_by_slug( $slug );
 293: 
 294:     return $lang->id;
 295:   }
 296: 
 297:   /**
 298:    * return language id by locale
 299:    *
 300:    * @param string $language locale
 301:    *
 302:    * @return int
 303:    */
 304:   public static function get_id_by_locale( $locale ) {
 305:     $langs = self::get_all();
 306:     
 307:     foreach( $langs as $lang ) {
 308:       if( $lang->cml_locale == $locale ) return $lang;
 309:     }
 310:     
 311:     return null;
 312:   }
 313: 
 314:   /**
 315:    * return the flag filename ( withouth extension )
 316:    *
 317:    * @param int/string $lang ( optional ) - id/slug of language, if empty default one will be used
 318:    * @param string $size ( optional ) - size of flag: "tiny" or "small"
 319:    *
 320:    * @return string
 321:    */
 322:   public static function get_flag( $lang = null, $size = "small" ) {
 323:     if( empty( $lang ) ) $lang = self::default_language_id();
 324:     if( ! is_numeric( $lang ) ) $lang = self::get_id_by_slug( $lang );
 325: 
 326:     if( empty( self::$_all_languages ) ) self::get_all();
 327: 
 328:     return self::$_all_languages[ $lang ]->cml_flag;
 329:   }
 330: 
 331:   /**
 332:    * return flag filename with the full path.
 333:    *
 334:    * Example
 335:    * www.example.com/wp-content/plugin/ceceppa-multilingua/flags/tiny/it_IT.png
 336:    *
 337:    * @param int/string $lang ( optional ) - id or slug of language, if empty default one will be used
 338:    * @param string $size ( optional ) - size of flag: "tiny" or "small"
 339:    *
 340:    * @return string: flag filename with the full path.
 341:    */
 342:   public static function get_flag_src( $lang = null, $size = CML_FLAG_TINY ) {
 343:     if( empty( self::$_all_languages ) ) self::get_all();
 344:     if( empty( self::$_default_language ) ) self::get_default();
 345:     if( $lang == null ) $lang = self::get_default_id();
 346:     if( ! is_numeric( $lang ) ) $lang = self::get_id_by_slug( $lang );
 347: 
 348:     if( ! isset( self::$_all_languages[ $lang ] ) ) {
 349:       return "";
 350:     }
 351: 
 352:     $lang = self::$_all_languages[ $lang ];
 353:     $flag = $lang->cml_flag;
 354: 
 355:     if( $lang->cml_custom_flag == 1 && file_exists( CML_UPLOAD_DIR . "/$size/$flag.png" ) )
 356:       $url = CML_UPLOAD_URL . "/$size/$flag.png";
 357:     else
 358:       $url = CML_PLUGIN_URL . "flags/$size/$flag.png";
 359: 
 360:     return esc_url( $url );
 361:   }
 362:   
 363:   /**
 364:    * return html <img> object of flag
 365:    *
 366:    * @param int/string $lang - id or slug of language
 367:    * @param string $size - flag size ( tiny or small )
 368:    *
 369:    * @return string
 370:    */
 371:   public static function get_flag_img( $lang, $size = CML_FLAG_TINY ) {
 372:     $url = self::get_flag_src( $lang, $size );
 373:     $name = self::get_name( $lang );
 374:     $slug = self::get_slug( $lang );
 375: 
 376:     return "<img src='$url' border='0' alt='$slug' title='$name' />";
 377:   }
 378:    
 379:    /**
 380:     * @ignore
 381:     *
 382:     * force "reload" languages
 383:     */
 384:    public static function reload() {
 385:     self::$_all_languages = null;
 386:    }
 387: 
 388:   /**
 389:    * get language object by post id
 390:    *
 391:    * @param int $post_id - id of post/page
 392:    *
 393:    * @return stdObject
 394:    */
 395:   public static function get_by_post_id( $post_id ) {
 396:     return CMLPost::get_language_by_id( $post_id );
 397:   }
 398: 
 399:   /**
 400:    * get language id by post id
 401:    *
 402:    * @param int $post_id - id of post
 403:    *
 404:    * @return int
 405:    */
 406:   public static function get_id_by_post_id( $post_id ) {
 407:     return CMLPost::get_language_id_by_id( $post_id );
 408:   }
 409:   
 410:   /**
 411:    * Is $lang the default one?
 412:    *
 413:    * @param int/string $lang ( optional ) id/slug. check if $lang is the default language, if null is passed
 414:    *                        current language will be assumed
 415:    * @return boolean
 416:    */
 417:   public static function is_default( $lang = null) {
 418:     if( null == $lang ) {
 419:       $lang = CMLUtils::_get( '_real_language');
 420:     } else {
 421:       if( ! is_numeric( $lang ) ) {
 422:         $lang = CMLLanguage::get_id_by_slug( $lang );
 423:       }
 424:     }
 425: 
 426:     return $lang == CMLLanguage::get_default_id();
 427:   }
 428:  
 429:   /**
 430:    * check if $lang is the current language
 431:    *
 432:    * @param int/string $lang language id/slug to compare
 433:    *
 434:    * @return boolean
 435:    */
 436:   public static function is_current( $lang ) {
 437:     if( null == $lang ) {
 438:       $lang = CMLLanguage::get_current_id();
 439:     } else {
 440:       if( ! is_numeric( $lang ) ) {
 441:         $lang = CMLLanguage::get_id_by_slug( $lang );
 442:       }
 443:     }
 444:     
 445:     return $lang == CMLLanguage::get_current_id();
 446:   }
 447: 
 448:   /**
 449:    * @ignore
 450:    * 
 451:    * set current language
 452:    *
 453:    * @param $lang - language object or id
 454:    *
 455:    * @return void
 456:    */
 457:   public static function set_current( $lang ) {
 458:     $id = is_object( $lang ) ? $lang->id : $lang;
 459:     
 460:     self::$_current_id = $id;
 461:   }
 462: }
 463: 
 464: /**
 465:  * This class is used to get and store custom translations in CECEPPA_ML_TRANSLATIONS table.
 466:  */
 467: class CMLTranslations {
 468:   //store "get" translations
 469:   /** @ignore */
 470:   private static $_translations = array();
 471:   /** @ignore */
 472:   private static $_keys = array();
 473: 
 474:   /**
 475:    * This function can be used by 3rd part plugin/theme to allow translation of its strings.
 476:    * Added string can be translated in "My Languages" page.
 477:    *
 478:    * @example
 479:    * Full example is provided here:<br />
 480:    *  http://www.alessandrosenese.eu/en/ceceppa-multilingua/extend-plugin-theme-compatibility/
 481:    *
 482:    * @param string $key used to store/get your own value from database. To avoid duplicated key use your own
 483:    *                        prefix for your key. Example: "_yoast_rssafter"
 484:    * @param string $default default value to use
 485:    * @param string $group The group name of your own strings, this name will be displayed in "My Translations" page
 486:    *                      in "Group" column. Group name should be preceded by "_" symbol.<br />
 487:    *                      Example: "_YOAST"
 488:    *
 489:    * @return void
 490:    */
 491:   public static function add( $key, $default, $group ) {
 492:     global $wpdb;
 493: 
 494:     $default = bin2hex( $default );
 495:     foreach( CMLLanguage::get_all() as $lang ) {
 496:       $query = sprintf( "SELECT id FROM %s WHERE cml_text = '%s' AND cml_lang_id = %d AND cml_type = '%s'",
 497:                         CECEPPA_ML_TRANSLATIONS,
 498:                         bin2hex( strtolower( $key ) ),
 499:                         $lang->id,
 500:                         $group );
 501:   
 502:       $record = $wpdb->get_var( $query );
 503:       if( empty( $record ) ) {
 504:         $wpdb->insert( CECEPPA_ML_TRANSLATIONS,
 505:                       array(
 506:                             'cml_text' => bin2hex( strtolower( $key ) ),
 507:                             'cml_lang_id' => $lang->id,
 508:                             'cml_translation' => $default,
 509:                             'cml_type' => $group
 510:                             ),
 511:                       array(
 512:                         '%s', '%d', '%s', '%s',
 513:                       )
 514:                      );
 515:       }
 516:     }
 517:   }
 518:   
 519:   /**
 520:    * Store custom translation in database.
 521:    *
 522:    * Since 1.4 CML generate GNUTEXT mo file from stored translations. 
 523:    * The domain used to generate translation is: "cmltrans".
 524:    *
 525:    * Mo file isn't generated automatically, but you have to call manually
 526:    * the function cml_generate_mo_from_translations()
 527:    * 
 528:    * This function will return the id of inserted record.
 529:    * 
 530:    * @example
 531:    *
 532:    * <?php _e( "Hello", "cmltrans" ); ?>
 533:    *
 534:    * Use "get" function instead of __, _e, because if "mo" generation fails,
 535:    * this function will get translation from database
 536:    * 
 537:    * @param int/string $lang - id/slug of language
 538:    * @param string $original - original string
 539:    * @param string $translation - translated string
 540:    * @param string $type - type of translation( W: Widget, S: Custom strings ).
 541:    *                Type field is used "internally" to show records in correct table, like
 542:    *                Widget titles, My translations...
 543:    *
 544:    * @return string
 545:    */
 546:   public static function set( $lang, $original, $translated, $type ) {
 547:     global $wpdb;
 548: 
 549:     if( ! is_numeric( $lang ) ) $lang = CMLLanguage::get_id_by_slug( $lang );
 550:     $original = trim( $original );
 551: 
 552:     $wpdb->delete( CECEPPA_ML_TRANSLATIONS,
 553:                     array( "cml_text" => bin2hex( $original ),
 554:                            "cml_type" => $type,
 555:                            "cml_lang_id" => $lang ),
 556:                     array( "%s", "%s", "%d" ) );
 557: 
 558:     return $wpdb->insert( CECEPPA_ML_TRANSLATIONS, 
 559:                           array( 'cml_text' => bin2hex( $original ),
 560:                                 'cml_lang_id' => $lang,
 561:                                 'cml_translation' => bin2hex( $translated ),
 562:                                 'cml_type' => $type ),
 563:                           array( '%s', '%d', '%s', '%s' ) );
 564:   }
 565:   
 566:   /**
 567:    * return translation stored in cml_trans table.
 568:    *
 569:    * This function will get translation from ".mo" file if:
 570:    *    1) it's generated correctly
 571:    *    2) $lang == current language
 572:    *
 573:    * otherwise will get translation from database
 574:    *
 575:    * <strong>string match is case sensitive</strong>
 576:    * 
 577:    * @param int/string $lang - language id or slug
 578:    * @param string $string - string to translate
 579:    * @param string $type - ( optional ) This is used internally by Ceceppa Multilingua, only in admin interface
 580:    *                  T - Site Title/Tagline,
 581:    *                  W - Widget,
 582:    *                  M - My translations
 583:    *                  
 584:    * @param boolean $return_empty - If true, return empty string if no translation is found
 585:    * @param boolean $ignore_po  Since 1.4 the plugin will generate mo file for all translation stored
 586:    *                                in CECEPPA_ML_TRANSLATIONS ( widget titles, my translations, site title/tagline... ).
 587:    *                                So by default if $lang == current language, the plugin will get translation
 588:    *                                from ".mo" file instead query the database.
 589:    *                                You can force to retive translation from database.
 590:    *
 591:    * @return string                 
 592:    */
 593:   public static function get( $lang, $string, $type = "", $return_empty = false, $ignore_po = false ) {
 594:     global $wpdb;
 595: 
 596:     // if( CMLLanguage::is_current( $lang ) && 
 597:     //     "_" != $type[ 0 ] &&
 598:     //     ! ( isset( $string[0] ) && "_" == $string[ 0 ] ) ) {
 599:     //   return $string;
 600:     // }
 601: 
 602:     if( "_" == $type[ 0 ] && ! $return_empty ) {
 603:       $return_empty = true;
 604:     }
 605: 
 606:     $string = trim( $string );
 607: 
 608:     //C = Category
 609:     $s = ( $type == "C" ) ? strtolower( $string ) : $string;
 610: 
 611:     //Look if I already translated it...
 612:     if( isset( self::$_keys[ $lang ] ) && in_array( sanitize_title( $s ), self::$_keys[ $lang ] ) ) {
 613:       $index = array_search( sanitize_title( $s ), self::$_keys[ $lang ] );
 614:       return self::$_translations[ $lang ][ $index ];
 615:     }
 616: 
 617:     if( CML_GET_TRANSLATIONS_FROM_PO &&
 618:        ! $ignore_po &&
 619:        1 == CMLUtils::_get( '_po_loaded' ) ) {
 620:          //file_exists( CML_PLUGIN_CACHE_PATH . "cmltrans-" . CMLLanguage::get_current()->cml_locale . ".mo" ) ) {
 621:       $ret = __( $s, 'cmltrans' );
 622:     }
 623: 
 624:     if( ! is_numeric( $lang ) ) {
 625:       $lang = CMLLanguage::get_id_by_slug( $lang );
 626:     }
 627: 
 628:     $query = sprintf(" SELECT UNHEX(cml_translation) FROM %s WHERE cml_text = '%s' AND cml_lang_id = %d AND cml_type LIKE '%s'",
 629:                                     CECEPPA_ML_TRANSLATIONS, bin2hex( $s ), $lang, "%" . $type . "%" );
 630: 
 631:     $return = $wpdb->get_var( $query );
 632: 
 633:     if( $return_empty && empty( $return ) ) return "";
 634: 
 635:     $return = ( empty( $return ) ) ?  $string : html_entity_decode( stripslashes( $return ) );
 636:     
 637:     self::$_translations[$lang][] = $return;
 638:     self::$_keys[ $lang ][] = sanitize_title( $string );
 639: 
 640:     return $return;
 641:   }
 642:   
 643:   /*
 644:    * get translation from wordpress
 645:    *
 646:    * @ignore
 647:    */
 648:   public static function gettext( $lang, $string, $type, $ignore_po = false ) {
 649:     $ret = self::get( $lang, $string, $type, true, $ignore_po );
 650: 
 651:     if( ! empty( $ret ) ) return $ret;
 652: 
 653:     //Recupero la traduzione dalle frasi di wordpress ;)
 654:     require_once( CML_PLUGIN_PATH . "gettext/gettext.inc" );
 655:     
 656:     $locale = CMLLanguage::get_current()->cml_locale;
 657: 
 658:     // gettext setup
 659:     T_setlocale( LC_MESSAGES, $locale );
 660:     // Set the text domain as 'messages'
 661: 
 662:     $domain = $locale;
 663:     T_bindtextdomain( $domain, CML_WP_LOCALE_DIR );
 664:     T_bind_textdomain_codeset( $domain, 'UTF-8' );
 665:     T_textdomain( $domain );
 666: 
 667:     $ret = T_gettext( $string );
 668: 
 669:     return ( empty( $ret ) ) ?  $string : html_entity_decode( stripslashes( $ret ) );
 670:   }
 671:   
 672:   /**
 673:    * delete all records with cml_type = xx
 674:    *
 675:    * @ignore
 676:    */
 677:   public static function delete( $type ) {
 678:     global $wpdb;
 679:     
 680:     $wpdb->delete( CECEPPA_ML_TRANSLATIONS,
 681:                   array( "cml_type" => $type ),
 682:                   array( "%s" ) );
 683:   }
 684: }
 685: 
 686: /**
 687:  * This class is used to get/set post translation/language or get language by its id
 688:  * 
 689:  */
 690: class CMLPost {
 691:   /** @ignore */
 692:   private static $_indexes = null;
 693:   /** @ignore */
 694:   private static $_posts_meta = array();
 695: 
 696:   /**
 697:    * return language object by post id
 698:    *
 699:    * this function return "null" if post doesn't exists in any language
 700:    * 
 701:    * @param int/string $post_id - id of post/page
 702:    *
 703:    * @return stdObject
 704:    */
 705:   public static function get_language_by_id( $post_id ) {
 706:     if( empty( self::$_indexes ) ) self::_load_indexes();
 707: 
 708:     /*
 709:      * search in current language first.
 710:      * because if post exists in multiple languages, included current one,
 711:      * I have to return current language id, not random :)
 712:      */
 713:     if( @in_array( $post_id, self::$_indexes[ CMLLanguage::get_current_id() ] ) ) {
 714:       return CMLLanguage::get_current();
 715:     }
 716: 
 717:     foreach( CMLLanguage::get_others() as $lang ) {
 718:       if( @in_array( $post_id, self::$_indexes[ $lang->id ] ) )
 719:         return $lang;
 720:     }
 721: 
 722:     return null;
 723:   }
 724:   
 725:   /**
 726:    * return language id by post id
 727:    *
 728:    * @param int $post_id - id of post/page
 729:    * @param boolean $meta - default false.
 730:    *                        If true use wp function "get_post_meta", instead of get_language_by_id method
 731:    *                        to get language of post.
 732:    *                        In backend I need to get information by post meta, or I'll lost
 733:    *                        "all languages" ( = 0 ) information.
 734:    *
 735:    * @return int
 736:    */
 737:   public static function get_language_id_by_id( $post_id, $meta = false ) {
 738:     if( $meta ) {
 739:       //Get from meta
 740:       $m = get_post_meta( $post_id, "_cml_meta", true );
 741: 
 742:       if( ! empty( $m ) && isset( $m[ "lang" ] ) ) {
 743:         return $m[ "lang"];
 744:       }
 745:     }
 746: 
 747:     $lang = self::get_language_by_id( $post_id );
 748: 
 749:     if( null === $lang ) {
 750:       //Get from meta
 751:       $m = get_post_meta( $post_id, "_cml_meta", true );
 752: 
 753:       if( $meta && empty( $m ) ) {
 754:         $lang = self::get_language_by_id( $post_id );
 755:   
 756:         if( is_object( $lang ) ) {
 757:           //update meta
 758:           self::update_meta( $lang->id, $post_id );
 759:         }
 760:   
 761:         return is_object( $lang ) ? $lang->id : 0;
 762:       } else {
 763:         return @$meta[ "lang" ];
 764:       }
 765:     }
 766: 
 767:     return $lang->id;
 768:   }
 769:   
 770:   /**
 771:    * get language slug by post id
 772:    *
 773:    * @param int $post_id post/page id
 774:    *
 775:    * @return string
 776:    */
 777:   public static function get_language_slug_by_id( $post_id ) {
 778:     $lang = self::get_language_by_id( $post_id );
 779:     
 780:     return is_object( $lang ) ? $lang->cml_language_slug : "";
 781:   }
 782: 
 783:   /**
 784:    * get the translation id, if exists, in selected language
 785:    *
 786:    * this function will return 0 if no translation is found.
 787:    * 
 788:    * @param int/string $lang - language id/slug in which return translation
 789:    * @param int $post_id - post id
 790:    *
 791:    * @return int
 792:    */
 793:   public static function get_translation( $lang, $post_id ) {
 794:     global $wpdb;
 795: 
 796:     if( is_numeric( $lang ) ) $lang = CMLLanguage::get_slug( $lang );
 797:     if( empty( $post_id ) ) return 0;
 798: 
 799:     //if( ! CECEPPA_ML_MIGRATED ) {
 800:     //  return cml_old_get_linked_post( $wpCeceppaML->get_language_id_by_post_id( $post_id ), null, $post_id, $lang );
 801:     //}
 802:   
 803:     $linked = self::get_translations( $post_id );
 804: 
 805:     return ( ! array_key_exists( $lang, $linked) ) ? 0 : $linked[ $lang ];
 806:   }
 807: 
 808:   /**
 809:    * get all available translations of post
 810:    *
 811:    * This function will return Array containing all info about linked posts
 812:    *
 813:    * Array(
 814:    * <ul>
 815:    *   <li>[language slug] => [post_id]</li>
 816:    *   <li>...</li>
 817:    *   <li>[indexes] => Array<br />
 818:    *    <i>In this subarray there are all linked posts, including $post_id</i>
 819:    *    <ul>
 820:    *      <li>[language slug] => [post_id]</li>
 821:    *      <li>...</li>
 822:    *    </ul>
 823:    *   </li>
 824:    *   <li>
 825:    *    [linked] => Array<br />
 826:    *    <i>In this subarray there are only linked post indexes</i> 
 827:    *    <ul>
 828:    *      <li>[linked language slug] => [linked_id]</li>
 829:    *      <li>...</li>
 830:    *    </ul>
 831:    *  </li>
 832:    * </ul>
 833:    * )
 834:    * 
 835:    * @example
 836:    * <br />
 837:    * Array (
 838:    * <ul>
 839:    *   <li>[it] => 2552</li>
 840:    *   <li>[en] => 541</li>
 841:    *   <li>[eo] => 0</li>
 842:    *   <li>[indexes] => Array
 843:    *       (
 844:    *       <ul>
 845:    *        <li>[it] => 2552</li>
 846:    *       </ul>
 847:    *       )
 848:    *    </li>
 849:    *    <li>
 850:    *   [others] => Array
 851:    *       (
 852:    *       <ul>
 853:    *        <li>[en] => 541</li>
 854:    *       )
 855:    *    </li>
 856:    *  </ul>
 857:    * )
 858:    *
 859:    * @param int $post_id - post id
 860:    * @param boolean $force - force to rebuild meta. ( This parameter is used internally by CML )
 861:    *
 862:    * return Array
 863:    */
 864:   public static function get_translations( $post_id, $force = false ) {
 865:     global $wpdb;
 866:   
 867:     if( empty( $post_id ) ) return array();
 868: 
 869:     if( ! isset( self::$_posts_meta[ $post_id ] ) || $force ) {
 870:       $row = get_post_meta( $post_id, "_cml_meta", true );
 871: 
 872:       if( empty( $row ) || empty( $row[ 'lang' ] ) || $force ) {
 873:         if( empty( $GLOBALS[ '_cml_language_columns' ] ) ) {
 874:           require_once ( CML_PLUGIN_ADMIN_PATH . 'admin-settings-gen.php' );
 875: 
 876:           cml_generate_lang_columns();
 877:         }
 878:       
 879:         $_cml_language_columns = & $GLOBALS[ '_cml_language_columns' ];
 880:         $_conv = & $GLOBALS[ '_cml_language_keys' ];
 881: 
 882:         $query = "SELECT ";
 883:         foreach( $_conv as $key => $label ) {
 884:           $select[] = "$key as $label";
 885:         }
 886: 
 887:         /*
 888:          * something happend that $_conv is empty and that couse a warning
 889:          * and I can't store post relations properly.
 890:          */
 891:         if( empty( $select ) ) {
 892:           $keys = array_keys( CMLLanguage::get_all() );
 893:           $langs = array_keys( CMLLanguage::get_slugs() );
 894: 
 895:           foreach( $keys as $k => $v ) {
 896:             $select[] = "lang_{$v} as " . $langs[ $k ];
 897:           }
 898:         }
 899: 
 900:         $query .= join( ",", $select ) . " FROM " . CECEPPA_ML_RELATIONS . " WHERE ";
 901:         foreach( $_cml_language_columns as $l ) {
 902:           $where[] = "$l = $post_id";
 903:         }
 904:         $query .= join( " OR ", $where );
 905:       
 906:         $row = $wpdb->get_row( $query, ARRAY_A );
 907:         unset( $row[ "id" ] );
 908: 
 909:         $keys = @array_filter( $row );
 910:         $keys = @array_replace( $keys, $_conv );
 911:         $others = @array_filter( is_array( $row ) ? $row : array() );
 912:         unset( $others[ CMLPost::get_language_slug_by_id( $post_id ) ] );
 913:       
 914:         $row = @array_merge( (array) $row, array( "indexes" => array_filter( $row ),
 915:                                                  "linked" => $others ) );
 916: 
 917:         if( ! $force && isset( $row[ 'lang' ] ) ) {
 918:           self::update_meta( self::get_language_id_by_id( $post_id ), $post_id, $row );
 919:         } else {
 920:         }
 921:       } else {
 922:         $row = $row[ 'translations' ];
 923:       }
 924: 
 925:       self::$_posts_meta[ $post_id ] = $row;
 926:     } else {
 927:       $row = self::$_posts_meta[ $post_id ];
 928:     }
 929: 
 930:     return $row;
 931:   }
 932:   
 933:   /**
 934:    * set language of post
 935:    *
 936:    * This function will unlink $post_id by its translations
 937:    * 
 938:    * @param int/string $lang - post language id/slug 
 939:    * @param int $post_id - post id
 940:    */
 941:   public static function set_language( $lang, $post_id ) {
 942:     if( ! is_numeric( $lang ) ) $lang = CMLLanguage::get_id_by_slug( $lang );
 943: 
 944:     cml_migrate_database_add_item( $lang, $post_id, 0, 0 );
 945:   }
 946: 
 947:   /**
 948:    * set single translation to post id
 949:    *
 950:    * This function is used to link 2 posts
 951:    *
 952:    * When you link a post to single translation, relations with other language will not be losed.
 953:    * If you want remove other relations, you have to use set_language method first.
 954:    * 
 955:    * @param int $post_id - post to set translation
 956:    * @param int/string $linked_lang - language id/slug of linked post
 957:    * @param int $linked_post - post id of translation
 958:    * @param int $post_lang ( optional ) - language of $post_id. If null, It will get from database
 959:    *
 960:    * @return void
 961:    */
 962:   public static function set_translation( $post_id, $linked_lang, $linked_post, $post_lang = null ) {
 963:     self::set_translations( $post_id, array( $linked_lang => $linked_post ), $post_lang );
 964:   }
 965: 
 966:   /**
 967:    * add multiple translations to post id
 968:    *
 969:    * This function will update relations only from $post_id with $translations posts, so relations
 970:    * from $post_id and languages than doesn't exists in $translations array will not be broken.
 971:    * 
 972:    * If you need to set relation only from $post_id and $translations, and remove the other one, you
 973:    * have to "break" them using set_language method first.
 974:    * 
 975:    * @param $post_id - post to set translation+
 976:    * @param $translations - array with language_slug as key and post_id as value.
 977:    *                        array( "it" => 1, "en" => 2 )...
 978:    * @param $post_lang ( optional ) - set also the language of $post_id
 979:    *
 980:    * @example:
 981:    *
 982:    *    CMLPost::set_translation( 1, array( "it" => 2, "en" => 3 ) )
 983:    */
 984:   public static function set_translations( $post_id, $translations, $post_lang = null ) {
 985:     //$_cml_language_columns = & $GLOBALS[ '_cml_language_columns' ];
 986:     if( null === $post_lang ) $post_lang = CMLPost::get_language_id_by_id( $post_id );
 987: 
 988:     foreach( $translations as $key => $id ) {
 989:       if( ! is_numeric( $key ) ) $key = CMLLanguage::get_by_slug( $key );
 990: 
 991:       cml_migrate_database_add_item( $post_lang, $post_id, $key, $id );
 992:     }
 993: 
 994:     //Update info
 995:     cml_fix_rebuild_posts_info();
 996:     self::_load_indexes();
 997: 
 998:     self::update_meta( $post_lang, $post_id );
 999:   }
1000:   
1001:   /*
1002:    * update post meta
1003:    * @ignore
1004:    */
1005:   public static function update_meta( $lang, $post_id, $translations = null ) {
1006:     if( $lang == "" ) return;
1007: 
1008:     /*
1009:      * I just updated post relation, so I have to rebuild meta :)
1010:      */
1011:     //Add my meta to post
1012:     if( null == $translations ) {
1013:       $translations = CMLPost::get_translations( $post_id, true );
1014:     }
1015: 
1016:     $meta = array( "lang" => $lang,
1017:                     "translations" => $translations );
1018: 
1019:     update_post_meta( $post_id, "_cml_meta", $meta );
1020:   }
1021: 
1022:   /**
1023:    * get indexes of posts that exists in selected language
1024:    *
1025:    * @param int/slug $lang ( optional, if not set will be = current language id )
1026:    *                      id / slug of language
1027:    *
1028:    * @return array
1029:    */
1030:   public static function get_posts_by_language( $lang = null ) {
1031:     if( empty( $lang ) ) $lang = CMLLanguage::get_current_id();
1032:     if( ! is_numeric( $lang ) ) $lang = CMLLanguage::get_id_by_slug( $lang );
1033:   
1034:     //Gli articoli senza lingua sono "figli di tutti"
1035:     if( empty( self::$_indexes ) ) self::_load_indexes();
1036: 
1037:     $posts = @self::$_indexes[ $lang ];
1038: 
1039:     return ! empty( $posts ) ? array_unique( $posts ) : array();
1040:   }
1041: 
1042:   /*
1043:    * for private use only, update post indexes by language
1044:    * @ignore
1045:    */
1046:   public static function _update_posts_by_language( $lang, $ids ) {
1047:     self::$_indexes[ $lang ] = $ids;
1048:   }
1049: 
1050:   /**
1051:    * return all posts by languages.
1052:    *
1053:    * The key of array is the language id
1054:    *
1055:    * @return array
1056:    */
1057:   public static function get_posts_by_languages() {
1058:     //Gli articoli senza lingua sono "figli di tutti"
1059:     if( empty( self::$_indexes ) ) self::_load_indexes();
1060: 
1061:     return self::$_indexes;
1062:   }
1063: 
1064:   /**
1065:    * check if $post_id has translation in selected language.
1066:    *
1067:    * @param int/string $lang - language id/slug
1068:    * @param int $post_id - post id
1069:    * 
1070:    * return boolean
1071:    */
1072:   public static function has_translation( $lang, $post_id ) {
1073:     if( ! isset( self::$_posts_meta[ $post_id ] ) ) {
1074:       self::$_posts_meta[ $post_id ] = self::get_translations( $post_id );
1075:     }
1076: 
1077:     if( is_numeric( $lang ) ) $lang = CMLLanguage::get_slug( $lang );
1078: 
1079:     return ( isset( self::$_posts_meta[ $post_id ]['indexes'] ) &&
1080:             self::$_posts_meta[ $post_id ]['indexes'][ $lang ] > 0 );
1081:   }
1082: 
1083:   /**
1084:    * check if $post_id has any translation
1085:    *
1086:    * @param int $post_id - post id
1087:    *
1088:    * @return boolean
1089:    */
1090:   public static function has_translations( $post_id ) {
1091:     if( ! isset( self::$_posts_meta[ $post_id ] ) ) {
1092:       self::$_posts_meta[ $post_id ] = self::get_translations( $post_id );
1093:     }
1094: 
1095:     return ! empty( self::$_posts_meta[ $post_id ][ 'linked' ] );
1096:   }
1097: 
1098:   /**
1099:    * check if $post1 is translation of $post2
1100:    *
1101:    * @param int $post1 post id
1102:    * @param int $post2 post id
1103:    *
1104:    * @return boolean
1105:    */
1106:   public static function is_translation( $post1, $post2 ) {
1107:     $translations = CMLPost::get_translations( $post1 );
1108: 
1109:     return in_array( $post2, $translations[ 'indexes' ] );
1110:   }
1111: 
1112:   /** @ignore */
1113:   private static function _load_indexes() {
1114:     $langs = cml_get_languages( false );
1115: 
1116:     foreach($langs as $lang) {
1117:       self::$_indexes[ $lang->id ] = get_option( "cml_posts_of_lang_" . $lang->id );
1118:     }
1119:   }
1120: 
1121:   /**
1122:    * @ignore
1123:    *
1124:    * Remove extra "-##" add by wordpress when more than one post has
1125:    * same titles, but ONLY on translations.
1126:    */
1127:   public static function remove_extra_number( $permalink, $post ) {
1128:     global $wpdb;
1129: 
1130:     $removed = false;
1131: 
1132:     if( is_object( $post ) && CMLPost::has_translations( $post->ID ) ) {
1133:       //Remove last "/"
1134:       $url = untrailingslashit( $permalink );
1135:       $url = str_replace( CMLUtils::home_url(), "", $url );
1136:   
1137:       /*
1138:        * Post/page link contains "-d"
1139:        */
1140:       preg_match_all( "/-\d+/", $url, $out );
1141:   
1142:       /*
1143:        * if true I have to check if it was added by "wordpress" :)
1144:        */
1145:       if( count( $out[ 0 ] ) > 0 ) {
1146:         /*
1147:          * when hook get_page_link, wordpress pass me only post id, not full object
1148:          */
1149:         $post_title = $post->post_title; //( ! isset( $post->post_name ) ) ?
1150:           //$post->post_title : $post->post_name;
1151:           // $a = $wpdb->get_var( "SELECT post_title FROM $wpdb->posts WHERE id = $post->ID" );
1152: 
1153:         /*
1154:          * got how many number occourrences ( -d ) are in the "real title"
1155:          */
1156:         preg_match_all( "/\d+/", $post_title, $pout );
1157: 
1158:         /*
1159:          * compare occourrences between permalink and title,
1160:          * if title contains more one, I remove it :)
1161:          */
1162:         //Remove autoinserted -## from url
1163:         if( count( $pout[0] ) < count( $out[ 0 ] ) ) {
1164:           $permalink = trailingslashit( preg_replace( "/-\d*$/", "",
1165:                                                      untrailingslashit( $permalink ) ) );
1166: 
1167:           $removed = true;
1168:         }
1169:       }
1170: 
1171:       if( $removed &&
1172:           CMLUtils::get_url_mode() == PRE_NONE ) {
1173:         $post_id = is_object( $post ) ? $post->ID : $post;
1174: 
1175:         $lang = CMLLanguage::get_by_post_id( $post_id );
1176:         if( empty( $lang ) ) {
1177:           $lang = CMLLanguage::get_current();
1178:         }
1179: 
1180:         $permalink = add_query_arg( array(
1181:                                           "lang" => $lang->cml_language_slug,
1182:                                           ), $permalink );
1183:       }
1184:     }
1185: 
1186:     return $permalink;
1187:   }
1188: }
1189: 
1190: /**
1191:  * utility class
1192:  *
1193:  */
1194: class CMLUtils {
1195:   /** @ignore */
1196:   private static $_permalink_structure;
1197:   /** @ignore */
1198:   private static $_url_mode;
1199:   /** @ignore */
1200:   private static $_date_format;
1201:   /** @ignore */
1202:   private static $_home_url;
1203:   /** @ignore */
1204:   private static $_clean_url;
1205:   /** @ignore */
1206:   private static $_clean_request;
1207:   /** @ignore */
1208:   private static $_request_url;
1209:   /** @ignore */
1210:   private static $_clean_applied = false;
1211:   /** @ignore */
1212:   private static $_url;
1213:   /** @ignore */
1214:   private static $_language_detected = null;
1215:   /** @ignore */
1216:   private static $_vars = array();
1217: 
1218:   /**
1219:    * @ignore
1220:    * 
1221:    * return wordpress permalink structure option
1222:    *
1223:    * @return string
1224:    */
1225:   public static function get_permalink_structure() {
1226:     if( ! isset( self::$_permalink_structure ) ) self::$_permalink_structure = get_option( "permalink_structure" );
1227:     
1228:     return self::$_permalink_structure;
1229:   }
1230:   
1231:   /**
1232:    * return home_url link in according to language slug.
1233:    *
1234:    * This function format home_url in according to $slug parameter
1235:    *
1236:    * @param string $slug - language slug. If null current slug will be used
1237:    *
1238:    * @return string
1239:    */
1240:   public static function get_home_url( $slug = null ) {
1241:     $_cml_settings = & $GLOBALS[ '_cml_settings' ];
1242: 
1243:     if( null === $slug ) $slug = CMLLanguage::get_default()->cml_language_slug;
1244: 
1245:     switch( CMLUtils::get_url_mode() ) {
1246:     case PRE_PATH:
1247:       if( $slug == CMLLanguage::get_default()->cml_language_slug &&
1248:           $_cml_settings[ 'url_mode_remove_default' ] ) {
1249:         $slug = "";
1250:       } else
1251:         $slug = "/$slug";
1252: 
1253:       $link = CMLUtils::home_url() . $slug;
1254:       break;
1255:     case PRE_DOMAIN:
1256:       $link = CMLUtils::home_url();
1257:       break;
1258:     default:
1259:       $link = CMLUtils::home_url() . "?lang=$slug";
1260:       break;
1261:     } //endswitch;
1262: 
1263:     return $link;
1264:   }
1265: 
1266:   /**
1267:    * @ignore
1268:    */
1269:   public static function get_url_mode() {
1270:     if( empty( self::$_url_mode ) )  {
1271:       global $_cml_settings;
1272:     
1273:       self::$_url_mode = $_cml_settings[ 'url_mode' ];  //more easy
1274:       
1275:       $permalink = self::get_permalink_structure();
1276:       if( empty( $permalink ) && self::$_url_mode == PRE_PATH )
1277:         self::$_url_mode = PRE_LANG;
1278:     }
1279: 
1280:     return self::$_url_mode;
1281:   }
1282:   
1283:   /**
1284:    * get wordpress date format option
1285:    * @ignore
1286:    */
1287:   public static function get_date_format() {
1288:     if( empty( self::$_date_format ) ) self::$_date_format = get_option( 'date_format' );
1289:     
1290:     return self::$_date_format;
1291:   }
1292:   
1293:   /**
1294:    * get "clean" home_url.
1295:    *
1296:    * The plugin translate home url in according to current language.
1297:    * So if you call the wp function "home_url" it will home url with language information,
1298:    * in according to url modification mode.
1299:    *
1300:    * This function will return "real" home without any language information.
1301:    *
1302:    * @example
1303:    *
1304:    * home_url()<br />
1305:    *  www.example.com/it<br />
1306:    * <br />
1307:    * CMLUtils::home_url()<br />
1308:    *  www.example.com<br />
1309:    * 
1310:    * @return string
1311:    */
1312:   public static function home_url() {
1313:     if( empty( self::$_home_url ) ) {
1314:       $GLOBALS[ '_cml_no_translate_home_url' ] = true;
1315:       self::$_home_url = home_url();
1316: 
1317:       unset( $GLOBALS[ '_cml_no_translate_home_url' ] );
1318:     }
1319: 
1320:     return self::$_home_url;
1321:   }
1322:   
1323:   /**
1324:    * remove language information from url
1325:    * 
1326:    * @ignore
1327:    */
1328:   public static function clear_url( $url = null ) {
1329:     global $wp_rewrite;
1330: 
1331:     if( self::get_url_mode() != PRE_PATH 
1332:         || ( self::$_clean_applied == true &&
1333:         null === $url ) ) {
1334:       return self::$_language_detected;
1335:     }
1336: 
1337:     if( empty( self::$_url ) ) {
1338:       self::$_url = "http://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
1339:       self::$_request_url = str_replace( trailingslashit( self::home_url() ),
1340:                                         "", self::$_url );
1341:     }
1342: 
1343:     if( null === $url ) {
1344:       $_url = self::$_url;
1345:       $request_url = self::$_request_url;
1346:       
1347:       /*
1348:        * remove all parameters in url
1349:        */
1350:       self::$_clean_url = preg_replace( "/\?.*/", "", $_url );
1351:       self::$_clean_request = $request_url;
1352:     } else {
1353:       $_url = $url;
1354:       $request_url = str_replace( trailingslashit( self::home_url() ),
1355:                                         "", $url );
1356:     }
1357: 
1358:     $_url = $request_url;
1359:     $base_url = str_replace( "http://" . $_SERVER['HTTP_HOST'], "", get_option( 'home' ) );
1360: 
1361:     if( preg_match( "#^([a-z]{2})(/.*)?$#i", $_url, $match ) ) {
1362:       $lang = CMLLanguage::get_id_by_slug( $match[1] );
1363:       if( empty( $lang ) ) {
1364:         return $url;
1365:       }
1366: 
1367:       $_url = substr( $_url, 3 );
1368:       $_url = preg_replace( "/\?.*/", "", $_url );
1369: 
1370:       if( null === $url ) {
1371:         self::$_language_detected = $lang;
1372: 
1373:         CMLLanguage::set_current( self::$_language_detected );
1374: 
1375:         self::$_clean_url = trailingslashit( self::$_home_url ) . $_url;
1376:         self::$_clean_request = trailingslashit( $base_url ) . $_url;
1377:       } else {
1378:         $_url = trailingslashit( CMLUtils::home_url() ) . $_url;
1379:       }
1380:     }
1381:     
1382:     if( null === $url ) {
1383:       self::$_clean_applied = true;
1384:     }
1385: 
1386:     return ( null === $url ) ? self::$_language_detected : $_url;
1387:   }
1388: 
1389:   /**
1390:    * return current url withouth any language information.
1391:    *
1392:    * @example
1393:    * 
1394:    *  www.example.com/en/example<br />
1395:    *<br />
1396:    *  CMLUtils::get_clean_url() will return:<br />
1397:    *<br />
1398:    *    www.example.com/example
1399:    *
1400:    * @return string
1401:    */
1402:   public static function get_clean_url() {
1403:     return self::$_clean_url;
1404:   }
1405:   
1406:   /**
1407:    * get $_SERVER[ 'REQUEST_URI' ] with no language information.
1408:    *
1409:    * @return string
1410:    */
1411:   public static function get_clean_request() {
1412:     return self::$_clean_request;
1413:   }
1414:   
1415:   /**
1416:    * @ignore
1417:    */
1418:   public static function _set( $key, $value ) {
1419:     self::$_vars[ $key ] = $value;
1420:   }
1421:   
1422:   /**
1423:    * @ignore
1424:    */
1425:   public static function _get( $key ) {
1426:     return isset( self::$_vars[ $key ] ) ? self::$_vars[ $key ] : null;
1427:   }
1428:   
1429:   /**
1430:    *@ignore
1431:    */
1432:   public static function _del( $key ) {
1433:     unset( self::$_vars[ $key ] );
1434:   }
1435: 
1436:   /**
1437:    * @ignore
1438:    */
1439:   public static function _append( $key, $value ) {
1440:     if( ! isset( self::$_vars[ $key ] ) ) {
1441:       self::$_vars[ $key ] = array();
1442:     }
1443:     
1444:     self::$_vars[ $key ][] = $value;
1445:   }
1446: }
1447: ?>
API documentation generated by ApiGen 2.8.0