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/helphum.com/www/wp-content/plugins/autoptimize/classes/
Upload File :
Current File : //home/helphum.com/www/wp-content/plugins/autoptimize/classes/autoptimizeCriticalCSSCron.php
<?php
/**
 * Critical CSS Cron logic:
 * processes the queue, submitting jobs to criticalcss.com and retrieving generated CSS from criticalcss.com and saving rules.
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class autoptimizeCriticalCSSCron {
    public function __construct() {
        $this->criticalcss = autoptimize()->criticalcss();

        // Add queue control to a registered event.
        add_action( 'ao_ccss_queue', array( $this, 'ao_ccss_queue_control' ) );
        // Add cleaning job to a registered event.
        add_action( 'ao_ccss_maintenance', array( $this, 'ao_ccss_cleaning' ) );
    }

    public function ao_ccss_queue_control() {
        // The queue execution backend.
        $key = $this->criticalcss->get_option( 'key' );

        if ( empty( $key ) ) {
            // no key set, not processing the queue!
            $this->criticalcss->log( 'No key set, so not processing queue.', 3 );
            return;
        }

        /**
         * Provide a debug facility for the queue
         *    This debug facility provides a way to easily force some queue behaviors useful for development and testing.
         *    To enable this feature, create the file AO_CCSS_DIR . 'queue.json' with a JSON object like the one bellow:
         *
         *    {"enable":bool,"htcode":int,"status":0|"str","resultStatus ":0|"str","validationStatus":0|"str"}
         *
         *    Where values are:
         *    - enable                    : 0 or 1, enable or disable this debug facility straight from the file
         *    - htcode                    : 0 or any HTTP reponse code (e.g. 2xx, 4xx, 5xx) to force API responses
         *    - status                    : 0 or a valid value for 'status' (see 'Generating critical css - Job Status Types' in spec docs)
         *    - resultStatus        : 0 or a valid value for 'resultStatus' (see 'Appendix - Result status types' in the spec docs)
         *    - validationStatus: 0 or a valid value for 'validationStatus' (see 'Appendix - Validation status types' in the spec docs)
         *
         *    When properly set, queue will always finish a job with the declared settings above regardless of the real API responses.
         */
        $queue_debug = false;
        if ( file_exists( AO_CCSS_DEBUG ) ) {
            $qdobj_raw = file_get_contents( AO_CCSS_DEBUG );
            $qdobj     = json_decode( $qdobj_raw, true );
            if ( $qdobj ) {
                if ( 1 === $qdobj['enable'] ) {
                    $queue_debug = true;
                    $this->criticalcss->log( 'Queue operating in debug mode with the following settings: <' . $qdobj_raw . '>', 3 );
                }
            }
        }

        // Set some default values for $qdobj to avoid function call warnings.
        if ( ! $queue_debug ) {
            $qdobj['htcode'] = false;
        }

        // Check if queue is already running.
        $queue_lock = false;
        if ( file_exists( AO_CCSS_LOCK ) ) {
            $queue_lock = true;
        }

        // Proceed with the queue if it's not already running.
        if ( ! $queue_lock ) {

            // Log queue start and create the lock file.
            $this->criticalcss->log( 'Queue control started', 3 );
            if ( touch( AO_CCSS_LOCK ) ) {
                $this->criticalcss->log( 'Queue control locked', 3 );
            }

            // Attach required variables.
            $queue = $this->criticalcss->get_option( 'queue' );
            $rtimelimit = $this->criticalcss->get_option( 'rtimelimit' );

            // make sure we have the queue and bail if not.
            if ( empty( $queue ) || ! is_array( $queue ) ) {
                $this->criticalcss->log( 'Job processing cannot work on an empty queue, aborting.', 3 );
                unlink( AO_CCSS_LOCK );
                return;
            }

            // Initialize counters.
            if ( 0 == $rtimelimit ) {
                // no time limit set, let's go with 1000 seconds.
                $rtimelimit = 1000;
            }
            $mt = time() + $rtimelimit; // maxtime queue processing can run.
            $jc = 1; // job count number.
            $jr = 1; // jobs requests number.
            $jt = count( $queue ); // number of jobs in queue.

            // Sort queue by ascending job status (e.g. ERROR, JOB_ONGOING, JOB_QUEUED, NEW...).
            array_multisort( array_column( $queue, 'jqstat' ), $queue ); // @codingStandardsIgnoreLine

            // Iterates over the entire queue.
            foreach ( $queue as $path => $jprops ) {
                // Prepare flags and target rule.
                $update      = false;
                $deljob      = false;
                $rule_update = false;
                $oldccssfile = false;
                $trule       = explode( '|', $jprops['rtarget'] );

                // Log job count.
                $this->criticalcss->log( 'Processing job ' . $jc . ' of ' . $jt . ' with id <' . $jprops['ljid'] . '> and status <' . $jprops['jqstat'] . '>', 3 );

                // Process NEW jobs.
                if ( 'NEW' == $jprops['jqstat'] ) {

                    // Log the new job.
                    $this->criticalcss->log( 'Found NEW job with local ID <' . $jprops['ljid'] . '>, starting its queue processing', 3 );

                    // Compare job and rule hashes (if any).
                    $hash = $this->ao_ccss_diff_hashes( $jprops['ljid'], $jprops['hash'], $jprops['hashes'], $jprops['rtarget'] );

                    // If job hash is new or different of a previous one.
                    if ( $hash ) {
                        if ( $jr > 2 ) {
                            // we already posted 2 jobs to criticalcss.com, don't post more this run
                            // but we can keep on processing the queue to keep it tidy.
                            $this->criticalcss->log( 'Holding off on generating request for job with local ID <' . $jprops['ljid'] . '>, maximum number of POSTS reached.', 3 );
                            continue;
                        }

                        // Set job hash.
                        $jprops['hash'] = $hash;

                        // Dispatch the job generate request and increment request count.
                        $apireq = $this->ao_ccss_api_generate( $path, $queue_debug, $qdobj['htcode'] );
                        $jr++;

                        // NOTE: All the following conditions maps to the ones in admin_settings_queue.js.php.
                        if ( empty( $apireq ) ) {
                            // ERROR: no response
                            // Update job properties.
                            $jprops['jqstat'] = 'NO_RESPONSE';
                            $jprops['jrstat'] = 'NONE';
                            $jprops['jvstat'] = 'NONE';
                            $jprops['jftime'] = microtime( true );
                            $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> request has no response, status now is <' . $jprops['jqstat'] . '>', 3 );
                        } elseif ( array_key_exists( 'errorCode', $apireq ) && 'INVALID_JWT_TOKEN' == $apireq['errorCode'] ) {
                            // ERROR: key validation
                            // Update job properties.
                            $jprops['jqstat'] = $apireq['errorCode'];
                            $jprops['jrstat'] = $apireq['error'];
                            $jprops['jvstat'] = 'NONE';
                            $jprops['jftime'] = microtime( true );
                            $this->criticalcss->log( 'API key validation error when processing job id <' . $jprops['ljid'] . '>, job status is now <' . $jprops['jqstat'] . '>', 3 );
                        } elseif ( array_key_exists( 'job', $apireq ) && array_key_exists( 'status', $apireq['job'] ) && 'JOB_QUEUED' == $apireq['job']['status'] || 'JOB_ONGOING' == $apireq['job']['status'] ) {
                            // SUCCESS: request has a valid result.
                            // Update job properties.
                            $jprops['jid']    = $apireq['job']['id'];
                            $jprops['jqstat'] = $apireq['job']['status'];
                            $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> generate request successful, remote id <' . $jprops['jid'] . '>, status now is <' . $jprops['jqstat'] . '>', 3 );
                        } elseif ( array_key_exists( 'job', $apireq ) && array_key_exists( 'status', $apireq['job'] ) && 'STATUS_JOB_BAD' == $apireq['job']['status'] ) {
                            // ERROR: concurrent requests
                            // Update job properties.
                            $jprops['jid']    = $apireq['job']['id'];
                            $jprops['jqstat'] = $apireq['job']['status'];
                            if ( $apireq['job']['error'] ) {
                                $jprops['jrstat'] = $apireq['job']['error'];
                            } else {
                                $jprops['jrstat'] = 'Baby did a bad bad thing';
                            }
                            $jprops['jvstat'] = 'NONE';
                            $jprops['jftime'] = microtime( true );
                            $this->criticalcss->log( 'Concurrent requests when processing job id <' . $jprops['ljid'] . '>, job status is now <' . $jprops['jqstat'] . '>', 3 );
                        } else {
                            // UNKNOWN: unhandled generate exception
                            // Update job properties.
                            $jprops['jqstat'] = 'JOB_UNKNOWN';
                            $jprops['jrstat'] = 'NONE';
                            $jprops['jvstat'] = 'NONE';
                            $jprops['jftime'] = microtime( true );
                            $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> generate request has an UNKNOWN condition, status now is <' . $jprops['jqstat'] . '>, check log messages above for more information', 2 );
                            $this->criticalcss->log( 'Job response was: ' . json_encode( $apireq ), 3 );
                        }
                    } else {
                        // SUCCESS: Job hash is equal to a previous one, so it's done
                        // Update job status and finish time.
                        $jprops['jqstat'] = 'JOB_DONE';
                        $jprops['jftime'] = microtime( true );
                        $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> requires no further processing, status now is <' . $jprops['jqstat'] . '>', 3 );
                    }

                    // Set queue update flag.
                    $update = true;

                } elseif ( 'JOB_QUEUED' == $jprops['jqstat'] || 'JOB_ONGOING' == $jprops['jqstat'] ) {
                    // Process QUEUED and ONGOING jobs
                    // Log the pending job.
                    $this->criticalcss->log( 'Found PENDING job with local ID <' . $jprops['ljid'] . '>, continuing its queue processing', 3 );

                    // Dispatch the job result request and increment request count.
                    $apireq = $this->ao_ccss_api_results( $jprops['jid'], $queue_debug, $qdobj['htcode'] );

                    // NOTE: All the following condigitons maps to the ones in admin_settings_queue.js.php
                    // Replace API response values if queue debugging is enabled and some value is set.
                    if ( $queue_debug ) {
                        if ( $qdobj['status'] ) {
                            $apireq['status'] = $qdobj['status'];
                        }
                        if ( $qdobj['resultStatus'] ) {
                            $apireq['resultStatus'] = $qdobj['resultStatus'];
                        }
                        if ( $qdobj['validationStatus'] ) {
                            $apireq['validationStatus'] = $qdobj['validationStatus'];
                        }
                    }

                    if ( empty( $apireq ) || ! is_array( $apireq ) ) {
                        // ERROR: no response
                        // Update job properties.
                        $jprops['jqstat'] = 'NO_RESPONSE';
                        $jprops['jrstat'] = 'NONE';
                        $jprops['jvstat'] = 'NONE';
                        $jprops['jftime'] = microtime( true );
                        $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> request has no response, status now is <' . $jprops['jqstat'] . '>', 3 );
                    } elseif ( array_key_exists( 'status', $apireq ) && ( 'JOB_QUEUED' == $apireq['status'] || 'JOB_ONGOING' == $apireq['status'] ) ) {
                        // SUCCESS: request has a valid result
                        // Process a PENDING job
                        // Update job properties.
                        $jprops['jqstat'] = $apireq['status'];
                        $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . '> unchanged', 3 );
                    } elseif ( array_key_exists( 'status', $apireq ) && 'JOB_DONE' == $apireq['status'] ) {
                        // Process a DONE job
                        // New resultStatus from ccss.com "HTML_404", consider as "GOOD" for now.
                        if ( 'HTML_404' == $apireq['resultStatus'] ) {
                            $apireq['resultStatus'] = 'GOOD';
                        }

                        if ( 'GOOD' == $apireq['resultStatus'] && ( 'GOOD' == $apireq['validationStatus'] || 'WARN' == $apireq['validationStatus'] ) ) {
                            // SUCCESS: GOOD job with GOOD or WARN validation
                            // Update job properties.
                            $jprops['file']   = $this->ao_ccss_save_file( $apireq['css'], $trule, false );
                            $jprops['jqstat'] = $apireq['status'];
                            $jprops['jrstat'] = $apireq['resultStatus'];
                            $jprops['jvstat'] = $apireq['validationStatus'];
                            $jprops['jftime'] = microtime( true );
                            $rule_update      = true;
                            do_action( 'autoptimize_action_ccss_cron_rule_saved', $jprops['rtarget'], $jprops['file'] );
                            $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . '>, file saved <' . $jprops['file'] . '>', 3 );
                        } elseif ( 'GOOD' == $apireq['resultStatus'] && ( 'BAD' == $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' == $apireq['validationStatus'] ) ) {
                            // SUCCESS: GOOD job with BAD or SCREENSHOT_WARN_BLANK validation
                            // Update job properties.
                            $jprops['jqstat'] = $apireq['status'];
                            $jprops['jrstat'] = $apireq['resultStatus'];
                            $jprops['jvstat'] = $apireq['validationStatus'];
                            $jprops['jftime'] = microtime( true );
                            if ( apply_filters( 'autoptimize_filter_ccss_save_review_rules', true ) ) {
                                $jprops['file']   = $this->ao_ccss_save_file( $apireq['css'], $trule, true );
                                $rule_update      = true;
                                do_action( 'autoptimize_action_ccss_cron_rule_saved', $jprops['rtarget'], $jprops['file'] );
                                $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . ', file saved <' . $jprops['file'] . '> but requires REVIEW', 3 );
                            } else {
                                $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful, remote id <' . $jprops['jid'] . '>, status <' . $jprops['jqstat'] . ', file not saved because it required REVIEW.', 3 );
                            }
                        } elseif ( 'GOOD' != $apireq['resultStatus'] && ( 'GOOD' != $apireq['validationStatus'] || 'WARN' != $apireq['validationStatus'] || 'BAD' != $apireq['validationStatus'] || 'SCREENSHOT_WARN_BLANK' != $apireq['validationStatus'] ) ) {
                            // ERROR: no GOOD, WARN or BAD results
                            // Update job properties.
                            $jprops['jqstat'] = $apireq['status'];
                            $jprops['jrstat'] = $apireq['resultStatus'];
                            $jprops['jvstat'] = $apireq['validationStatus'];
                            $jprops['jftime'] = microtime( true );
                            $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful but job FAILED, status now is <' . $jprops['jqstat'] . '>', 3 );
                            $apireq['css'] = '/* critical css removed for DEBUG logging purposes */';
                            $this->criticalcss->log( 'Job response was: ' . json_encode( $apireq ), 3 );
                        } else {
                            // UNKNOWN: unhandled JOB_DONE exception
                            // Update job properties.
                            $jprops['jqstat'] = 'JOB_UNKNOWN';
                            $jprops['jrstat'] = $apireq['resultStatus'];
                            $jprops['jvstat'] = $apireq['validationStatus'];
                            $jprops['jftime'] = microtime( true );
                            $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful but job is UNKNOWN, status now is <' . $jprops['jqstat'] . '>', 2 );
                            $apireq['css'] = '/* critical css removed for DEBUG logging purposes */';
                            $this->criticalcss->log( 'Job response was: ' . json_encode( $apireq ), 3 );
                        }
                    } elseif ( array_key_exists( 'job', $apireq ) && is_array( $apireq['job'] ) && array_key_exists( 'status', $apireq['job'] ) && ( 'JOB_FAILED' == $apireq['job']['status'] || 'STATUS_JOB_BAD' == $apireq['job']['status'] ) ) {
                        // ERROR: failed job
                        // Update job properties.
                        $jprops['jqstat'] = $apireq['job']['status'];
                        if ( $apireq['job']['error'] ) {
                            $jprops['jrstat'] = $apireq['job']['error'];
                        } else {
                            $jprops['jrstat'] = 'Baby did a bad bad thing';
                        }
                        $jprops['jvstat'] = 'NONE';
                        $jprops['jftime'] = microtime( true );
                        $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful but job FAILED, status now is <' . $jprops['jqstat'] . '>', 3 );
                    } elseif ( array_key_exists( 'error', $apireq ) && 'This css no longer exists. Please re-generate it.' == $apireq['error'] ) {
                        // ERROR: CSS doesn't exist
                        // Update job properties.
                        $jprops['jqstat'] = 'NO_CSS';
                        $jprops['jrstat'] = $apireq['error'];
                        $jprops['jvstat'] = 'NONE';
                        $jprops['jftime'] = microtime( true );
                        $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request successful but job FAILED, status now is <' . $jprops['jqstat'] . '>', 3 );
                    } else {
                        // UNKNOWN: unhandled results exception
                        // Update job properties.
                        $jprops['jqstat'] = 'JOB_UNKNOWN';
                        $jprops['jrstat'] = 'NONE';
                        $jprops['jvstat'] = 'NONE';
                        $jprops['jftime'] = microtime( true );
                        $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> result request has an UNKNOWN condition, status now is <' . $jprops['jqstat'] . '>, check log messages above for more information', 2 );
                    }

                    // Set queue update flag.
                    $update = true;
                }

                // Mark DONE jobs for removal.
                if ( 'JOB_DONE' == $jprops['jqstat'] ) {
                    $update = true;
                    $deljob = true;
                }

                // Persist updated queue object.
                if ( $update ) {
                    if ( ! $deljob ) {
                        // Update properties of a NEW or PENDING job...
                        $queue[ $path ] = $jprops;
                    } else {
                        // ...or remove the DONE job.
                        unset( $queue[ $path ] );
                        $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> is DONE and was removed from the queue', 3 );
                    }

                    // Update queue object.
                    $queue_raw = json_encode( $queue );
                    update_option( 'autoptimize_ccss_queue', $queue_raw, false );
                    $this->criticalcss->log( 'Queue updated by job id <' . $jprops['ljid'] . '>', 3 );

                    // Update target rule.
                    if ( $rule_update ) {
                        $this->ao_ccss_rule_update( $jprops['ljid'], $jprops['rtarget'], $jprops['file'], $jprops['hash'] );
                        $this->criticalcss->log( 'Job id <' . $jprops['ljid'] . '> updated the target rule <' . $jprops['rtarget'] . '>', 3 );
                    }
                } else {
                    // Or log no queue action.
                    $this->criticalcss->log( 'Nothing to do on this job', 3 );
                }

                // Break the loop if request time limit is (almost exceeded).
                if ( time() > $mt ) {
                    $this->criticalcss->log( 'The time limit of ' . $rtimelimit . ' seconds was exceeded, queue control must finish now', 3 );
                    break;
                }

                // Increment job counter.
                $jc++;
            }

            // Remove the lock file and log the queue end.
            if ( file_exists( AO_CCSS_LOCK ) ) {
                unlink( AO_CCSS_LOCK );
                $this->criticalcss->log( 'Queue control unlocked', 3 );
            }
            $this->criticalcss->log( 'Queue control finished', 3 );

            // Log that queue is locked.
        } else {
            $this->criticalcss->log( 'Queue is already running, skipping the attempt to run it again', 3 );
        }
    }

    public function ao_ccss_diff_hashes( $ljid, $hash, $hashes, $rule ) {
        // Compare job hashes
        // STEP 1: update job hashes.
        if ( 1 == count( $hashes ) ) {
            // Job with a single hash
            // Set job hash.
            $hash = $hashes[0];
            $this->criticalcss->log( 'Job id <' . $ljid . '> updated with SINGLE hash <' . $hash . '>', 3 );
        } else {
            // Job with multiple hashes
            // Loop through hashes to concatenate them.
            $nhash = '';
            foreach ( $hashes as $shash ) {
                $nhash .= $shash;
            }

            // Set job hash.
            $hash = md5( $nhash );
            $this->criticalcss->log( 'Job id <' . $ljid . '> updated with a COMPOSITE hash <' . $hash . '>', 3 );
        }

        // STEP 2: compare job to existing jobs to prevent double submission for same type+hash.
        $queue = $this->criticalcss->get_option( 'queue' );

        foreach ( $queue as $queue_item ) {
            $this->criticalcss->log( 'Comparing <' . $rule . $hash . '> with <' . $queue_item['rtarget'] . $queue_item['hash'] . '>', 3 );
            if ( $queue_item['hash'] == $hash && $queue_item['rtarget'] == $rule && in_array( $queue_item['jqstat'], array( 'JOB_QUEUED', 'JOB_ONGOING', 'JOB_DONE' ) ) ) {
                $this->criticalcss->log( 'Job id <' . $ljid . '> matches the already pending job <' . $queue_item['ljid'] . '>', 3 );
                return false;
            }
        }

        // STEP 3: compare job and existing rule (if any) hashes
        // Attach required arrays.
        $rules = $this->criticalcss->get_option( 'rules' );

        // Prepare rule variables.
        $trule = explode( '|', $rule );
        if ( is_array( $trule ) && ! empty( $trule ) && array_key_exists( $trule[1], $rules[ $trule[0] ] ) ) {
            $srule = $rules[ $trule[0] ][ $trule[1] ];
        } else {
            $srule = '';
        }

        // If hash is empty, set it to now for a "forced job".
        if ( empty( $hash ) ) {
            $hash = 'new';
            $this->criticalcss->log( 'Job id <' . $ljid . '> had no hash, assuming forced job so setting hash to new', 3 );
        }

        // Check if a MANUAL rule exist and return false.
        if ( ! empty( $srule ) && ( 0 == $srule['hash'] && 0 != $srule['file'] ) ) {
            $this->criticalcss->log( 'Job id <' . $ljid . '> matches the MANUAL rule <' . $trule[0] . '|' . $trule[1] . '>', 3 );
            return false;
        } elseif ( ! empty( $srule ) ) {
            // Check if an AUTO rule exist.
            if ( $hash === $srule['hash'] && is_file( AO_CCSS_DIR . $srule['file'] ) && 0 != filesize( AO_CCSS_DIR . $srule['file'] ) ) {
                // Check if job hash matches rule, if the CCSS file exists said file is not empty and return FALSE is so.
                $this->criticalcss->log( 'Job id <' . $ljid . '> with hash <' . $hash . '> MATCH the one in rule <' . $trule[0] . '|' . $trule[1] . '>', 3 );
                return false;
            } else {
                // Or return the new hash if they differ.
                $this->criticalcss->log( 'Job id <' . $ljid . '> with hash <' . $hash . '> DOES NOT MATCH the one in rule <' . $trule[0] . '|' . $trule[1] . '> or rule\'s CCSS file was invalid.', 3 );
                return $hash;
            }
        } else {
            // Return the hash for a job that has no rule yet.
            $this->criticalcss->log( 'Job id <' . $ljid . '> with hash <' . $hash . '> has no rule yet', 3 );
            return $hash;
        }
    }

    public function ao_ccss_api_generate( $path, $debug, $dcode ) {
        // POST jobs to criticalcss.com and return responses
        // Get key and key status.
        $key = $this->criticalcss->get_option( 'key' );
        $key_status = $this->criticalcss->get_option( 'keyst' );
        $noptimize = $this->criticalcss->get_option( 'noptimize' );

        // Prepare full URL to request.
        $site_host = get_site_url();
        $site_path = parse_url( $site_host, PHP_URL_PATH );

        if ( ! empty( $site_path ) ) {
            $site_host = str_replace( $site_path, '', $site_host );
        }

        // Logic to bind to one domain to avoid site clones of sites would
        // automatically begin spawning requests to criticalcss.com which has
        // a per domain cost.
        $domain = $this->criticalcss->get_option( 'domain' );
        if ( empty( $domain ) ) {
            // first request being done, update option to allow future requests are only allowed if from same domain.
            update_option( 'autoptimize_ccss_domain', str_rot13( $site_host ) );
        } elseif ( trim( $domain, '\'"' ) !== 'none' && parse_url( $site_host, PHP_URL_HOST ) !== parse_url( $domain, PHP_URL_HOST ) && apply_filters( 'autoptimize_filter_ccss_bind_domain', true ) ) {
            // not the same domain, log as error and return without posting to criticalcss.com.
            $this->criticalcss->log( 'Request for domain ' . $site_host . ' does not match bound domain ' . $domain . ' so not proceeding.', 2 );
            return false;
        }

        $src_url = $site_host . $path;

        // Avoid AO optimizations if required by config or avoid lazyload if lazyload is active in AO.
        if ( ! empty( $noptimize ) ) {
            $src_url .= '?ao_noptirocket=1';
        } elseif ( ( class_exists( 'autoptimizeImages', false ) && autoptimizeImages::should_lazyload_wrapper() ) || apply_filters( 'autoptimize_filter_ccss_enforce_nolazy', false ) ) {
            $src_url .= '?ao_nolazy=1';
        }

        $src_url = apply_filters( 'autoptimize_filter_ccss_cron_srcurl', $src_url );

        if ( true !== autoptimizeUtils::is_local_server( parse_url( $src_url, PHP_URL_HOST ) ) ) {
            // Initialize request body.
            $body           = array();
            $body['url']    = $src_url;
            $body['aff']    = 1;
            $body['aocssv'] = AO_CCSS_VER;

            // Prepare and add viewport size to the body if available.
            $viewport = $this->criticalcss->viewport();
            if ( ! empty( $viewport['w'] ) && ! empty( $viewport['h'] ) ) {
                $body['width']  = $viewport['w'];
                $body['height'] = $viewport['h'];
            }

            // Prepare and add forceInclude to the body if available.
            $finclude = $this->criticalcss->get_option( 'finclude' );
            $finclude = $this->ao_ccss_finclude( $finclude );
            if ( ! empty( $finclude ) ) {
                $body['forceInclude'] = $finclude;
            }

            // Add filter to allow the body array to be altered (e.g. to add customPageHeaders).
            $body = apply_filters( 'autoptimize_ccss_cron_api_generate_body', $body );

            // Body must be json and log it.
            $body = json_encode( $body, JSON_UNESCAPED_SLASHES );
            $this->criticalcss->log( 'criticalcss.com: POST generate request body is ' . $body, 3 );

            // Prepare the request.
            $url  = esc_url_raw( AO_CCSS_API . 'generate?aover=' . AO_CCSS_VER );
            $args = array(
                'headers' => apply_filters(
                    'autoptimize_ccss_cron_api_generate_headers',
                    array(
                        'User-Agent'    => 'Autoptimize v' . AO_CCSS_VER,
                        'Content-type'  => 'application/json; charset=utf-8',
                        'Authorization' => 'JWT ' . $key,
                        'Connection'    => 'close',
                    )
                ),
                'body'    => $body,
            );

            // Dispatch the request and store its response code.
            $req  = wp_safe_remote_post( $url, $args );
            $code = wp_remote_retrieve_response_code( $req );
            $body = json_decode( wp_remote_retrieve_body( $req ), true );

            if ( $debug && $dcode ) {
                // If queue debug is active, change response code.
                $code = $dcode;
            }

            if ( 200 == $code ) {
                // Response code is OK.
                // Workaround criticalcss.com non-RESTful reponses.
                if ( 'JOB_QUEUED' == $body['job']['status'] || 'JOB_ONGOING' == $body['job']['status'] || 'STATUS_JOB_BAD' == $body['job']['status'] ) {
                    // Log successful and return encoded request body.
                    $this->criticalcss->log( 'criticalcss.com: POST generate request for path <' . $src_url . '> replied successfully', 3 );

                    // This code also means the key is valid, so cache key status for 24h if not already cached.
                    if ( ( ! $key_status || 2 != $key_status ) && $key ) {
                        update_option( 'autoptimize_ccss_keyst', 2 );
                        $this->criticalcss->log( 'criticalcss.com: API key is valid, updating key status', 3 );
                    }

                    // Return the request body.
                    return $body;
                } else {
                    // Log successful requests with invalid reponses.
                    $this->criticalcss->log( 'criticalcss.com: POST generate request for path <' . $src_url . '> replied with code <' . $code . '> and an UNKNOWN error condition, body follows...', 2 );
                    $this->criticalcss->log( print_r( $body, true ), 2 );
                    return $body;
                }
            } else {
                // Response code is anything else.
                // Log failed request with a valid response code and return body.
                if ( $code ) {
                    $this->criticalcss->log( 'criticalcss.com: POST generate request for path <' . $src_url . '> replied with error code <' . $code . '>, body follows...', 2 );
                    $this->criticalcss->log( print_r( $body, true ), 2 );

                    if ( 401 == $code ) {
                        // If request is unauthorized, also clear key status.
                        update_option( 'autoptimize_ccss_keyst', 1 );
                        $this->criticalcss->log( 'criticalcss.com: API key is invalid, updating key status', 3 );
                    }

                    // Return the request body.
                    return $body;
                } else {
                    // Log failed request with no response and return false.
                    $this->criticalcss->log( 'criticalcss.com: POST generate request for path <' . $src_url . '> has no response, this could be a service timeout', 2 );
                    if ( is_wp_error( $req ) ) {
                        $this->criticalcss->log( $req->get_error_message(), 2 );
                    }

                    return false;
                }
            }
        } else {
            // localhost/ private network server, no CCSS possible.
            $this->criticalcss->log( 'ccss cron: job not created at ccss.com as for local server', 3 );
            return false;
        }
    }

    public function ao_ccss_api_results( $jobid, $debug, $dcode ) {
        // GET jobs from criticalcss.com and return responses
        // Get key.
        $key = $this->criticalcss->get_option( 'key' );

        // Prepare the request.
        $url  = AO_CCSS_API . 'results?resultId=' . $jobid;
        $args = array(
            'headers' => apply_filters(
                'autoptimize_ccss_cron_api_generate_headers',
                array(
                    'User-Agent'    => 'Autoptimize CriticalCSS Power-Up v' . AO_CCSS_VER,
                    'Authorization' => 'JWT ' . $key,
                    'Connection'    => 'close',
                )
            ),
        );

        // Dispatch the request and store its response code.
        $req  = wp_safe_remote_get( $url, $args );
        $code = wp_remote_retrieve_response_code( $req );
        $body = json_decode( wp_remote_retrieve_body( $req ), true );

        if ( $debug && $dcode ) {
            // If queue debug is active, change response code.
            $code = $dcode;
        }

        if ( 200 == $code ) {
            // Response code is OK.
            if ( is_array( $body ) && ( array_key_exists( 'status', $body ) || array_key_exists( 'job', $body ) ) && ( 'JOB_QUEUED' == $body['status'] || 'JOB_ONGOING' == $body['status'] || 'JOB_DONE' == $body['status'] || 'JOB_FAILED' == $body['status'] || 'JOB_UNKNOWN' == $body['status'] || 'STATUS_JOB_BAD' == $body['job']['status'] ) ) {
                // Workaround criticalcss.com non-RESTful reponses
                // Log successful and return encoded request body.
                $this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied successfully', 3 );
                return $body;
            } elseif ( is_array( $body ) && ( array_key_exists( 'error', $body ) && 'This css no longer exists. Please re-generate it.' == $body['error'] ) ) {
                // Handle no CSS reply
                // Log no CSS error and return encoded request body.
                $this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied successfully but the CSS for it does not exist anymore', 3 );
                return $body;
            } else {
                // Log failed request and return false.
                $this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied with code <' . $code . '> and an UNKNOWN error condition, body follows...', 2 );
                $this->criticalcss->log( print_r( $body, true ), 2 );
                return false;
            }
        } else {
            // Response code is anything else
            // Log failed request with a valid response code and return body.
            if ( $code ) {
                $this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> replied with error code <' . $code . '>, body follows...', 2 );
                $this->criticalcss->log( print_r( $body, true ), 2 );
                if ( 401 == $code ) {
                    // If request is unauthorized, also clear key status.
                    update_option( 'autoptimize_ccss_keyst', 1 );
                    $this->criticalcss->log( 'criticalcss.com: API key is invalid, updating key status', 3 );
                }

                // Return the request body.
                return $body;
            } else {
                // Log failed request with no response and return false.
                $this->criticalcss->log( 'criticalcss.com: GET results request for remote job id <' . $jobid . '> has no response, this could be a service timeout', 2 );
                return false;
            }
        }
    }

    public function ao_ccss_save_file( $ccss, $target, $review ) {
        // Save critical CSS into the filesystem and return its filename
        // Prepare review mark.
        if ( $review ) {
            $rmark = '_R';
        } else {
            $rmark = '';
        }

        // Prepare target rule, filename and content.
        $filename = false;
        $content  = $ccss;

        if ( $this->criticalcss->check_contents( $content ) ) {
            // Sanitize content, set filename and try to save file.
            $file     = AO_CCSS_DIR . 'ccss_' . md5( $ccss . $target[1] ) . $rmark . '.css';
            $status   = file_put_contents( $file, $content, LOCK_EX );
            $filename = pathinfo( $file, PATHINFO_BASENAME );
            $this->criticalcss->log( 'Critical CSS file for the rule <' . $target[0] . '|' . $target[1] . '> was saved as <' . $filename . '>, size in bytes is <' . $status . '>', 3 );

            if ( ! $status ) {
                // If file has not been saved, reset filename.
                $this->criticalcss->log( 'Critical CSS file <' . $filename . '> could not be not saved', 2 );
                $filename = false;
                return $filename;
            }
        } else {
            $this->criticalcss->log( 'Critical CSS received did not pass content check', 2 );
            return $filename;
        }

        // Remove old critical CSS if a previous one existed in the rule and if that file exists in filesystem
        // Attach required arrays.
        $rules = $this->criticalcss->get_option( 'rules' );

        // Only proceed if the rule already existed.
        if ( array_key_exists( $target[1], $rules[ $target[0] ] ) ) {
            $srule   = $rules[ $target[0] ][ $target[1] ];
            $oldfile = $srule['file'];

            if ( $oldfile && $oldfile !== $filename ) {
                $delfile = AO_CCSS_DIR . $oldfile;
                if ( file_exists( $delfile ) ) {
                    $unlinkst = unlink( $delfile );
                    if ( $unlinkst ) {
                        $this->criticalcss->log( 'A previous critical CSS file <' . $oldfile . '> was removed for the rule <' . $target[0] . '|' . $target[1] . '>', 3 );
                    }
                }
            }
        }

        // Return filename or false.
        return $filename;
    }

    public function ao_ccss_rule_update( $ljid, $srule, $file, $hash ) {
        // Update or create a rule
        // Attach required arrays.
        $rules = $this->criticalcss->get_option( 'rules' );

        // Prepare rule variables.
        $trule  = explode( '|', $srule );
        if ( array_key_exists( $trule[1], $rules[ $trule[0] ] ) ) {
            $rule = $rules[ $trule[0] ][ $trule[1] ];
        } else {
            $rule = array();
        }
        $action = false;
        $rtype  = '';

        if ( is_array( $rule ) && array_key_exists( 'hash', $rule ) && 0 === $rule['hash'] && array_key_exists( 'file', $rule ) && 0 !== $rule['file'] ) {
            // manual rule, don't ever overwrite.
            $action = 'NOT UPDATED';
            $rtype  = 'MANUAL';
        } elseif ( is_array( $rule ) && array_key_exists( 'hash', $rule ) && 0 === $rule['hash'] && array_key_exists( 'file', $rule ) && 0 === $rule['file'] ) {
            // If this is an user created AUTO rule with no hash and file yet, update its hash and filename
            // Set rule hash, file and action flag.
            $rule['hash'] = $hash;
            $rule['file'] = $file;
            $action       = 'UPDATED';
            $rtype        = 'AUTO';
        } elseif ( is_array( $rule ) && array_key_exists( 'hash', $rule ) && 0 !== $rule['hash'] && ctype_alnum( $rule['hash'] ) ) {
            // If this is an genuine AUTO rule, update its hash and filename
            // Set rule hash, file and action flag.
            $rule['hash'] = $hash;
            $rule['file'] = $file;
            $action       = 'UPDATED';
            $rtype        = 'AUTO';
        } else {
            // If rule doesn't exist, create an AUTO rule
            // AUTO rules were only for types, but will now also work for paths.
            if ( ( 'types' == $trule[0] || 'paths' == $trule[0] ) && ! empty( $trule[1] ) ) {
                // Set rule hash and file and action flag.
                $rule['hash'] = $hash;
                $rule['file'] = $file;
                $action       = 'CREATED';
                $rtype        = 'AUTO';
            } else {
                // Log that no rule was created.
                $this->criticalcss->log( 'Exception, no AUTO rule created', 3 );
            }
        }

        if ( $action ) {
            // If a rule creation/update is required, persist updated rules object.
            $rules[ $trule[0] ][ $trule[1] ] = $rule;
            $rules_raw = json_encode( $rules );
            update_option( 'autoptimize_ccss_rules', $rules_raw );
            $this->criticalcss->flush_options();
            $this->criticalcss->log( 'Target rule <' . $srule . '> of type <' . $rtype . '> was ' . $action . ' for job id <' . $ljid . '>', 3 );
            
            // and trigger action for whoever needs to be aware.
            do_action( 'autoptimize_action_ccss_cron_rule_updated', $srule, $file, '' );
        } else {
            $this->criticalcss->log( 'No rule action required', 3 );
        }
    }

    function ao_ccss_finclude( $finclude_raw ) {
        // Prepare forceInclude object.
        if ( ! empty( $finclude_raw ) ) {
            // If there are any content
            // Convert raw string into arra and initialize the returning object.
            $fincludes = explode( ',', $finclude_raw );
            $finclude  = array();

            // Interacts over every rule.
            $i = 0;
            foreach ( $fincludes as $include ) {
                // Trim leading and trailing whitespaces.
                $include = trim( $include );

                if ( substr( $include, 0, 2 ) === '//' ) {
                    // Regex rule
                    // Format value as required.
                    $include = str_replace( '//', '/', $include );
                    $include = $include . '/i';

                    // Store regex object.
                    $finclude[ $i ]['type']  = 'RegExp';
                    $finclude[ $i ]['value'] = $include;
                } else {
                    // Simple value rule.
                    $finclude[ $i ]['value'] = $include;
                }

                $i++;
            }

            // Return forceInclude object.
            return $finclude;
        } else {
            // Or just return false if empty.
            return false;
        }
    }

    public function ao_ccss_cleaning() {
        // Perform plugin maintenance
        // Truncate log file >= 1MB .
        if ( file_exists( AO_CCSS_LOG ) ) {
            if ( filesize( AO_CCSS_LOG ) >= 1048576 ) {
                $logfile = fopen( AO_CCSS_LOG, 'w' );
                fclose( $logfile );
            }
        }

        // Remove lock file.
        if ( file_exists( AO_CCSS_LOCK ) ) {
            unlink( AO_CCSS_LOCK );
        }

        // Make sure queue processing is scheduled, recreate if not.
        if ( ! wp_next_scheduled( 'ao_ccss_queue' ) ) {
            wp_schedule_event( time(), apply_filters( 'ao_ccss_queue_schedule', 'ao_ccss' ), 'ao_ccss_queue' );
        }

        // Queue cleaning.
        $queue = $this->criticalcss->get_option( 'queue' );

        $queue_purge_threshold = 100;
        $queue_purge_age       = 24 * 60 * 60;
        $queue_length          = count( $queue );
        $timestamp_yesterday   = microtime( true ) - $queue_purge_age;
        $remove_old_new        = false;
        $queue_altered         = false;

        if ( $queue_length > $queue_purge_threshold ) {
            $remove_old_new = true;
        }

        foreach ( $queue as $path => $job ) {
            if ( ( $remove_old_new && 'NEW' == $job['jqstat'] && $job['jctime'] < $timestamp_yesterday ) || in_array( $job['jqstat'], array( 'JOB_FAILED', 'STATUS_JOB_BAD', 'NO_CSS', 'NO_RESPONSE' ) ) ) {
                unset( $queue[ $path ] );
                $queue_altered = true;
            }
        }

        // save queue to options!
        if ( $queue_altered ) {
            $queue_raw = json_encode( $queue );
            update_option( 'autoptimize_ccss_queue', $queue_raw, false );
            $this->criticalcss->log( 'Queue cleaning done.', 3 );
        }

        // re-check key if invalid.
        $keyst = $this->criticalcss->get_option( 'keyst' );
        if ( 1 == $keyst ) {
            $this->ao_ccss_api_generate( '', '', '' );
        }
    }
}