Plugin Customizer: Ad WordPress ^^BOOKMOBI0HWb#((%IMOBIY;;6 @EXTHdPer Soderlindi!general ,proof of conceptg

tl;dr -  The commented demo plugin is available at GitHub.Introduction I've wanted to add a customizer to my Read Offline plugin for a long time, letting the user easily change the PDF and ePub design. As I like …

j'Wed, 28 Sep 2016 20:16:29 +0000p#http://soderlind.no/?p=4908ePer Søderlindf5Copyright Per Soderlind - http://soderlind.noPlugin Customizer: Ad WordPress customizer to a plugin

Plugin Customizer: Ad WordPress customizer to a plugin

tl;dr –  The commented demo plugin is available at GitHub.

Introduction

I’ve wanted to add a customizer to my Read Offline plugin for a long time, letting the user easily change the PDF and ePub design. As I like to write a demo plugin before adding new functionality, here’s my take on adding WordPress customizer to a plugin.

Understanding how the customizer works wasn’t easy.

Understanding how the customizer works wasn’t easy. I’ve read the documentation and read a lot of source code. After viewing the loopconf presentation Patrick Rauland held last year, I asked him and got an early beta version of the WooCommerce Email Customizer plugin. I’ve also followed the work Weston Ruter and XWP have done and have skimmed through their customizer plugins, I’ve also viewed tickets and followed the discussions on Slack.

The thing I found hardest was understanding how to remove the other sections from the customizer, so I asked on Twitter

Any idea how I can reset the #WordPress Customizer. i.e. remove existing panels and controls before I add mine ?

— Per Søderlind (@soderlind) September 11, 2016

Fortunately, Weston came to the rescue :)

@soderlind @bjornjohansen @tommcfarlin I just did a writeup for what I think may be the most concise way to do it: https://t.co/2pXoYtEjrZ

— Weston Ruter ⚡ (@westonruter) September 11, 2016

The important parts

Timing is everything.

Timing is everything, and so is understanding when parts of the code is used. WordPress customizer relies on ajax for communication between the controls and the preview, and customizer uses ajax for saving settings.

“Blank Slate” loads at a priority of 1, so the Plugin Customizer must load after it, but if it’s loaded at the default priority of 10, it will not be available. As shown below, I add the customizer_register  at priority 9.

So, everything looked fine, but I couldn’t save the settings (!!), and the only error message I got was a 500 Server error. I understood that when saving & publishing the customizer settings, admin-ajax.php expects to find the settings, and if I removed the bailout test everything worked fine.

The problem was that I couldn’t “see” the solution. When I removed the bailout test, Plugin Customizer sections would pop up in the default Appearance -> Customize, and if I added the bailout test, I couldn’t save the settings.

Now, after the problem is solved, it’s a simple fix (isn’t it always). Register the customizer settings before the bailout test and register the customizer sections and controls after the bailout test.

Adding a preview

Weston describes how to add a preview in Navigating to a URL in the Customizer Preview when a Section is Expanded. I’ve extended his code to add a template per section.

Loading the template, I tested the hooks template_redirect and template_include, but I ended up creating a permalink. It fitted well to script above.

Like to learn how to create a custom permalink? I’ve written another demo plugin that shows you how to do it.

Code

The Plugin Customizer demo plugin is available at GitHub. The code is documented. If you find logical flaws, typos etc, please contribute.

Credits

I couldn’t, at least not in the near future, have developed this plugin without the help from Patrick Rauland and Weston Ruter.

Btw, any flaws in the plugin are mine.

 

Contents

