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