PNG  IHDRQgAMA a cHRMz&u0`:pQ<bKGDgmIDATxwUﹻ& ^CX(J I@ "% (** BX +*i"]j(IH{~R)[~>h{}gy)I$Ij .I$I$ʊy@}x.: $I$Ii}VZPC)I$IF ^0ʐJ$I$Q^}{"r=OzI$gRZeC.IOvH eKX $IMpxsk.쒷/&r[޳<v| .I~)@$updYRa$I |M.e JaֶpSYR6j>h%IRز if&uJ)M$I vLi=H;7UJ,],X$I1AҒJ$ XY XzI@GNҥRT)E@;]K*Mw;#5_wOn~\ DC&$(A5 RRFkvIR}l!RytRl;~^ǷJj اy뷦BZJr&ӥ8Pjw~vnv X^(I;4R=P[3]J,]ȏ~:3?[ a&e)`e*P[4]T=Cq6R[ ~ޤrXR Հg(t_HZ-Hg M$ãmL5R uk*`%C-E6/%[t X.{8P9Z.vkXŐKjgKZHg(aK9ڦmKjѺm_ \#$5,)-  61eJ,5m| r'= &ڡd%-]J on Xm|{ RҞe $eڧY XYrԮ-a7RK6h>n$5AVڴi*ֆK)mѦtmr1p| q:흺,)Oi*ֺK)ܬ֦K-5r3>0ԔHjJئEZj,%re~/z%jVMڸmrt)3]J,T K֦OvԒgii*bKiNO~%PW0=dii2tJ9Jݕ{7"I P9JKTbu,%r"6RKU}Ij2HKZXJ,妝 XYrP ެ24c%i^IK|.H,%rb:XRl1X4Pe/`x&P8Pj28Mzsx2r\zRPz4J}yP[g=L) .Q[6RjWgp FIH*-`IMRaK9TXcq*I y[jE>cw%gLRԕiFCj-ďa`#e~I j,%r,)?[gp FI˨mnWX#>mʔ XA DZf9,nKҲzIZXJ,L#kiPz4JZF,I,`61%2s $,VOϚ2/UFJfy7K> X+6 STXIeJILzMfKm LRaK9%|4p9LwJI!`NsiazĔ)%- XMq>pk$-$Q2x#N ؎-QR}ᶦHZډ)J,l#i@yn3LN`;nڔ XuX5pF)m|^0(>BHF9(cզEerJI rg7 4I@z0\JIi䵙RR0s;$s6eJ,`n 䂦0a)S)A 1eJ,堌#635RIgpNHuTH_SԕqVe ` &S)>p;S$魁eKIuX`I4춒o}`m$1":PI<[v9^\pTJjriRŭ P{#{R2,`)e-`mgj~1ϣLKam7&U\j/3mJ,`F;M'䱀 .KR#)yhTq;pcK9(q!w?uRR,n.yw*UXj#\]ɱ(qv2=RqfB#iJmmL<]Y͙#$5 uTU7ӦXR+q,`I}qL'`6Kͷ6r,]0S$- [RKR3oiRE|nӦXR.(i:LDLTJjY%o:)6rxzҒqTJjh㞦I.$YR.ʼnGZ\ֿf:%55 I˼!6dKxm4E"mG_ s? .e*?LRfK9%q#uh$)i3ULRfK9yxm܌bj84$i1U^@Wbm4uJ,ҪA>_Ij?1v32[gLRD96oTaR׿N7%L2 NT,`)7&ƝL*꽙yp_$M2#AS,`)7$rkTA29_Iye"|/0t)$n XT2`YJ;6Jx".e<`$) PI$5V4]29SRI>~=@j]lp2`K9Jaai^" Ԋ29ORI%:XV5]JmN9]H;1UC39NI%Xe78t)a;Oi Ҙ>Xt"~G>_mn:%|~ޅ_+]$o)@ǀ{hgN;IK6G&rp)T2i୦KJuv*T=TOSV>(~D>dm,I*Ɛ:R#ۙNI%D>G.n$o;+#RR!.eU˽TRI28t)1LWϚ>IJa3oFbu&:tJ*(F7y0ZR ^p'Ii L24x| XRI%ۄ>S1]Jy[zL$adB7.eh4%%누>WETf+3IR:I3Xה)3אOۦSRO'ٺ)S}"qOr[B7ϙ.edG)^ETR"RtRݜh0}LFVӦDB^k_JDj\=LS(Iv─aTeZ%eUAM-0;~˃@i|l @S4y72>sX-vA}ϛBI!ݎߨWl*)3{'Y|iSlEڻ(5KtSI$Uv02,~ԩ~x;P4ցCrO%tyn425:KMlD ^4JRxSهF_}شJTS6uj+ﷸk$eZO%G*^V2u3EMj3k%)okI]dT)URKDS 7~m@TJR~荪fT"֛L \sM -0T KfJz+nإKr L&j()[E&I ߴ>e FW_kJR|!O:5/2跌3T-'|zX ryp0JS ~^F>-2< `*%ZFP)bSn"L :)+pʷf(pO3TMW$~>@~ū:TAIsV1}S2<%ޟM?@iT ,Eūoz%i~g|`wS(]oȤ8)$ ntu`өe`6yPl IzMI{ʣzʨ )IZ2= ld:5+請M$-ї;U>_gsY$ÁN5WzWfIZ)-yuXIfp~S*IZdt;t>KūKR|$#LcԀ+2\;kJ`]YǔM1B)UbG"IRߊ<xܾӔJ0Z='Y嵤 Leveg)$znV-º^3Ւof#0Tfk^Zs[*I꯳3{)ˬW4Ւ4 OdpbZRS|*I 55#"&-IvT&/윚Ye:i$ 9{LkuRe[I~_\ؠ%>GL$iY8 9ܕ"S`kS.IlC;Ҏ4x&>u_0JLr<J2(^$5L s=MgV ~,Iju> 7r2)^=G$1:3G< `J3~&IR% 6Tx/rIj3O< ʔ&#f_yXJiގNSz; Tx(i8%#4 ~AS+IjerIUrIj362v885+IjAhK__5X%nV%Iͳ-y|7XV2v4fzo_68"S/I-qbf; LkF)KSM$ Ms>K WNV}^`-큧32ŒVؙGdu,^^m%6~Nn&͓3ŒVZMsRpfEW%IwdǀLm[7W&bIRL@Q|)* i ImsIMmKmyV`i$G+R 0tV'!V)֏28vU7͒vHꦼtxꗞT ;S}7Mf+fIRHNZUkUx5SAJㄌ9MqμAIRi|j5)o*^'<$TwI1hEU^c_j?Е$%d`z cyf,XO IJnTgA UXRD }{H}^S,P5V2\Xx`pZ|Yk:$e ~ @nWL.j+ϝYb퇪bZ BVu)u/IJ_ 1[p.p60bC >|X91P:N\!5qUB}5a5ja `ubcVxYt1N0Zzl4]7­gKj]?4ϻ *[bg$)+À*x쳀ogO$~,5 زUS9 lq3+5mgw@np1sso Ӻ=|N6 /g(Wv7U;zωM=wk,0uTg_`_P`uz?2yI!b`kĸSo+Qx%!\οe|އԁKS-s6pu_(ֿ$i++T8=eY; צP+phxWQv*|p1. ά. XRkIQYP,drZ | B%wP|S5`~́@i޾ E;Չaw{o'Q?%iL{u D?N1BD!owPHReFZ* k_-~{E9b-~P`fE{AܶBJAFO wx6Rox5 K5=WwehS8 (JClJ~ p+Fi;ŗo+:bD#g(C"wA^ r.F8L;dzdIHUX݆ϞXg )IFqem%I4dj&ppT{'{HOx( Rk6^C٫O.)3:s(۳(Z?~ٻ89zmT"PLtw䥈5&b<8GZ-Y&K?e8,`I6e(֍xb83 `rzXj)F=l($Ij 2*(F?h(/9ik:I`m#p3MgLaKjc/U#n5S# m(^)=y=đx8ŬI[U]~SцA4p$-F i(R,7Cx;X=cI>{Km\ o(Tv2vx2qiiDJN,Ҏ!1f 5quBj1!8 rDFd(!WQl,gSkL1Bxg''՞^ǘ;pQ P(c_ IRujg(Wz bs#P­rz> k c&nB=q+ؔXn#r5)co*Ũ+G?7< |PQӣ'G`uOd>%Mctz# Ԫڞ&7CaQ~N'-P.W`Oedp03C!IZcIAMPUۀ5J<\u~+{9(FbbyAeBhOSܳ1 bÈT#ŠyDžs,`5}DC-`̞%r&ڙa87QWWp6e7 Rϫ/oY ꇅ Nܶըtc!LA T7V4Jsū I-0Pxz7QNF_iZgúWkG83 0eWr9 X]㾮݁#Jˢ C}0=3ݱtBi]_ &{{[/o[~ \q鯜00٩|cD3=4B_b RYb$óBRsf&lLX#M*C_L܄:gx)WΘsGSbuL rF$9';\4Ɍq'n[%p.Q`u hNb`eCQyQ|l_C>Lb꟟3hSb #xNxSs^ 88|Mz)}:](vbۢamŖ࿥ 0)Q7@0=?^k(*J}3ibkFn HjB׻NO z x}7p 0tfDX.lwgȔhԾŲ }6g E |LkLZteu+=q\Iv0쮑)QٵpH8/2?Σo>Jvppho~f>%bMM}\//":PTc(v9v!gոQ )UfVG+! 35{=x\2+ki,y$~A1iC6#)vC5^>+gǵ@1Hy٪7u;p psϰu/S <aʸGu'tD1ԝI<pg|6j'p:tպhX{o(7v],*}6a_ wXRk,O]Lܳ~Vo45rp"N5k;m{rZbΦ${#)`(Ŵg,;j%6j.pyYT?}-kBDc3qA`NWQū20/^AZW%NQ MI.X#P#,^Ebc&?XR tAV|Y.1!؅⨉ccww>ivl(JT~ u`ٵDm q)+Ri x/x8cyFO!/*!/&,7<.N,YDŽ&ܑQF1Bz)FPʛ?5d 6`kQձ λc؎%582Y&nD_$Je4>a?! ͨ|ȎWZSsv8 j(I&yj Jb5m?HWp=g}G3#|I,5v珿] H~R3@B[☉9Ox~oMy=J;xUVoj bUsl_35t-(ՃɼRB7U!qc+x4H_Qo֮$[GO<4`&č\GOc[.[*Af%mG/ ňM/r W/Nw~B1U3J?P&Y )`ѓZ1p]^l“W#)lWZilUQu`-m|xĐ,_ƪ|9i:_{*(3Gѧ}UoD+>m_?VPۅ15&}2|/pIOʵ> GZ9cmíتmnz)yߐbD >e}:) r|@R5qVSA10C%E_'^8cR7O;6[eKePGϦX7jb}OTGO^jn*媓7nGMC t,k31Rb (vyܴʭ!iTh8~ZYZp(qsRL ?b}cŨʊGO^!rPJO15MJ[c&~Z`"ѓޔH1C&^|Ш|rʼ,AwĴ?b5)tLU)F| &g٣O]oqSUjy(x<Ϳ3 .FSkoYg2 \_#wj{u'rQ>o;%n|F*O_L"e9umDds?.fuuQbIWz |4\0 sb;OvxOSs; G%T4gFRurj(֍ڑb uԖKDu1MK{1^ q; C=6\8FR艇!%\YÔU| 88m)֓NcLve C6z;o&X x59:q61Z(T7>C?gcļxѐ Z oo-08jہ x,`' ҔOcRlf~`jj".Nv+sM_]Zk g( UOPyεx%pUh2(@il0ݽQXxppx-NS( WO+轾 nFߢ3M<;z)FBZjciu/QoF 7R¥ ZFLF~#ȣߨ^<쩡ݛкvџ))ME>ώx4m#!-m!L;vv#~Y[đKmx9.[,UFS CVkZ +ߟrY٧IZd/ioi$%͝ب_ֶX3ܫhNU ZZgk=]=bbJS[wjU()*I =ώ:}-蹞lUj:1}MWm=̛ _ ¾,8{__m{_PVK^n3esw5ӫh#$-q=A̟> ,^I}P^J$qY~Q[ Xq9{#&T.^GVj__RKpn,b=`żY@^՝;z{paVKkQXj/)y TIc&F;FBG7wg ZZDG!x r_tƢ!}i/V=M/#nB8 XxЫ ^@CR<{䤭YCN)eKOSƟa $&g[i3.C6xrOc8TI;o hH6P&L{@q6[ Gzp^71j(l`J}]e6X☉#͕ ׈$AB1Vjh㭦IRsqFBjwQ_7Xk>y"N=MB0 ,C #o6MRc0|$)ف"1!ixY<B9mx `,tA>)5ػQ?jQ?cn>YZe Tisvh# GMމȇp:ԴVuږ8ɼH]C.5C!UV;F`mbBk LTMvPʍϤj?ԯ/Qr1NB`9s"s TYsz &9S%U԰> {<ؿSMxB|H\3@!U| k']$U+> |HHMLޢ?V9iD!-@x TIî%6Z*9X@HMW#?nN ,oe6?tQwڱ.]-y':mW0#!J82qFjH -`ѓ&M0u Uγmxϵ^-_\])@0Rt.8/?ٰCY]x}=sD3ojަЫNuS%U}ԤwHH>ڗjܷ_3gN q7[q2la*ArǓԖ+p8/RGM ]jacd(JhWko6ڎbj]i5Bj3+3!\j1UZLsLTv8HHmup<>gKMJj0@H%,W΃7R) ">c, xixј^ aܖ>H[i.UIHc U1=yW\=S*GR~)AF=`&2h`DzT󑓶J+?W+}C%P:|0H܆}-<;OC[~o.$~i}~HQ TvXΈr=b}$vizL4:ȰT|4~*!oXQR6Lk+#t/g lԁߖ[Jڶ_N$k*". xsxX7jRVbAAʯKҎU3)zSNN _'s?f)6X!%ssAkʱ>qƷb hg %n ~p1REGMHH=BJiy[<5 ǁJҖgKR*倳e~HUy)Ag,K)`Vw6bRR:qL#\rclK/$sh*$ 6덤 KԖc 3Z9=Ɣ=o>X Ώ"1 )a`SJJ6k(<c e{%kϊP+SL'TcMJWRm ŏ"w)qc ef꒵i?b7b('"2r%~HUS1\<(`1Wx9=8HY9m:X18bgD1u ~|H;K-Uep,, C1 RV.MR5άh,tWO8WC$ XRVsQS]3GJ|12 [vM :k#~tH30Rf-HYݺ-`I9%lIDTm\ S{]9gOڒMNCV\G*2JRŨ;Rҏ^ڽ̱mq1Eu?To3I)y^#jJw^Ńj^vvlB_⋌P4x>0$c>K†Aļ9s_VjTt0l#m>E-,,x,-W)سo&96RE XR.6bXw+)GAEvL)͞K4$p=Ũi_ѱOjb HY/+@θH9޼]Nԥ%n{ &zjT? Ty) s^ULlb,PiTf^<À] 62R^V7)S!nllS6~͝V}-=%* ʻ>G DnK<y&>LPy7'r=Hj 9V`[c"*^8HpcO8bnU`4JȪAƋ#1_\ XϘHPRgik(~G~0DAA_2p|J묭a2\NCr]M_0 ^T%e#vD^%xy-n}-E\3aS%yN!r_{ )sAw ڼp1pEAk~v<:`'ӭ^5 ArXOI驻T (dk)_\ PuA*BY]yB"l\ey hH*tbK)3 IKZ򹞋XjN n *n>k]X_d!ryBH ]*R 0(#'7 %es9??ښFC,ՁQPjARJ\Ρw K#jahgw;2$l*) %Xq5!U᢯6Re] |0[__64ch&_}iL8KEgҎ7 M/\`|.p,~`a=BR?xܐrQ8K XR2M8f ?`sgWS%" Ԉ 7R%$ N}?QL1|-эټwIZ%pvL3Hk>,ImgW7{E xPHx73RA @RS CC !\ȟ5IXR^ZxHл$Q[ŝ40 (>+ _C >BRt<,TrT {O/H+˟Pl6 I B)/VC<6a2~(XwV4gnXR ϱ5ǀHٻ?tw똤Eyxp{#WK qG%5],(0ӈH HZ])ג=K1j&G(FbM@)%I` XRg ʔ KZG(vP,<`[ Kn^ SJRsAʠ5xՅF`0&RbV tx:EaUE/{fi2;.IAwW8/tTxAGOoN?G}l L(n`Zv?pB8K_gI+ܗ #i?ޙ.) p$utc ~DžfՈEo3l/)I-U?aԅ^jxArA ΧX}DmZ@QLےbTXGd.^|xKHR{|ΕW_h] IJ`[G9{).y) 0X YA1]qp?p_k+J*Y@HI>^?gt.06Rn ,` ?);p pSF9ZXLBJPWjgQ|&)7! HjQt<| ؅W5 x W HIzYoVMGP Hjn`+\(dNW)F+IrS[|/a`K|ͻ0Hj{R,Q=\ (F}\WR)AgSG`IsnAR=|8$}G(vC$)s FBJ?]_u XRvύ6z ŨG[36-T9HzpW̞ú Xg큽=7CufzI$)ki^qk-) 0H*N` QZkk]/tnnsI^Gu't=7$ Z;{8^jB% IItRQS7[ϭ3 $_OQJ`7!]W"W,)Iy W AJA;KWG`IY{8k$I$^%9.^(`N|LJ%@$I}ֽp=FB*xN=gI?Q{٥4B)mw $Igc~dZ@G9K X?7)aK%݅K$IZ-`IpC U6$I\0>!9k} Xa IIS0H$I H ?1R.Чj:4~Rw@p$IrA*u}WjWFPJ$I➓/6#! LӾ+ X36x8J |+L;v$Io4301R20M I$-E}@,pS^ޟR[/s¹'0H$IKyfŸfVOπFT*a$I>He~VY/3R/)>d$I>28`Cjw,n@FU*9ttf$I~<;=/4RD~@ X-ѕzἱI$: ԍR a@b X{+Qxuq$IЛzo /~3\8ڒ4BN7$IҀj V]n18H$IYFBj3̵̚ja pp $Is/3R Ӻ-Yj+L;.0ŔI$Av? #!5"aʄj}UKmɽH$IjCYs?h$IDl843.v}m7UiI=&=0Lg0$I4: embe` eQbm0u? $IT!Sƍ'-sv)s#C0:XB2a w I$zbww{."pPzO =Ɔ\[ o($Iaw]`E).Kvi:L*#gР7[$IyGPI=@R 4yR~̮´cg I$I/<tPͽ hDgo 94Z^k盇΄8I56^W$I^0̜N?4*H`237}g+hxoq)SJ@p|` $I%>-hO0eO>\ԣNߌZD6R=K ~n($I$y3D>o4b#px2$yڪtzW~a $I~?x'BwwpH$IZݑnC㧄Pc_9sO gwJ=l1:mKB>Ab<4Lp$Ib o1ZQ@85b̍ S'F,Fe,^I$IjEdù{l4 8Ys_s Z8.x m"+{~?q,Z D!I$ϻ'|XhB)=…']M>5 rgotԎ 獽PH$IjIPhh)n#cÔqA'ug5qwU&rF|1E%I$%]!'3AFD/;Ck_`9 v!ٴtPV;x`'*bQa w I$Ix5 FC3D_~A_#O݆DvV?<qw+I$I{=Z8".#RIYyjǪ=fDl9%M,a8$I$Ywi[7ݍFe$s1ՋBVA?`]#!oz4zjLJo8$I$%@3jAa4(o ;p,,dya=F9ً[LSPH$IJYЉ+3> 5"39aZ<ñh!{TpBGkj}Sp $IlvF.F$I z< '\K*qq.f<2Y!S"-\I$IYwčjF$ w9 \ߪB.1v!Ʊ?+r:^!I$BϹB H"B;L'G[ 4U#5>੐)|#o0aڱ$I>}k&1`U#V?YsV x>{t1[I~D&(I$I/{H0fw"q"y%4 IXyE~M3 8XψL}qE$I[> nD?~sf ]o΁ cT6"?'_Ἣ $I>~.f|'!N?⟩0G KkXZE]ޡ;/&?k OۘH$IRۀwXӨ<7@PnS04aӶp.:@\IWQJ6sS%I$e5ڑv`3:x';wq_vpgHyXZ 3gЂ7{{EuԹn±}$I$8t;b|591nءQ"P6O5i }iR̈́%Q̄p!I䮢]O{H$IRϻ9s֧ a=`- aB\X0"+5"C1Hb?߮3x3&gşggl_hZ^,`5?ߎvĸ%̀M!OZC2#0x LJ0 Gw$I$I}<{Eb+y;iI,`ܚF:5ܛA8-O-|8K7s|#Z8a&><a&/VtbtLʌI$I$I$I$I$I$IRjDD%tEXtdate:create2022-05-31T04:40:26+00:00!Î%tEXtdate:modify2022-05-31T04:40:26+00:00|{2IENDB`Mini Shell

HOME


Mini Shell 1.0
DIR:/home/jaibharticollegehmr.in/www/wp-content/plugins/responsive-lightbox/includes/
Upload File :
Current File : /home/jaibharticollegehmr.in/www/wp-content/plugins/responsive-lightbox/includes/class-folders.php
<?php
// exit if accessed directly
if ( ! defined( 'ABSPATH' ) )
	exit;

/**
 * Responsive Lightbox folders class.
 *
 * @class Responsive_Lightbox_Folders
 */
class Responsive_Lightbox_Folders {

	private $mode = '';
	private $rl_media_tag_terms = [];
	private $term_counters = [
		'keys'		=> [],
		'values'	=> []
	];
	private $allowed_select_html = [
		'select'	=> [
			'name'				=> true,
			'id'				=> true,
			'class'				=> true,
			'required'			=> true,
			'tabindex'			=> true,
			'aria-describedby'	=> true
		],
		'option'	=> [
			'value'		=> true,
			'class'		=> true,
			'selected'	=> true
		]
	];

	/**
	 * Class constructor.
	 *
	 * @param bool $read_only Whether plugin is in read only mode
	 * @return void
	 */
	public function __construct( $read_only = false ) {
		// set instance
		Responsive_Lightbox()->folders = $this;

		// allow to load old taxonomies even in read only mode
		add_action( 'wp_ajax_rl-folders-load-old-taxonomies', [ $this, 'load_old_taxonomies' ] );

		if ( $read_only )
			return;

		// actions
		add_action( 'init', [ $this, 'detect_library_mode' ], 11 );
		add_action( 'restrict_manage_posts', [ $this, 'restrict_manage_posts' ] );
		add_action( 'wp_enqueue_media', [ $this, 'add_library_scripts' ] );
		add_action( 'admin_enqueue_scripts', [ $this, 'add_library_scripts' ] );
		add_action( 'pre-upload-ui', [ $this, 'pre_upload_ui' ] );
		add_action( 'post-upload-ui', [ $this, 'post_upload_ui' ] );
		add_action( 'add_attachment', [ $this, 'add_attachment' ] );
		add_action( 'wp_ajax_save-attachment-compat', [ $this, 'ajax_save_attachment_compat' ], 0 );
		add_action( 'wp_ajax_rl-folders-delete-term', [ $this, 'delete_term' ] );
		add_action( 'wp_ajax_rl-folders-rename-term', [ $this, 'rename_term' ] );
		add_action( 'wp_ajax_rl-folders-add-term', [ $this, 'add_term' ] );
		add_action( 'wp_ajax_rl-folders-move-term', [ $this, 'move_term' ] );
		add_action( 'wp_ajax_rl-folders-move-attachments', [ $this, 'move_attachments' ] );

		// filters
		add_filter( 'admin_body_class', [ $this, 'admin_body_class' ] );
		add_filter( 'parse_query', [ $this, 'parse_query' ] );
		add_filter( 'ajax_query_attachments_args', [ $this, 'ajax_query_attachments_args' ] );
		add_filter( 'attachment_fields_to_edit', [ $this, 'attachment_fields_to_edit' ], 10, 2 );
		add_filter( 'rl_count_attachments', [ $this, 'count_attachments' ], 10 );
	}

	/**
	 * Load previously used media taxonomies via AJAX.
	 *
	 * @return void
	 */
	public function load_old_taxonomies() {
		// no data?
		if ( ! isset( $_POST['taxonomies'], $_POST['nonce'] ) )
			wp_send_json_error();

		// invalid taxonomies format?
		if ( ! is_array( $_POST['taxonomies'] ) )
			wp_send_json_error();

		// invalid nonce?
		if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-taxonomies-nonce' ) )
			wp_send_json_error();

		// get all possible (current and previous) taxonomies
		$fields = $this->get_taxonomies();

		// any results?
		if ( ! empty( $fields ) ) {
			// remove main taxonomy
			if ( ( $key = array_search( 'rl_media_folder', $fields, true ) ) !== false )
				unset( $fields[$key] );

			// remove media tags
			if ( ( $key = array_search( 'rl_media_tag', $fields, true ) ) !== false )
				unset( $fields[$key] );

			// sanitize taxonomies
			$taxonomies = array_map( 'santize_key', $_POST['taxonomies'] );

			foreach ( $taxonomies as $taxonomy ) {
				// remove available taxonomy
				if ( ( $key = array_search( $taxonomy, $fields, true ) ) !== false )
					unset( $fields[$key] );
			}
		}

		// send taxonomies, reindex them to avoid casting to an object in js
		wp_send_json_success( [ 'taxonomies' => array_values( $fields ) ] );

	}

	/**
	 * Detect library mode (list or grid).
	 *
	 * @global string $pagenow
	 *
	 * @return void
	 */
	public function detect_library_mode() {
		global $pagenow;

		if ( $pagenow === 'upload.php' ) {
			// available modes
			$modes = [ 'grid', 'list' ];

			// sanitize mode
			if ( isset( $_GET['mode'] ) )
				$mode = sanitize_key( $_GET['mode'] );
			else
				$mode = '';

			// check mode
			if ( ! ( $mode && ctype_lower( $mode ) && in_array( $mode, $modes, true ) ) ) {
				// get user mode
				$user_mode = (string) get_user_option( 'media_library_mode' );

				// valid user mode?
				if ( in_array( $user_mode, $modes, true ) )
					$mode = $user_mode;
				// default wp mode
				else
					$mode = 'grid';
			}

			// store mode
			$this->mode = $mode;
		}

		if ( $pagenow === 'upload.php' || wp_doing_ajax() ) {
			$this->rl_media_tag_terms = get_terms(
				[
					'taxonomy'		=> 'rl_media_tag',
					'hide_empty'	=> false,
					'orderby'		=> 'name',
					'order'			=> 'asc',
					'number'		=> 0,
					'fields'		=> 'id=>name',
					'hierarchical'	=> false
				]
			);
		}
	}

	/**
	 * Admin body classes.
	 *
	 * @global string $pagenow
	 *
	 * @param array $classes Admin body classes
	 * @return array
	 */
	public function admin_body_class( $classes ) {
		global $pagenow;

		if ( $pagenow === 'upload.php' ) {
			// append class
			$classes .= ' rl-folders-upload-' . $this->mode . '-mode';
		}

		return $classes;
	}

	/**
	 * Get folders dropdown HTML.
	 *
	 * @param string $taxonomy Folders taxonomy
	 * @param string $selected Folders taxonomy ID
	 * @return string
	 */
	private function get_folders( $taxonomy, $selected = 0 ) {
		// get only 1 term to check if taxonomy is empty
		$any_terms = get_terms(
			[
				'taxonomy'		=> $taxonomy,
				'hide_empty'	=> false,
				'fields'		=> 'ids',
				'hierarchical'	=> false,
				'number'		=> 1
			]
		);

		// prepare dropdown categories parameters
		$args = [
			'orderby'			=> 'name',
			'order'				=> 'asc',
			'show_option_all'	=> __( 'Root Folder', 'responsive-lightbox' ),
			'show_count'		=> false,
			'hide_empty'		=> false,
			'hierarchical'		=> true,
			'hide_if_empty'		=> false,
			'echo'				=> false,
			'selected'			=> (int) $selected,
			'id'				=> 'rl_folders_upload_files',
			'name'				=> 'rl_folders_upload_files_term_id',
			'taxonomy'			=> $taxonomy
		];

		// no terms?
		if ( ! is_wp_error( $any_terms ) && empty( $any_terms ) ) {
			$args['show_option_none'] = __( 'Root Folder', 'responsive-lightbox' );
			$args['option_none_value'] = 0;
		}

		return wp_dropdown_categories( $args );
	}

	/**
	 * Add filter to add media folder id to the uploader
	 *
	 * @return void
	 */
	public function pre_upload_ui() {
		add_filter( 'upload_post_params', [ $this, 'upload_post_params' ] );
	}

	/**
	 * Add media folder id param to the uploader.
	 *
	 * @param array $params Plupload parameters
	 * @return array
	 */
	public function upload_post_params( $params ) {
		$params['rl_folders_upload_files_term_id'] = 0;

		return $params;
	}

	/**
	 * Display dropdown at media upload UI screen.
	 *
	 * @return void
	 */
	public function post_upload_ui() {
		// get taxonomy
		$taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];

		// get only 1 term to check if taxonomy is empty
		$any_terms = get_terms(
			[
				'taxonomy'		=> $taxonomy,
				'hide_empty'	=> false,
				'fields'		=> 'ids',
				'hierarchical'	=> false,
				'number'		=> 1
			]
		);

		// prepare dropdown categories parameters
		$args = [
			'orderby'			=> 'name',
			'order'				=> 'asc',
			'show_option_all'	=> __( 'Root Folder', 'responsive-lightbox' ),
			'show_count'		=> false,
			'hide_empty'		=> false,
			'hierarchical'		=> true,
			'hide_if_empty'		=> false,
			'echo'				=> false,
			'selected'			=> isset( $_GET[$taxonomy] ) ? (int) $_GET[$taxonomy] : 0,
			'id'				=> 'rl_folders_upload_files',
			'name'				=> 'rl_folders_upload_files_term_id',
			'taxonomy'			=> $taxonomy
		];

		// no terms?
		if ( ! is_wp_error( $any_terms ) && empty( $any_terms ) ) {
			$args['show_option_none'] = __( 'Root Folder', 'responsive-lightbox' );
			$args['option_none_value'] = 0;
		}

		// display select
		echo '<p><label>' . esc_html__( 'Upload files to', 'responsive-lightbox' ) . ': ' . wp_kses( wp_dropdown_categories( $args ), $this->allowed_select_html ) . '</label></p>';
	}

	/**
	 * Assign attachment to given term.
	 *
	 * @param int $post_id Current attachment ID
	 * @return void
	 */
	public function add_attachment( $post_id ) {
		if ( isset( $_POST['rl_folders_upload_files_term_id'] ) ) {
			// cast term id
			$term_id = (int) $_POST['rl_folders_upload_files_term_id'];

			// get taxonomy
			$taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];

			// valid term?
			if ( is_array( term_exists( $term_id, $taxonomy ) ) )
				wp_set_object_terms( $post_id, $term_id, $taxonomy, false );
		}
	}

	/**
	 * Add filterable dropdown to media library.
	 *
	 * @global string $pagenow
	 *
	 * @return void
	 */
	public function restrict_manage_posts() {
		global $pagenow;

		if ( $pagenow === 'upload.php' ) {
			// get taxonomy
			$taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];

			$html = wp_dropdown_categories(
				[
					'orderby'			=> 'name',
					'order'				=> 'asc',
					'id'				=> 'media-attachment-rl-folders-filters',
					'show_option_all'	=> __( 'All Files', 'responsive-lightbox' ),
					'show_count'		=> false,
					'hide_empty'		=> false,
					'hierarchical'		=> true,
					'selected'			=> ( isset( $_GET[$taxonomy] ) ? (int) $_GET[$taxonomy] : 0 ),
					'name'				=> $taxonomy,
					'taxonomy'			=> $taxonomy,
					'hide_if_empty'		=> true,
					'echo'				=> false
				]
			);

			if ( $html === '' )
				echo '<select name="' . esc_attr( $taxonomy ) . '" id="media-attachment-rl-folders-filters" class="postform"><option>' . esc_html__( 'All Files', 'responsive-lightbox' ) . '</option></select> ';
			else
				echo wp_kses( $html, $this->allowed_select_html );
		}
	}

	/**
	 * Change query to adjust taxonomy if needed.
	 *
	 * @global string $pagenow
	 *
	 * @param object $query WP Query
	 * @return object
	 */
	public function parse_query( $query ) {
		global $pagenow;

		// get taxonomy
		$taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];

		if ( $pagenow === 'upload.php' && isset( $_GET[$taxonomy] ) ) {
			// get tax query
			$tax_query = $query->get( 'tax_query' );

			if ( empty( $tax_query ) || ! is_array( $tax_query ) )
				$tax_query = [];

			// -1 === root, 0 === all files, >0 === term_id
			$term_id = (int) $_GET[$taxonomy];

			if ( $term_id !== 0 && ( $query->is_main_query() || empty( $query->query['rl_folders_root'] ) ) ) {
				$tax = [
					'taxonomy'	=> $taxonomy,
					'field'		=> 'id'
				];

				// root folder?
				if ( $term_id === -1 ) {
					$tax['terms'] = 0;
					$tax['operator'] = 'NOT EXISTS';
					$tax['include_children'] = false;
				// specified term id
				} else {
					$tax['terms'] = $term_id;
					$tax['include_children'] = false;
				}

				// add new tax query
				$tax_query[] = [ 'relation' => 'AND', $tax ];

				// set new tax query
				$query->set( 'tax_query', $tax_query );
			}
		}

		return $query;
	}

	/**
	 * Change AJAX query parameters to adjust taxonomy in the media library if needed.
	 *
	 * @param array $query Query arguments
	 * @return array
	 */
	public function ajax_query_attachments_args( $query ) {
		// get taxonomy
		$taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];

		if ( isset( $_POST['query'][$taxonomy] ) ) {
			$term_id = sanitize_key( $_POST['query'][$taxonomy] );

			if ( $term_id === 'all' )
				return $query;

			$term_id = (int) $term_id;

			if ( $term_id < 0 )
				return $query;

			if ( empty( $query['tax_query'] ) || ! is_array( $query['tax_query'] ) )
				$query['tax_query'] = [];

			$query['tax_query'][] = [
				'relation' => 'AND',
				[
					'taxonomy'			=> $taxonomy,
					'field'				=> 'id',
					'terms'				=> $term_id,
					'include_children'	=> ( ! ( isset( $_POST['query']['include_children'] ) && $_POST['query']['include_children'] === 'false' ) ),
					'operator'		 	=> ( $term_id === 0 ? 'NOT EXISTS' : 'IN' )
				]
			];
		}

		return $query;
	}

	/**
	 * Filter the array of attachment fields that are displayed when editing an attachment.
	 *
	 * @param array $fields Attachment fields
	 * @param object $post Post object
	 * @return array
	 */
	public function attachment_fields_to_edit( $fields, $post ) {
		if ( wp_doing_ajax() ) {
			// get main instance
			$rl = Responsive_Lightbox();

			// get taxonomy option
			$taxonomy = $rl->options['folders']['media_taxonomy'];

			// get taxonomy object
			$tax = (array) get_taxonomy( $taxonomy );

			if ( ! empty( $tax ) ) {
				if ( ! $tax['public'] || ! $tax['show_ui'] )
					return $fields;

				if ( empty( $tax['args'] ) )
					$tax['args'] = [];

				$ids = wp_get_post_terms( $post->ID, $taxonomy, [ 'fields' => 'ids' ] );

				// get select HTML
				$dropdown = wp_dropdown_categories(
					[
						'orderby'			=> 'name',
						'order'				=> 'asc',
						'show_option_none'	=> __( 'Root Folder', 'responsive-lightbox' ),
						'show_option_all'	=> false,
						'show_count'		=> false,
						'hide_empty'		=> false,
						'hierarchical'		=> true,
						'selected'			=> ( ! empty( $ids ) ? reset( $ids ) : 0 ),
						'name'				=> $taxonomy . '_term',
						'taxonomy'			=> $taxonomy,
						'hide_if_empty'		=> false,
						'echo'				=> false
					]
				);

				$tax['input'] = 'html';
				$tax['html'] = wp_kses( $dropdown, $this->allowed_select_html );

				$fields[$taxonomy] = $tax;
			}

			if ( $rl->options['folders']['media_tags'] && taxonomy_exists( 'rl_media_tag' ) ) {
				// get taxonomy object
				$tax = (array) get_taxonomy( 'rl_media_tag' );

				if ( ! empty( $tax ) ) {
					if ( ! $tax['public'] || ! $tax['show_ui'] )
						return $fields;

					if ( empty( $tax['args'] ) )
						$tax['args'] = [];

					$tags_html = '';

					// get terms
					$tags = wp_get_post_terms( $post->ID, 'rl_media_tag', [ 'fields' => 'id=>name' ] );

					// valid terms?
					if ( ! is_wp_error( $tags ) && ! empty( $tags ) ) {
						foreach ( $tags as $tag_name ) {
							$tags_html .= '<option value="' . esc_attr( $tag_name ) . '" selected="selected">' . esc_html( $tag_name ) . '</li>';
						}
					} else
						$tags = [];

					// update input
					$tax['input'] = 'html';

					// $tags_html is already escaped here
					$tax['html'] = '
					<select class="rl-media-tag-select2" multiple="multiple" name="attachments[' . (int) $post->ID . '][rl_media_tag]">
						' . $tags_html . '
					</select>';

					// update taxonomy
					$fields['rl_media_tag'] = $tax;
				}
			}
		}

		return $fields;
	}

	/**
	 * Assign new term IDs to given attachment ID via AJAX in modal attachment edit screen.
	 *
	 * @return void
	 */
	function ajax_save_attachment_compat() {
		// no attachment id?
		if ( ! isset( $_REQUEST['id'] ) )
			wp_send_json_error();

		$id = (int) $_REQUEST['id'];

		// invalid id?
		if ( $id <= 0 )
			wp_send_json_error();

		// no valid data?
		if ( empty( $_REQUEST['attachments'][$id] ) || ! is_array( $_REQUEST['attachments'][$id] ) )
			wp_send_json_error();

		// no sanitization like in wordpress core: wp_ajax_save_attachment_compat() function
		$attachment_data = $_REQUEST['attachments'][$id];

		// check nonce
		check_ajax_referer( 'update-post_' . $id, 'nonce' );

		if ( ! current_user_can( 'edit_post', $id ) )
			wp_send_json_error();

		// get post
		$post = get_post( $id, ARRAY_A );

		if ( empty( $post ) || $post['post_type'] !== 'attachment' )
			wp_send_json_error();

		// update attachment data if needed
		$post = apply_filters( 'attachment_fields_to_save', $post, $attachment_data );

		if ( isset( $post['errors'] ) )
			wp_send_json_error();

		// update attachment
		wp_update_post( $post );

		// get taxonomy
		$taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];

		// first if needed?
		if ( isset( $attachment_data[$taxonomy] ) )
			wp_set_object_terms( $id, (int) reset( array_map( 'trim', $attachment_data[$taxonomy] ) ), $taxonomy, false );
		elseif ( isset( $_REQUEST[$taxonomy . '_term'] ) )
			wp_set_object_terms( $id, (int) $_REQUEST[$taxonomy . '_term'], $taxonomy, false );
		else
			wp_set_object_terms( $id, '', $taxonomy, false );

		// check media tags
		if ( isset( $attachment_data['rl_media_tag'] ) && is_string( $attachment_data['rl_media_tag'] ) ) {
			$media_tags = explode( ',', $attachment_data['rl_media_tag'] );

			if ( ! empty( $media_tags ) && is_array( $media_tags ) )
				$media_tags = array_filter( array_map( 'sanitize_title', $media_tags ) );

			// any media tags?
			if ( ! empty( $media_tags ) )
				wp_set_object_terms( $id, $media_tags, 'rl_media_tag', false );
			else
				wp_set_object_terms( $id, '', 'rl_media_tag', false );
		}

		// get attachment data
		$attachment = wp_prepare_attachment_for_js( $id );

		// invalid attachment?
		if ( ! $attachment )
			wp_send_json_error();

		// finally send success
		wp_send_json_success( $attachment );
	}

	/**
	 * AJAX action to delete term.
	 *
	 * @return void
	 */
	public function delete_term() {
		// no data?
		if ( ! isset( $_POST['term_id'], $_POST['nonce'], $_POST['children'] ) )
			wp_send_json_error();

		// invalid nonce?
		if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-library-nonce' ) )
			wp_send_json_error();

		// sanitize term id
		$term_id = (int) $_POST['term_id'];

		if ( $term_id <= 0 )
			wp_send_json_error();

		// get taxonomy
		$taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];

		$remove_children = (int) $_POST['children'];

		// delete children?
		if ( $remove_children === 1 ) {
			// get term children
			$children = get_term_children( $term_id, $taxonomy );

			// found any children?
			if ( ! empty( $children ) && ! is_wp_error( $children ) ) {
				// reverse array to delete terms with no children first
				foreach ( array_reverse( $children ) as $child_id ) {
					// delete child
					wp_delete_term( $child_id, $taxonomy );
				}
			}
		}

		// delete parent
		if ( is_wp_error( wp_delete_term( $term_id, $taxonomy ) ) )
			wp_send_json_error();
		else
			wp_send_json_success( $this->get_folders( $taxonomy ) );
	}

	/**
	 * AJAX action to assign new parent of the term.
	 *
	 * @return void
	 */
	public function move_term() {
		// no data?
		if ( ! isset( $_POST['parent_id'], $_POST['term_id'], $_POST['nonce'] ) )
			wp_send_json_error();

		// invalid nonce?
		if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-library-nonce' ) )
			wp_send_json_error();

		// get taxonomy
		$taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];

		// update term
		$update = wp_update_term( (int) $_POST['term_id'], $taxonomy, [ 'parent' => (int) $_POST['parent_id'] ] );

		// error?
		if ( is_wp_error( $update ) )
			wp_send_json_error();
		else
			wp_send_json_success( $this->get_folders( $taxonomy ) );
	}

	/**
	 * AJAX action to add new term.
	 *
	 * @return void
	 */
	public function add_term() {
		// no data?
		if ( ! isset( $_POST['parent_id'], $_POST['name'], $_POST['nonce'] ) )
			wp_send_json_error();

		// invalid nonce?
		if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-library-nonce' ) )
			wp_send_json_error();

		// get taxonomy
		$taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];

		// prepare data
		$original_slug = $slug = sanitize_title( $_POST['name'] );
		$name = sanitize_text_field( $_POST['name'] );
		$parent_id = (int) $_POST['parent_id'];

		// empty name?
		if ( $original_slug === '' || $name === '' )
			wp_send_json_error();

		// get all term slugs
		$terms = get_terms(
			[
				'taxonomy'		=> $taxonomy,
				'hide_empty'	=> false,
				'number'		=> 0,
				'fields'		=> 'id=>slug',
				'hierarchical'	=> true
			]
		);

		// any terms?
		if ( ! is_wp_error( $terms ) && is_array( $terms ) && ! empty( $terms ) ) {
			$i = 2;

			// slug already exists? create unique one
			while ( in_array( $slug, $terms, true ) ) {
				$slug = $original_slug . '-' . $i ++;
			}
		}

		// add new term, name is sanitized inside wp_insert_term with sanitize_term function
		$term = wp_insert_term(
			$name,
			$taxonomy,
			[
				'parent'	=> $parent_id,
				'slug'		=> $slug
			]
		);

		// error?
		if ( is_wp_error( $term ) )
			wp_send_json_error();

		$term = get_term( $term['term_id'], $taxonomy );

		// error?
		if ( is_wp_error( $term ) )
			wp_send_json_error();
		else {
			wp_send_json_success(
				[
					'name'		=> $term->name,
					'term_id'	=> $term->term_id,
					'url'		=> admin_url( 'upload.php?mode=' . $this->mode . '&' . $taxonomy . '=' . $term->term_id ),
					'select'	=> $this->get_folders( $taxonomy, $term->term_id )
				]
			);
		}
	}

	/**
	 * AJAX action to rename term.
	 *
	 * @return void
	 */
	public function rename_term() {
		// no data?
		if ( ! isset( $_POST['term_id'], $_POST['name'], $_POST['nonce'] ) )
			wp_send_json_error();

		// invalid nonce?
		if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-library-nonce' ) )
			wp_send_json_error();

		// sanitize term id
		$term_id = (int) $_POST['term_id'];

		if ( $term_id <= 0 )
			wp_send_json_error();

		// get taxonomy
		$taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];

		// update term, name is sanitized inside wp_update_term with sanitize_term function
		$update = wp_update_term( $term_id, $taxonomy, [ 'name' => $_POST['name'] ] );

		// error?
		if ( is_wp_error( $update ) )
			wp_send_json_error();

		$term = get_term( $term_id, $taxonomy );

		// error?
		if ( is_wp_error( $term ) )
			wp_send_json_error();
		else {
			wp_send_json_success(
				[
					'name'		=> $term->name,
					'select'	=> $this->get_folders( $taxonomy, $term_id )
				]
			);
		}
	}

	/**
	 * AJAX action to assign new term to attachments.
	 *
	 * @return void
	 */
	public function move_attachments() {
		// no data?
		if ( ! isset( $_POST['attachment_ids'], $_POST['old_term_id'], $_POST['new_term_id'], $_POST['nonce'] ) )
			wp_send_json_error();

		// invalid nonce?
		if ( ! ctype_alnum( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'rl-folders-ajax-library-nonce' ) )
			wp_send_json_error();

		// not empty attachment ids array?
		if ( empty( $_POST['attachment_ids'] ) || ! is_array( $_POST['attachment_ids'] ) )
			wp_send_json_error();

		// prepare data
		$ids = $all_terms = [];
		$attachments = [
			'success'		=> [],
			'failure'		=> [],
			'duplicated'	=> []
		];

		// filter unwanted data
		$ids = array_unique( array_filter( array_map( 'intval', $_POST['attachment_ids'] ) ) );

		// no ids?
		if ( empty( $ids ) )
			wp_send_json_error();

		// prepare term ids
		$old_term_id = (int) $_POST['old_term_id'];
		$new_term_id = (int) $_POST['new_term_id'];

		// get taxonomy
		$taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];

		// moving to root folder?
		if ( $new_term_id === 0 ) {
			foreach ( $ids as $id ) {
				// get attachment term ids
				$all_terms[$id] = wp_get_object_terms( $id, $taxonomy, [ 'fields' => 'ids' ] );

				// remove all terms assigned to attachment
				if ( ! is_wp_error( wp_set_object_terms( $id, null, $taxonomy, false ) ) )
					$attachments['success'][] = $id;
				else
					$attachments['failure'][] = $id;
			}
		} else {
			foreach ( $ids as $id ) {
				// get attachment term ids
				$terms = wp_get_object_terms( $id, $taxonomy, [ 'fields' => 'ids' ] );

				// got terms?
				if ( ! is_wp_error( $terms ) ) {
					// save existing term (attachment already assigned to this term)
					if ( in_array( $new_term_id, $terms, true ) )
						$attachments['duplicated'][] = $id;

					// update attachment's term
					if ( ! is_wp_error( wp_set_object_terms( $id, $new_term_id, $taxonomy, false ) ) )
						$attachments['success'][] = $id;
					else
						$attachments['failure'][] = $id;
				}
			}
		}

		if ( empty( $attachments['success'] ) )
			wp_send_json_error();
		else {
			wp_send_json_success(
				[
					'attachments'	=> $attachments,
					'terms'			=> $all_terms
				]
			);
		}
	}

	/**
	 * Change wp_list_categories HTML link.
	 *
	 * @param array $matches Matched elements
	 * @return string
	 */
	public function replace_folders_href( $matches ) {
		// get taxonomy
		$taxonomy = Responsive_Lightbox()->options['folders']['media_taxonomy'];

		// set 'all files' folder
		$term_id = -1;
		$url_term_id = 0;

		// any matches?
		if ( ! empty( $matches[1] ) ) {
			$params = parse_url( html_entity_decode( urldecode( $matches[1] ) ) );

			if ( isset( $params['query'] ) ) {
				// parse query string
				parse_str( $params['query'], $atts );

				if ( isset( $atts['term'] ) ) {
					// get term
					$term = get_term_by( 'slug', $atts['term'], $taxonomy );

					// valid term?
					if ( $term !== false ) {
						$this->term_counters['keys'][] = $term->term_id;

						// set term id
						$url_term_id = $term_id = $term->term_id;
					}
				}
			}
		}

		// escape url early
		return 'href="' . esc_url( apply_filters( 'rl_folders_media_folder_url', add_query_arg( [ 'mode' => $this->mode, $taxonomy => $url_term_id ] ), $matches, $this->mode, $url_term_id ) ) . '" data-term_id="' . (int) $term_id . '"';
	}

	/**
	 * Change wp_list_categories HTML link by adding attachment counter.
	 *
	 * @param array $matches Matched elements
	 * @return string
	 */
	public function replace_folders_count( $matches ) {
		if ( isset( $matches[1] ) ) {
			$count = (int) str_replace( [ ' ', '&nbsp;' ], '', $matches[1] );
			$this->term_counters['values'][] = $count;

			return ' (' . $count . ')</a>';
		}

		return '</a>';
	}

	/**
	 * Change wp_list_categories HTML output by adding jsTree attributes if needed.
	 *
	 * @param array $matches Matched elements
	 * @return string
	 */
	public function open_folders( $matches ) {
		if ( isset( $matches[0] ) ) {
			// open parent term
			if ( isset( $matches[0] ) && strpos( $matches[0], 'current-cat-ancestor' ) !== false )
				return $matches[0] . ' data-jstree=\'{ "opened": true }\'';

			// select current term
			if ( strpos( $matches[0], 'current-cat' ) !== false )
				return $matches[0] . ' data-jstree=\'{ "selected": true }\'';
		}
	}

	/**
	 * Enqueue all needed scripts and styles for media library and modal screens.
	 *
	 * @global string $pagenow
	 * @global object $wp_list_table
	 * @global array $_wp_admin_css_colors
	 *
	 * @param string $page Current page similar to $pagenow depends on from which filter function was called
	 * @return void
	 */
	public function add_library_scripts( $page ) {
		// count how many times function was executed, allow this only once
		static $run = 0;

		// allow only wp media scripts (empty $page), upload.php or media-new.php
		if ( ! ( ( $page === '' || $page === 'upload.php' || $page === 'media-new.php' ) && $run < 1 ) )
			return;

		global $pagenow;

		$run++;

		// change page for wp_enqueue_media
		if ( $page === '' ) {
			if ( $pagenow === 'upload.php' )
				$page = 'upload.php';
			else
				$page = 'media';
		}

		// get main instance
		$rl = Responsive_Lightbox();

		// include select2 styles
		wp_enqueue_style( 'responsive-lightbox-admin-select2', RESPONSIVE_LIGHTBOX_URL . '/assets/select2/select2' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css', [], $rl->defaults['version'] );

		// filterable media folders taxonomy
		$taxonomy = get_taxonomy( $rl->options['folders']['media_taxonomy'] );

		// no taxonomy? it should be available here, updated in init_folders method
		if ( $taxonomy === false )
			return;

		// main script dependencies
		$dependencies = [ 'jquery', 'underscore', 'jquery-ui-draggable', 'jquery-ui-droppable', 'media-models', 'tags-suggest' ];

		// create folder counters
		$counters = [];

		if ( $page !== 'media' ) {
			// prepare variables
			$no_items = '';
			$childless = false;

			// include styles
			wp_enqueue_style( 'responsive-lightbox-folders-admin-css', RESPONSIVE_LIGHTBOX_URL . '/css/admin-folders.css' );
			wp_enqueue_style( 'responsive-lightbox-folders-perfect-scrollbar', RESPONSIVE_LIGHTBOX_URL . '/assets/perfect-scrollbar/perfect-scrollbar' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css' );
			wp_enqueue_style( 'responsive-lightbox-folders-jstree', RESPONSIVE_LIGHTBOX_URL . '/assets/jstree/themes/default/style' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.css' );

			// get color scheme global
			global $_wp_admin_css_colors;

			// set default color;
			$color = '0,160,210';

			if ( ! empty( $_wp_admin_css_colors ) ) {
				// get current admin color scheme name
				$current_color_scheme = get_user_option( 'admin_color' );

				if ( empty( $current_color_scheme ) )
					$current_color_scheme = 'fresh';

				// color exists? some schemes don't have 4 colors
				if ( isset( $_wp_admin_css_colors[$current_color_scheme] ) && property_exists( $_wp_admin_css_colors[$current_color_scheme], 'colors' ) && isset( $_wp_admin_css_colors[$current_color_scheme]->colors[3] ) ) {
					// convert color
					$rgb = $rl->hex2rgb( $_wp_admin_css_colors[$current_color_scheme]->colors[3] );

					// valid color?
					if ( $rgb !== false )
						$color = implode( ',', $rgb );
				}
			}

			// $color is already validated, no escaping
			wp_add_inline_style(
				'responsive-lightbox-folders-jstree',
				'#rl-folders-tree-container .jstree .rl-folders-state-active.rl-folders-state-hover {
					background: #fff !important;
				}
				#rl-folders-tree-container .jstree-container-ul .jstree-wholerow-clicked,
				#rl-folders-tree-container .jstree-container-ul:not(.jstree-wholerow-ul) .jstree-clicked {
					background: rgba(' . esc_attr( $color ) . ', 0.15);
				}
				#rl-folders-tree-container .jstree-container-ul .jstree-wholerow-hovered,
				#rl-folders-tree-container .jstree-container-ul:not(.jstree-wholerow-ul) .jstree-hovered {
					background: rgba(' . esc_attr( $color ) . ', 0.05);
				}'
			);

			// list categories parameters
			$categories = [
				'orderby'				=> 'name',
				'order'					=> 'asc',
				'show_count'			=> true,
				'show_option_all'		=> '',
				'show_option_none'		=> '',
				'use_desc_for_title'	=> false,
				'title_li'				=> '',
				'hide_empty'			=> false,
				'hierarchical'			=> true,
				'taxonomy'				=> $taxonomy->name,
				'hide_title_if_empty'	=> true,
				'echo'					=> false
			];

			// get current term id
			$term_id = isset( $_GET[$taxonomy->name] ) ? (int) $_GET[$taxonomy->name] : 0;

			// list mode?
			if ( $this->mode === 'list' ) {
				// get global wp list table instance
				global $wp_list_table;

				// empty instance?
				if ( is_null( $wp_list_table ) )
					$wp_list_table = _get_list_table( 'WP_Media_List_Table' );

				// start buffering
				ob_start();

				// display "no media" table row
				echo '<tr class="no-items"><td class="colspanchange" colspan="' . (int) $wp_list_table->get_column_count() . '">';

				$wp_list_table->no_items();

				echo '</td></tr>';

				// save "no media" table row
				$no_items = ob_get_contents();

				// clear the buffer
				ob_end_clean();

				// valid term?
				if ( $term_id > 0 ) {
					$children = get_term_children( $term_id, $taxonomy->name );

					// found any children?
					$childless = ! ( ! empty( $children ) && ! is_wp_error( $children ) );
				}
			}

			// set current term id
			if ( $term_id > 0 )
				$categories['current_category'] = $term_id;

			// hide filter for grid
			if ( $this->mode !== 'list' ) {
				wp_add_inline_style(
					'responsive-lightbox-folders-admin-css',
					'#media-attachment-rl-folders-filters { display: none; }
					.media-modal-content .media-frame select.attachment-filters {
						max-width: 100%;
						min-width: auto;
					}'
				);
			}

			// get taxonomy html output
			$html = wp_list_categories( $categories );

			if ( $html !== '' ) {
				// fix for urls
				$html = preg_replace_callback( '/href=(?:\'|")(.*?)(?:\'|")/', [ $this, 'replace_folders_href' ], $html );

				// fix for counters
				$html = preg_replace_callback( '/<\/a> \(((?:\d+|&nbsp;)+)\)/', [ $this, 'replace_folders_count' ], $html );

				// open all needed folders at start
				if ( $term_id > 0 )
					$html = preg_replace_callback( '/class="cat-item cat-item-(\d+)(?:[a-z\s0-9-]+)?"/', [ $this, 'open_folders' ], $html );

				// check whether counters are valid
				if ( ! ( empty( $this->term_counters['keys'] ) || empty( $this->term_counters['values'] ) || count( $this->term_counters['keys'] ) !== count( $this->term_counters['values'] ) ) ) {
//@TODO counters are supposed to be used in JS but not implemented yet
					// update folder counters
					$counters = array_combine( $this->term_counters['keys'], $this->term_counters['values'] );
				}
			}

			// root folder query
			$root_query = new WP_Query(
				apply_filters(
					'rl_root_folder_query_args',
					[
						'rl_folders_root'	=> true,
						'posts_per_page'	=> -1,
						'post_type'			=> 'attachment',
						'post_status'		=> 'inherit,private',
						'fields'			=> 'ids',
						'no_found_rows'		=> false,
						'tax_query'			=> [
							[
								'relation' => 'AND',
								[
									'taxonomy'			=> $taxonomy->name,
									'field'				=> 'id',
									'terms'				=> 0,
									'include_children'	=> false,
									'operator'			=> 'NOT EXISTS'
								]
							]
						]
					]
				)
			);

			// set number of all attachments
			$counters[-1] = (int) apply_filters( 'rl_count_attachments', 0 );

			// set number of root attachments (not categorized)
			$counters[0] = (int) $root_query->post_count;

			$html = '
			<ul>
				<li class="cat-item cat-item-all"' . ( $term_id === 0 ? ' data-jstree=\'{ "selected": true }\'' : '' ) . '>
					<a href="' . esc_url( apply_filters( 'rl_folders_media_folder_url', add_query_arg( [ 'mode' => $this->mode, $taxonomy->name => 0 ] ), null, $this->mode, 0 ) ) . '" data-term_id="all">' . esc_html__( 'All Files', 'responsive-lightbox' ) . ' (' . (int) $counters[-1] . ')</a>
				</li>
				<li class="cat-item cat-item-0" data-jstree=\'{ "opened": true' . ( $term_id === -1 ? ', "selected": true ' : '' ) . ' }\'>
					<a href="' . esc_url( apply_filters( 'rl_folders_media_folder_url', add_query_arg( [ 'mode' => $this->mode, $taxonomy->name => -1 ] ), null, $this->mode, -1 ) ) . '" data-term_id="0">' . esc_html__( 'Root Folder', 'responsive-lightbox' ) . ' (' . (int) $counters[0] . ')</a>
				<ul>' . $html . '</ul>
				</li>
			</ul>';

			// register scripts
			wp_register_script( 'responsive-lightbox-folders-jstree', RESPONSIVE_LIGHTBOX_URL . '/assets/jstree/jstree' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', [], $rl->defaults['version'], false );
			wp_register_script( 'responsive-lightbox-folders-perfect-scrollbar', RESPONSIVE_LIGHTBOX_URL . '/assets/perfect-scrollbar/perfect-scrollbar' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', [], $rl->defaults['version'], false );

			$dependencies[] = 'responsive-lightbox-folders-jstree';
			$dependencies[] = 'responsive-lightbox-folders-perfect-scrollbar';
		}

		wp_enqueue_script( 'responsive-lightbox-admin-select2', RESPONSIVE_LIGHTBOX_URL . '/assets/select2/select2.full' . ( ! ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.min' : '' ) . '.js', [ 'jquery' ], $rl->defaults['version'], false );

		wp_enqueue_script( 'responsive-lightbox-folders-admin', RESPONSIVE_LIGHTBOX_URL . '/js/admin-folders.js', $dependencies, $rl->defaults['version'], false );

		if ( $page === 'media' ) {
			// prepare script data
			$script_data = [
				'taxonomy'	=> $taxonomy->name,
				'page'		=> $page,
				'root'		=> esc_html__( 'Root Folder', 'responsive-lightbox' ),
				'terms'		=> wp_dropdown_categories(
					[
						'orderby'			=> 'name',
						'order'				=> 'asc',
						'show_option_all'	=> esc_html__( 'All Files', 'responsive-lightbox' ),
						'show_count'		=> false,
						'hide_empty'		=> false,
						'hierarchical'		=> true,
						'selected'			=> ( isset( $_GET[$taxonomy->name] ) ? (int) $_GET[$taxonomy->name] : 0 ),
						'name'				=> $taxonomy->name,
						'taxonomy'			=> $taxonomy->name,
						'hide_if_empty'		=> true,
						'echo'				=> false
					]
				)
			];
		} else {
			// prepare script data
			$script_data = [
				'remove_children'	=> $rl->options['folders']['folders_removal'],
				'wholerow'			=> $rl->options['folders']['jstree_wholerow'],
				'theme'				=> 'default',
				'counters'			=> $counters,
				'no_media_items'	=> $no_items,
				'taxonomy'			=> $taxonomy->name,
				'page'				=> $page,
				'root'				=> esc_html__( 'Root Folder', 'responsive-lightbox' ),
				'all_terms'			=> esc_html__( 'All Files', 'responsive-lightbox' ),
				'new_folder'		=> esc_html__( 'New Folder', 'responsive-lightbox' ),
				'delete_term'		=> esc_html__( 'Are you sure you want to delete this folder?', 'responsive-lightbox' ),
				'delete_terms'		=> esc_html__( 'Are you sure you want to delete this folder with all subfolders?', 'responsive-lightbox' ),
				'nonce'				=> wp_create_nonce( 'rl-folders-ajax-library-nonce' ),
				'terms'				=> wp_dropdown_categories(
					[
						'orderby'			=> 'name',
						'order'				=> 'asc',
						'show_option_all'	=> esc_html__( 'All Files', 'responsive-lightbox' ),
						'show_count'		=> false,
						'hide_empty'		=> false,
						'hierarchical'		=> true,
						'selected'			=> ( isset( $_GET[$taxonomy->name] ) ? (int) $_GET[$taxonomy->name] : 0 ),
						'name'				=> $taxonomy->name,
						'taxonomy'			=> $taxonomy->name,
						'hide_if_empty'		=> true,
						'echo'				=> false
					]
				),
				'template'			=> '
					<div id="rl-folders-tree-container">
						<div class="media-toolbar wp-filter">
							<div class="view-switch rl-folders-action-links">
								<a href="#" title="' . esc_attr( $taxonomy->labels->add_new_item ) . '" class="dashicons dashicons-plus rl-folders-add-new-folder' . ( $this->mode === 'list' && ( $term_id === -1 || $term_id > 0 ) ? '' : ' disabled-link' ) . '"></a>
								<a href="#" title="' . esc_attr( sprintf( __( 'Save new %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-yes rl-folders-save-new-folder" style="display: none;"></a>
								<a href="#" title="' . esc_attr( sprintf( __( 'Cancel adding new %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-no rl-folders-cancel-new-folder" style="display: none;"></a>
								<a href="#" title="' . esc_attr( $taxonomy->labels->edit_item ) . '" class="dashicons dashicons-edit rl-folders-rename-folder' . ( $this->mode === 'list' && $term_id > 0 ? '' : ' disabled-link' ) . '"></a>
								<a href="#" title="' . esc_attr( sprintf( __( 'Save %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-yes rl-folders-save-folder" style="display: none;"></a>
								<a href="#" title="' . esc_attr( sprintf( __( 'Cancel renaming %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-no rl-folders-cancel-folder" style="display: none;"></a>
								<a href="#" title="' . esc_attr( sprintf( __( 'Delete %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-trash rl-folders-delete-folder' . ( $this->mode === 'list' && $term_id > 0 ? '' : ' disabled-link' ) . '"></a>
								<a href="#" title="' . esc_attr( sprintf( __( 'Expand %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-arrow-down-alt2 rl-folders-expand-folder' . ( $this->mode === 'list' && ! $childless && ( $term_id === -1 || $term_id > 0 ) ? '' : ' disabled-link' ) . '"></a>
								<a href="#" title="' . esc_attr( sprintf( __( 'Collapse %s', 'responsive-lightbox' ), $taxonomy->labels->singular_name ) ) . '" class="dashicons dashicons-arrow-up-alt2 rl-folders-collapse-folder' . ( $this->mode === 'list' && ! $childless && ( $term_id === -1 || $term_id > 0 ) ? '' : ' disabled-link' ) . '"></a>
							</div>
						</div>
						<div id="rl-folders-tree">' . wp_kses_post( $html ) . '</div>
					</div>'
			];
		}

		wp_add_inline_script( 'responsive-lightbox-folders-admin', 'var rlFoldersArgs = ' . wp_json_encode( $script_data ) . ";\n", 'before' );

		add_action( 'admin_print_styles', [ $this, 'admin_print_media_styles' ] );
	}

	/**
	 * CSS fix for media folders checklist.
	 *
	 * @return void
	 */
	public function admin_print_media_styles() {
		echo '<style>.rl_media_folder li .selectit input[type="checkbox"] { margin: 0 3px; }</style>';
	}

	/**
	 * Count attachments.
	 *
	 * @return int
	 */
	public function count_attachments() {
		$count = wp_count_posts( 'attachment' );

		return (int) $count->inherit;
	}

	/**
	 * Get all previously used media taxonomies.
	 *
	 * @global object $wpdb
	 *
	 * @return array
	 */
	public function get_taxonomies() {
		global $wpdb;

		// query
		$fields = $wpdb->get_col( "
			SELECT DISTINCT tt.taxonomy
			FROM " . $wpdb->prefix . "term_taxonomy tt
			LEFT JOIN " . $wpdb->prefix . "term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
			LEFT JOIN " . $wpdb->prefix . "posts p ON p.ID = tr.object_id
			WHERE p.post_type = 'attachment'
			ORDER BY tt.taxonomy ASC"
		);

		if ( ! empty( $fields ) ) {
			// remove polylang taxonomy
			if ( ( $key = array_search( 'language', $fields, true ) ) !== false )
				unset( $fields[$key] );
		}

		return $fields;
	}
}