Introduction
The important parts
Adding a preview
Code
Credits
JFIF``>CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222ml" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?Т((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((ۏڤW,G* hԨ)ϕU(2=zp|U0F9J0k|mR,)#[1pcz@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@U=[@'h~:6/IQEQEQEQ:=/R힬}kԾ)HYLP9':~f=.Y|IIz$)FibHg?iLKj*O[QscpxʞЎhQ@-%p5R7Le^3,`=YYRqLKd8Ic |quyϾi%=݋I,/"MZNsF@TE|4ąݛL6ixxoOd"ݏh8`-ψ^ 뚞){eg >8޴~b\P" ׮f`؝X7$xQ=’ O]uW%_xz+&381sX֯mK'ڀ="((((((((((|{տ}޾v΀;hV]]$)fT+ǵhN8RMnx/D7yX@;s3\ ݥƟw%M 2Pk_vq}8x? _%VOrVdc˧N}kžFq"ȇ{MQE5:r?8f^%ٴȕ{y?WRXyl*\YxJ$XK_IEPEe sHUc\r? RE#Ye zR?.n l\iHGscTh25+CpzC0[:((jzk넅;ՏMpIM~w?4OV5{){[2+2[ J4yK;CISa@)TƾR(QEQE-QLG O6͘s@ί^kww{.<*ºO|>աK 28a*McVk ki*Gqzװ/oÐ Wv$͓?JKBn?G]M$ڿڬז a{V^7${}t=k}̑!%8[ҵ;}cMٳz_ soM߻]GQ3 Zd򭽼?ݍ W2Ms),]'5 ?ZW.<в[ggJX$2#ր=ÞtأIAM>[UӿudO4ᗖwZU\#Cs r潋:\۷#G pKUs쑓j|)H"@T]J #M%V='r▤l. ߲&#X.AܳEtËFYF+;?jFMO]k46js?bX5ޥ_Z]Euj][9>uUOV5{R+:/IQEQE:_WWmiZONkǧܸ1+zB6p+~xw O i`ϬgPkV (|H>3J1W_ްd!<xևxl59ПqL5%H#"1PMOX|˟+3y8u/@5GP2? Z`_6>?߯D9O,ˋ$;y.gYyg+G݃} ^ _5_B4?N?b;wzzV*At+N1 6XyowۻɯZ-{xwr_hоȦum"wwej~rWUK@VroI+#*ʵ#*jʀ<&)RT8d`}li/^tI'vo\Jp[xeUR=A5$Ck AIH0 oGUQdĞ*־iset/1)z%|c{>{ &ܧ~oԴkI{WkgB1K a?Jҙ|h ƑGOx{M o󮒼Cƺ^)% F=\ƀ(>$ՌqnSIُz:(yqȏȚḮ >ycW@]=T".~8ak|G ݬs$2gʙFc;jj|qb CWïK{n^XS|$u8Ƿһo ]4هT?FOk(((_;^uo_DM[a!==ğ ger)^ ?MgB5@84nU ׳xIB[MKwO$SxG(Οf5|x{ϴ}^Dԣl:z:S@@Y6kiڷ2 HauA7䦾}8IQ@=IR?|@!?|CA-S5v+{]!?Q@  jO5 jP&#sК(ü! Mc y%Op9p(uԞז25Va%"'&kڌyy!G~@Wxvqi귐3lS4V. sFH?h_KYGr3^-x_2D4pu Ri'_iUsOhӻWD.?{7j񯈱_3$QҀ:_K OsMw|+6A&W?ZzOʧM|_GG?}tP(xyc|ARA#~5/s%@C0A"RJdY2|n=+ԯt+ F~@C77PYۼ3$1 ;^3 |#ǟ}k׫ Is}19TBj6zbRc oֶ>\ WNs˴؏pphǡ6[c>Кeu # |?z\1dԚwu*1,qp>{s>+Fi6(X1 g%r1u~/ڤOQ#KKRmguh-#d2`(TƾR(QEQE|F)[.TTZ>9?B}+{H.4mNc*z0lмEa E@%1==W2*ܽqǷ^:b>JǞ#@PXՏ]xWHQ䊇?zY6`I9$'V-E BEpG ((+[{L7PE3SK<7#?Z(e;H`^ZjPEPd%VV{D>EQEB]HV]*Ig{t%N*6, KcBw( >\\iRyYԑWm-mLUeOekm2]z9]?ZPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPERUgHn`WT@qEVlF9™\.~Pg\#F fZ-k]b.=sҪZxHAmI)8d= Ң^jzr+]CnpW .`[-幞UbA3:J{iztxe?j|9Cwo{XĠ.p@hMs%j4y.P 㓑ڒYu);+'t+@P*jz&] =:kiz$6P#8s}@(6mр~+OO+޾^7o>)м+ZwOJЖ oqpc>c8 J˷&u0Rդ'|2}ֵ(wq#jrAN~wXXHAVIfi/rsD (:IYxG6jv08(jk=RPg[;. E m\PZ+;IfmD3\ WYRR-Old[EP:ޖ%#ډ!ϚU`Ӟ):W7€.Q\%&LYhsaa}G7N9 tUIK [g+1'l :Nμ62}%et7UaY~ |ڌ-fl5-0˅>1=?U);-:>}o H4F3GQ˯ i5+Ul2@4EoK4J2?YxCQj@3W:ߍ=2塎0Ar?Ũv:v϶Aoggwc3*OwEw$@hwJe5 xe뱟Zm{kymk΀'zëZ&Gҵ`Vh%IbnUу}ui67?g-4kf&mo k@TsCk Mq*EVmt{ڍO0% XVdCoSEy_ZX\jڗ,#1eR7*Vu{Qi5X6Ghi`Q4TW wR]3ӈ*0_zV6)]S&HHn264QT6hm|ATL`vζWN*>HOJEWo.b<4'l53SbWN2U}:J+u cY\iKUTaq8-vTQEQEQEQEQEQEQEP2QAA'u~U-gLX.t`0zc=ro^Eniy?=Z/43cq,ƻ >? =̆O8UųhzU-NR6f6 |ۏLv ? Ǩh2"\Ӯ֥#Gż8(NXm'' s]w|/k[hghg>\3wЍc] RN?dk3ev=ַt6zou%K'#%x;i@p021[vveݿʍc݌g/.iMKR՗2&@,ŲN>M"["DQp><Z^=RHeqWt ]R]EI#c'NhN>)E9)3It贠cG"c N͵>}GmRY_uh~M7UԿ:'$rΟV[Db3ǒ kxI~Kỷ)v î1GLj~ݎA[+ AGye{{rWr y91[I:Kx;2x;r:ǵZ:o`bHi&}+@5]9uk[|\JK-s§rZ9=t0n%Ŕ0"/kc#5jz9mmG6cRG$tdo|@դV%G~"K#j,"Oo:;H?XKg,9ӴO2ga,Y·qv~TZ>_6q#6O{9^zO@?]=~un #21J/lߵۼ'$pFRtowѦJ WMz-03N+i>lgXC4{̌zǖJg=T: /h~al+,0%sci6ZEbI\w ^ OO߳}߻v>@?ݗGPx^Y]ҬnFmRrr}cu($ا۾P>Vjlj|9 ھHo F1@ֿ߁4V;G <?>۬:߆ZՔn#, _λ qivڴ|{xЍxgjpˮks_E݈&3 ]}} =<2Z>Kp/At3={g / @BeK8 lONӭW h0mVݧ,|=m6f2^Gm#1;sk~f>ev }ֺmB@Yi(NOCVtKjjk5H95~oIk{%·O:#G5wMtӪjwmRsI=VӮNͬjne䞽2kG ?gXѶ_ sZn#%6<3ZrkpA9`1qдt_jqUpv=NIc!^+H=0ùl $ӵ˛KȋowԊ׃Gu;ſk2m#,IJO_7_h}Gkľ-i+3ş.ez;ƀ9{K;>mYyBri9>zh5i<.?N5Ѝc] RN?m v Hpˈ  dzғ\ .yFp?WiXͦ%7LIʍǧs^> Aml]W𿇿eW7e@O@w??G?k?]>k?n~d>OnsOOyI>Vݻw]@^?u{k̐1\'=]:-YHXݎz{ eYw!|wґ#c?nz&Ͻ@o>#5Y@BEhϰ0 'ߥL4=s[=NNH7S)R3qe_nO O p 'P??SOO=»'K[x#w*4!jZT}ePuyZ "wڬ{xj.;wSO[[[o2h 1Wu\7|Ew{&,0Cj6v0㟭w4QEQE>;}Pw)cIO[{Q巵KEBWzmK/AQPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPSGEޥ }Q@Q@g?lD iesc|NGӼ w>eq6Q[$ЂK<΀><ͽ:.~yc..{? Y ZxfN\K6v:; ?í_gx7A O~zw)QoSi= ~{̍ȅ¯q?\t)k%1s@-"^"ꦕcgXۻj@Q@Q@ O'5zQN~O~-Q@T]Yz %Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ ޥ K( (0|_6j3 zlOeg"f^] ( ( (zOpBFc8rjk\:H˸(U(lty>;|{ |{ h^RKT}((((((((((((((((((((((((((^,pT]XEQEQ\5<=5L"wFoz/)ml`PQ\GKuGR72yi*X%[ʹ V3FͽR|gwrz-yޱ{ݐdd23}weeKHR(&B42r@AEsOury&iY/#'7>ȑaF5uCbK:"q)%I8##=+Gú7ܵ2 c@EPdSMAހS߅0S߅KEPrz^@ EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPcR>((?F>%{YD\q]:'FKD<]9ʗz|MHNKG'ր9o y)]˧$:Y+c3<'3EIL*qaץꊱWV@m5|6<)u 7!e@fxe/3)\`3޶>)qZDScC g?:-636DHwj(e*2HԼ-חar ;5 Ke=F7Њor.!ҬPrboO´'^RXaE <>5=;S7ٕԱ=$c"-J'[%a8K͠i˦Z41by*d}*խKxr$ 3=Q@ O'5zQO~O~-Q@T}Iz %Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ ޥ K( ( (,IA>򠓖 EQEW^Դ+[n<9ح59PO\PKId&;Sd& 3.7sr(MAާ( ` (*>$Gހ((((((((((((((((((((((((((REޥ }Q@Q@u]ZE](w'jƗ8;6午\_n?f1>Ŝ?i6q7qhd G 7TZٰ㻳fAe<2sg O1P8=g]B{/DN}G v:t=souwXR}qxJUv2}*<ߥq :HUifuߴcܒNj,t}CI[!8  {P_WB v^u8*yi :Rضo(ٵdcnӥl^[_si2M 5\_ 8E`n6BS$@Cҹ_KgZ@%IbF?*_Jz('5zOj)(Z(#ԒzJ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (Kz?(QEQEs>:ou:o9_n $ uƗxWKXs{>PqֺJJ#^~[|d7N9O^Fgykr][rmI@o\Z+oT||d85kMηg\KnA=9 bBquڊ(lty>;|{ |{ h^RKT}((((((((((((((((((((((((((^,pT]XEQEQEQEQEQEQEQE>;}PL@EGޤQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEXjhE}f42'tdΒ\Sѓ:J(r}OFO(?>󤢀'tdΒ\Sѓ:J(I'QO~ (*>$Gހ(((((((((((((((((((((((((({Tmhz(EEV( b@F*[b@F*[b@F*[b@}(*>$Eހ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (%G }ANY(ZZhu=:\Q@ E&G#PI(Rdz2=E-Q@ E&G#PI(Rdz2=E-Q@ E&G#P%**BtQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEFLIS00 00 00 0800 4100 0000 00 00 00ff ff ff ff00 0100 0300 00 00 0300 00 00 01ff ff ff ffFCIS00 00 00 1400 00 00 1000 00 00 0100 00 00 0000 00 25 4900 00 00 0000 00 00 2000 00 00 0800 0100 0100 00 00 003918400778