From 11837941709173fc7d4b779d6834fa15426940b3 Mon Sep 17 00:00:00 2001 From: Rumperuu Date: Sat, 7 Aug 2021 16:45:47 +0100 Subject: [PATCH] =?UTF-8?q?refactor:=20finish=20=E2=80=98Referrers=20and?= =?UTF-8?q?=20Tooltips=E2=80=99=20settings=20section?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- settings.ods | Bin 39992 -> 41370 bytes src/admin/layout/class-engine.php | 11 + src/admin/layout/class-init.php | 4 + src/admin/layout/class-settings-page.php | 805 +----------------- src/includes/class-core.php | 5 +- src/includes/class-settings.php | 618 +------------- .../settings/class-settings-group.php | 13 +- .../class-amp-compat-settings-group.php | 73 ++ .../general/class-excerpts-settings-group.php | 75 ++ .../class-general-settings-section.php | 15 + .../class-hard-links-settings-group.php | 166 ++++ .../general/class-love-settings-group.php | 111 +++ .../class-numbering-settings-group.php | 90 ++ ...ass-reference-container-settings-group.php | 19 - .../class-backlink-symbol-settings-group.php | 92 ++ ...eferrers-and-tooltips-settings-section.php | 26 +- ...ass-referrers-in-labels-settings-group.php | 73 ++ .../class-referrers-settings-group.php | 145 ++++ ...lass-tooltip-appearance-settings-group.php | 236 +++++ ...lass-tooltip-dimensions-settings-group.php | 79 ++ .../class-tooltip-position-settings-group.php | 179 ++++ .../class-tooltip-text-settings-group.php | 115 +++ .../class-tooltip-timing-settings-group.php | 125 +++ ...lass-tooltip-truncation-settings-group.php | 105 +++ .../class-tooltips-settings-group.php | 86 ++ src/public/class-general.php | 21 +- src/public/class-parser.php | 264 +++--- 27 files changed, 1965 insertions(+), 1586 deletions(-) create mode 100644 src/includes/settings/general/class-amp-compat-settings-group.php create mode 100644 src/includes/settings/general/class-excerpts-settings-group.php create mode 100644 src/includes/settings/general/class-hard-links-settings-group.php create mode 100644 src/includes/settings/general/class-love-settings-group.php create mode 100644 src/includes/settings/general/class-numbering-settings-group.php create mode 100644 src/includes/settings/referrers-and-tooltips/class-backlink-symbol-settings-group.php create mode 100644 src/includes/settings/referrers-and-tooltips/class-referrers-in-labels-settings-group.php create mode 100644 src/includes/settings/referrers-and-tooltips/class-referrers-settings-group.php create mode 100644 src/includes/settings/referrers-and-tooltips/class-tooltip-appearance-settings-group.php create mode 100644 src/includes/settings/referrers-and-tooltips/class-tooltip-dimensions-settings-group.php create mode 100644 src/includes/settings/referrers-and-tooltips/class-tooltip-position-settings-group.php create mode 100644 src/includes/settings/referrers-and-tooltips/class-tooltip-text-settings-group.php create mode 100644 src/includes/settings/referrers-and-tooltips/class-tooltip-timing-settings-group.php create mode 100644 src/includes/settings/referrers-and-tooltips/class-tooltip-truncation-settings-group.php create mode 100644 src/includes/settings/referrers-and-tooltips/class-tooltips-settings-group.php diff --git a/settings.ods b/settings.ods index 4a98b91c37cfbb3d926d7bc77272072cdc055ed2..64556c3686686762b27672f4b63e0ce1eeb8e133 100644 GIT binary patch delta 39557 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

GA9aG?Nq+83FGni2wosZ_A%uhS zz-<0sHQNgz4~^18iCDJJ63hn!@Tj;LCf0Nd1=p0~Yj z%Le9&!PpHGY)G2mUdk~2w*F1q0V(hRfr%74v=s7CkKFqRjftoOxp|@PqH|RzrdhHH zB%I%SH2772^uZ+yrPq0a6M7R_sz`5WCfz<>mm^R{gNliT0z61iYWeb%x6rIro~)i_ z%rF>dDYT+O`_AlZcedi1F5&=W4%Rmg+DQLJxZam9&3%Qi5()A(zENn|ZVl}*Rh!Y3 z$Dzo7dp~Ehan^($wGFaz0sB*v>lqC+O*Uoz(k8CC17{7_C8Y**epMDQcMX$u3}O{P zFF5DhF34cb(J#@OAhwtQ7z*L~W@pRtMg}wF*;24zW=pj~qv2}+wxO%oy6~zUg_wJF zsm;y=1EH%k+To1`>wMKle*zOAJk7o%&h=6uL?CRYLQVKQ9bzi!w?A%6Iw#>WKu-U9 zf_NkP>3S;{$S7+v+sbX5y5`C-H6nf4iD?!)?^_4I=!-$25-Umuh~87w#b|k=m955w z`e}2hs|)2%8U*}U`l^?S^v&4D`>SHb#=wYNJ$CQDvbt z%g^Z5_|hsRVD{lS0B~U(zfslcd8)0rWCO6lXqc8I`$uCEe@#D?IHK+v1UtV5>Et@Y ze?vYs*Qs>Tq@0q01?jqxp4ukiT*9vT3yE8zEY#vPiw-$1szAqCqkSx6a!1G6N7HxA zx7MR@If&$mT@QBeWn=FUM{ed=kZpG5oeDucUO4S~uYWKafYA|t4}ST(xqELOT!<$! zx?u$|m%FfHard{x`DXM!5UOvhj6ap&WE`vM%XQe49Y?S6_=o!CNS{QJP0D1SWqRlV zy~_{i5?Vg};4Pv=+t`#CLU4|7ff*RDOSqJYCl*aenY#Pc2ERayLCLNqfoA+2zK}-z zjagyTPmZZ(K%BBnlLj^6I!Pc8S698%6h#;x4qFVYtNZwGK1g<+Mnk;n` zp}YZ^t{Y{T`9&H@07jO#+f0->3NOr_%W=+wZtO4n*3`GNr*gn!j6(4e{e;sM3&5`1 zH^?#oQZQ(aX8tNv<>E~nAl7)W@$gr9^xQdb zd*D=RPa)cO1nUjgN$Mw{CzF>ws={w*3f{nVw?huD&9%U#5_c#+Dx;kz)m(J)wlk4F zaWqO$^)zNG{elrEF{4+X8dvQq^$`{i# zQqYeE7(Me1UVC0JU*ay}d(Q7yqQ=bpGPq6XPQxP5h?TIK5=e7nIL!W;m`TSI$3or%WJ=(QH=US7dGDJkendX&@e$w2`ETXK zynPoUE$YP;P4_Hwtr#%QhaTG?ZRL?s$v%UzFwmYxOzg^Gzh|SqQ_v?&gsWml*)?3K zUpP!D>$$iCM+jQ&%3fiNbX#Q?XL))*(7)VZB`tc4;Eog#*KzqspqEy;aOJzk=cRB3 z&@^*!VniqMztPJ?%8T<-e>hLku{~zOZf-N7yGna)4)%>TaJ@1P&@5@IYJtTWo zO7?+-5)Z*$FhY-J(#N~MVsLyNwRmUI7rvfg`m$o@oQ*(fd;&Y-`6Mjt=Gr+*knIw= zy0|g>ski(7f2um`s5qLX;V%*#LXZW*BEbpn5D4y0NFcbo1s0bq?iL&ZEEa+Vch|*b zg9LXCF2MriUGm)feBYfpbEdmb^-RtDQRh@w{i*}L4*-Diu7FU>N+-^pL{Z2qSx>Pv zrqq!MXp_?)l(@-=1mwb8y#|bQC?v|G`wF#JUz%VZj_G^|A7(Q+C+lG3epXYCX1Sc6 z#*)3GJV=InfV5ZHx#8%~p36_c{f6Xw;Jk!x0cgbF(=Y9Dws6w|t=LqtDygjA{`wFV zp;TR+jw+~=?pFD%x=62bhcv|6)(+2@GGQK@R5o(%wmXd~@HdKKZ1Jajl?9!%4JJ!! zByFi58XueD^J9zmZyCm0`{8ARr?p$jcP=1CF8D}Y&XyEeW9e3LcqaIWK_1KR<$cu% z+aEi6qH?{1_&eFV+X>(gl5tQ%hphk5$0oUWAnmVxugvLpApgoViw#I<+!rraCui<< zerXr@%~GZ(nDJQ|ZG`dCG9XLsXk^ajP89o?6injn?0U_bA$W20qshYiKEPY#ddh@o zcJ%)RySZo8NkpRJck0|#6GY1AS5wSrez1dQ0oN;Wd3w%hDyqi=7tfnJ(|khVrQ))# z7zcS}d4UfQt1;6|7BkPfs&7~*_7nkp+x~~FfYQ%+awcyY4b`J4<}-v=qmrO}Na{T3 zF3t%RSg1ny@t1y_4I?Ey7<|VeO@%5l8XAWMypicLE(|*i2lDzknyI8$xoWf_$}wwf z;)Mg7M8rCh-f_mGFK|uz&L@WT!9nU}{Z8@=R_nBod-y2Z_-eX*qwMo}ix?)!+fLi0 zm+=>0H}x&$CrGD+Plv;ibZ}K zG0xQ%!9D{Etip7yxQ6I6{LqX*KibhTwhN+3Xp6FF43WV73g0p1WwIya=J!n23VM!R zPql#%4q^RP!iIA0hBw>X)`p>8Yr)LYsbLjdnt;S?!P}|+^7LxcEnGQnx35? z$^HOxG%XC;q%S$_1%Nq}6X99~bh^nO0d2UU$$|mVjxyuzR;rJQj@s-plIz^h9A$2! zC%OOz>!dH~XhV&QV(~a($g+jBTVV;+4?iI_r$)|FcYnjWa?R~|XTONfe{E*z6$@0O zboU)d6Da^M56E2S`=iUY?Z>SDkeGG|dez*lX5f+uKjyobH0qOj0C&G^{ z5{sb>hN4YUo13vhKk2U2$Ev@PTb9lL!haPz(1{m^ao9uWVK?mLBsf&Efhs_(jf8z; zJ!D33`d&`VhGP@4Gr765>(qh@`(WY?xTdFn_bcF`VRMLwWE=b*4mV`mh z*Toq7_nAxc0l0^PG!9{K0LMjP7$q*v;Mby+)u4jDjp~-Bm&yrQn5RN--?Rug{6(Kg z-a#_aKnS03&sP#kRv5(_!bFJIy)i1%!N=zTM)n72HxF}bvD zYc{DDuG2#25uS=!A(ERkBRN5MkAgO@4pM{!ts?0V_*kb>p!Vvxi}{O-gKS&|Q`O4; zk#v|ACyBQA7^>x^c>AAcrY*Obn7~aLRj}nKkb`r`LPCIZ38Ll;1l{+w#edZvv1S+a z7h63dHx}_cAbrLD9rZh*A)3g^8VWx4!}A2B^HVQre&O(Mt~jWl_~;*c-JY0)dQ!RI zxwA2Sut$G!kCv5`H%&#T!;2Za_Bq@Wxh%wUwz*LDo~ZmdC^;l#u)eDRD1JYqy}Nm_ zrDP5H4PGeY^MUNjiO*Jknb^MmMiHNSy*EG^yJ}WM)&HXA?hTT**Gj!3dlj0iden$&wHvy8m(G^YOQ z<~#77GBg4!c&sP?bKarGH6gHlu>p0%%xSeJ7e(d?Efz$|_@AuwiGEU@>H-GUBNg~; znjo-!r-+5^E#)Y4SsQzzqJ)bSQezZHGF?w{^Q6uz+8YOZIcm1WIVLaar$~w|?<}LD zxhY^hW_|n9$Hc@ehe;rOmT|p}B$|6Qu?Hr|dSjGWgy^eIFKI*y_ZaF1^fz3Y+c{BR z%N@agBYc7GBNE~WBXjXv(GUy3h>2sZOO9!zdlwaa5TPVoWlUFM#g zOuzjl{R=buQbAD(%ExX}jnwH?@fb4C_*o|)e~C-ulG~fG4mHnf8=_Fd6GVLiyaDX5 z{j1@>do~8-Ulp1izc)nRy%G0=8(31ILB<+($pfq}p2+GAFXhB>ZgLKDq-rr#^ZsE*i+`LSIg?iCw<~&$-n5`05KW+%+|U{NepPDGCC2L$dZqJ zF|V7d>}kQ*+(+mxU(~Q>S3nf3)}ooE68uz>Id78g`#2R_IeF0?wQCebWZQ|8Pc&no$n0hd5=lmHB{K$On2Tv0lch?>1 zK*H?Ghk4kjw6L7o{a=?WNH;6oN8%@`JvKN4PmK#dy8I5f!i+~MJ?}yg1lph3Qr4M- z1pL*$T-iZ^7BU22;FtsYea9aKCmXuM=p_0qpuLby9w?#FT6U%SnmbJ!l00?nu=#SA zk%62=>nd{Mm!Pt;=Gy5EOw#84DzKuKhBd9+uZnLZ5a}141A1jQXi~hLck!7!m*-TZ z0A{ z$T12hcq5s_ZAN1vFC)kwMigY@|AjB}MvSIEGTbF_|vebDPDQ-2}a<U1hU?6T=OWaP{t>ryscM`zbT5DcyFw zLz8IayOlPxg+Cs`Vr^9nZMc#Zdp|@6hJrph$#QP6)lrym=3n`#%<{A=E=fYMORNac zhhqf8sIU`);cvL_Jn2m@HHav=+aw_y_y80WWMYd3M*;j1(6lZa#ooSkK z{V_4GJ$<~<9tMh@-PHFXTW6VkJtZI7%RF;rC~@7fO=Mci9cNrVkDGCH!@vA=ww!`) zmrB)m0^=n!cmlzG$Tb^JY7v`XOD(l}FAd5N@0#ziG;}iw6cb=K&eLvLUBFbnOizsbk@Y=_+j?q9Sx@FM#87rtCMW~l_ z?*Un~r(x?sR12W$AX@m0P$rPG>30;uNo_=FetM}MZL?%;xUIPITgibwR2S1EH_ z4}HS81h>xC_?!{vIVQ;@aNOd&X!;<1X&yrUBnSL9wNP}M5>7Gf zSOEc~e zpv*r)LQ|nRM=W_u@B;6)8m?O4^-%_r(#!uXswP~@0q4CoUlFf&F81mhIU~5 z-Rh|K;k~P`@@IIb#w_Pe>KL$_-b{cXk1+~Do?aU~z3jn-D`c4@1-=Yh1D@Zg`g2Io z2s29bmsgmL)hMDU{eOcEEM(VS1IY#-(8WuDEVGQOLwJpIF5jrT(-g9icm{cLFat}! zkwnebkwDJUzHUVc|EgODU{tL5^5a?r-1+-)Vw7xq zyD^N`N42??F2{;?);1L~7HNgV6ts`nkP5ZZ%Jq4jrBJvBiiuDpG|E^gxQ0UzY4s7JCOgR=(Cd;ZYY$f$5E z;Iy!QV|bg7b7p(zj|HNl>I&4cP3J0@f!K$&WE+8;mofaDX88tt(_^-7I3>&7QNH>k z^${P42{+!EPlbGUJl%+!{}m$Ciqpp}Bz9lGqsv`rW%ns?{VCNhp3h9H4(sQ+`}u>e zywwK9Hh1>k(DPY&$Y*YYvBZ&A@^x<02NCi06_M~f(ZdClNpL5@Bx-#gs0Uu1?`Fbp z+X>yh+pYbXR;i2eAF-rf+X}Iyr%a(e0IAF^i|LCe#RX zrSxj=Bxv6ieWJ{@ga5f~g=T3tK|ZK?uhY)pn3KGJh~4uH!eBrWyni9<%-AHTC7FgN z?y%Nko4V?NxBSTLC*hrgW(ek$y%b>AQL0;SuKWHLF8DIjI5~=)&7muhk&}!gA#TIo zsmiPc`HosT*PGni!stb=s6C+7$gJ&I{NGvt(|FCgJS6Wbx!f41;CSD>m7KF(9HJu( zAf>DjbhQ03^Azm8^*D3piS`3S2`O5MNW-n_i$+ls6IiF)sAcJ7(bNtSs}+!*O-xA8r{QXz@> zJFt6r3H@;j)@MgneQ`D5-;^8rEE^1Y{f$%o_VPo4QprFag~k!;XQQDIcxWInz0DTDw4M7fa zrW~dDe~i9hKR_T~gu{oD4O@LwsP*iywDjEiYL+_Mi2m&1fn);>-F3AipHBQ)h`Cnt zxd={jPND2hbOkSG1JZjqDLWxlq6e5CvxdA5f8MMGt^`2c*b)%-khFa)pRt|zk4@l8 zM$#4e3#}r~MLygi9v{0$moq?Pwn(Ji#>gB$U-?4O8A2XCyGmZ;+He2Ez-g=OVa>0^ z=Dx?r0lv6htJ-B%IJ=}drlQv)2&MUG)GVv**R76bFG$|bxZTSO*WZOb@S^GdRlvxTgKSGisj!`;e*sL8`yLJV!B)M2le zap<{&`UaT_aclgO_*#*x#~qAw7|4g~i6iA2qr@#60k>3HA$vNpC)hE0;ZM;e;g zA=zEYImsKm6z14B)5D)`^-*g?=u_V0%aTWA@ZqOe^}a#jSIRYvT{Or^+anwQ!OSDl zwv0kO%yq|W?S|9wYM(TjPC!G*R};YG>#fnK-t@3y8AlrlT~bI3m0aBxi(m=!*9kjV zKG(sYUBpfBy#j_ndHsEgh0VKu#toJwL7+xymVH}Ct|N>Aa}->_j2){&%pk^(^)^yxNL1KKIjrCK*k#$82ul~}EW z?V3)hn?gW9n&0fsjO%4;A9^AexTgonL+biw_z$|e5;}%=D4S5dIsj1Y@dTi*goI24 zAOZj|0Dw$Cbj=WZp-6T_fkyVknN(&J#7JUn8hIi`8q>dRvwz!Cf5)cMWd7dE)5#MB z(pmquEz|!yCil00{hz*ghT`9TOojmN5T^y=sZ?2yz5fFj+bKK% delta 38149 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 qx)H*>6E7|ZMEzfwBo(+wF56$wzkeX{e}RZp;l8', + $name, + $name, + $disabled ? ' disabled': '' + ); + } + /************************************************************************** * NEW METHODS END diff --git a/src/admin/layout/class-init.php b/src/admin/layout/class-init.php index 5fb8c08..41f972b 100644 --- a/src/admin/layout/class-init.php +++ b/src/admin/layout/class-init.php @@ -95,6 +95,10 @@ class Init { Settings::instance()->register_settings(); Settings::instance()->settings_sections['general']->add_settings_section(); + Settings::instance()->settings_sections['referrers_and_tooltips']->add_settings_section(); + Settings::instance()->settings_sections['scope_and_priority']->add_settings_section(); + Settings::instance()->settings_sections['custom_css']->add_settings_section(); + $this->settings->add_settings_sections(); $this->settings->add_settings_fields(); } diff --git a/src/admin/layout/class-settings-page.php b/src/admin/layout/class-settings-page.php index f659dd1..943308c 100644 --- a/src/admin/layout/class-settings-page.php +++ b/src/admin/layout/class-settings-page.php @@ -89,70 +89,6 @@ class SettingsPage extends Engine { } } - public function add_general_settings_fields(): void { - // Options for the label element. - $label_element_options = array( - 'p' => __( 'paragraph', 'footnotes' ), - 'h2' => __( 'heading 2', 'footnotes' ), - 'h3' => __( 'heading 3', 'footnotes' ), - 'h4' => __( 'heading 4', 'footnotes' ), - 'h5' => __( 'heading 5', 'footnotes' ), - 'h6' => __( 'heading 6', 'footnotes' ), - ); - // Options for the positioning of the reference container. - $positions_options = array( - 'post_end' => __( 'at the end of the post', 'footnotes' ), - 'widget' => __( 'in the widget area', 'footnotes' ), - 'footer' => __( 'in the footer', 'footnotes' ), - ); - // Basic responsive page layout options. - $page_layout_options = array( - 'none' => __( 'No', 'footnotes' ), - 'reference-container' => __( 'to the reference container exclusively', 'footnotes' ), - 'entry-content' => __( 'to the div element starting below the post title', 'footnotes' ), - 'main-content' => __( 'to the main element including the post title', 'footnotes' ), - ); - - // Options for the separating punctuation between backlinks. - $separators_options = array( - // Unicode character names are conventionally uppercase. - 'comma' => __( 'COMMA', 'footnotes' ), - 'semicolon' => __( 'SEMICOLON', 'footnotes' ), - 'en_dash' => __( 'EN DASH', 'footnotes' ), - ); - - /* - * Options for the terminating punctuation after backlinks. - * The Unicode name of RIGHT PARENTHESIS was originally more accurate because. - * This character is bidi-mirrored. Let's use the Unicode 1.0 name. - * The wrong names were enforced in spite of Unicode, that subsequently scrambled to correct. - */ - $terminators_options = array( - 'period' => __( 'FULL STOP', 'footnotes' ), - // Unicode 1.0 name of RIGHT PARENTHESIS (represented as a left parenthesis in right-to-left scripts). - 'parenthesis' => __( 'CLOSING PARENTHESIS', 'footnotes' ), - 'colon' => __( 'COLON', 'footnotes' ), - ); - // Options for the first column width (per cent is a ratio, not a unit). - $width_units_options = array( - '%' => __( 'per cent', 'footnotes' ), - 'px' => __( 'pixels', 'footnotes' ), - 'rem' => __( 'root em', 'footnotes' ), - 'em' => __( 'em', 'footnotes' ), - 'vw' => __( 'viewport width', 'footnotes' ), - ); - // Options for reference container script mode. - $script_mode_options = array( - 'jquery' => __( 'jQuery', 'footnotes' ), - 'js' => __( 'plain JavaScript', 'footnotes' ), - ); - // Options for Yes/No select box. - $enabled_options = array( - 'yes' => __( 'Yes', 'footnotes' ), - 'no' => __( 'No', 'footnotes' ), - ); - } - public function setting_field_callback( array $args ): void { if (isset($args['type'])) { echo $args['description'] . ''; @@ -170,6 +106,9 @@ class SettingsPage extends Engine { case 'checkbox': $this->add_input_checkbox($args); return; + case 'color': + $this->add_input_color($args); + return; default: trigger_error("Unknown setting type.", E_USER_ERROR); } } else trigger_error("No setting type.", E_USER_ERROR); @@ -179,742 +118,6 @@ class SettingsPage extends Engine { * NEW METHODS END **************************************************************************/ - /** - * Displays the AMP compatibility mode option. - * - * @since 2.6.0 (release) - */ - public function amp_compat(): void { - - // Load template file. - $template = new Template( Template::DASHBOARD, 'settings-amp' ); - // Replace all placeholders. - $template->replace( - array( - // Translators: '%s' is the link text 'AMP-WP' linked to the plugin's front page on WordPress.org. - 'description-1-amp' => sprintf( __( 'The official %s plugin is required when this option is enabled.', 'footnotes' ), 'AMP-WP' ), - 'label-amp' => $this->add_label( Settings::FOOTNOTES_AMP_COMPATIBILITY_ENABLE, __( 'Enable AMP compatibility mode:', 'footnotes' ) ), - 'amp' => $this->add_checkbox( Settings::FOOTNOTES_AMP_COMPATIBILITY_ENABLE ), - 'notice-amp' => __( 'This option enables hard links with configurable scroll offset in % viewport height.', 'footnotes' ), - // Translators: '%s' is the logogram of the 'Footnotes' plugin. - 'description-2-amp' => sprintf( __( '%s is becoming AMP compatible when this box is checked. Styled tooltips are displayed with fade-in/fade-out effect if enabled, and the reference container expands also on clicking a referrer if it\'s collapsed by default.', 'footnotes' ), '' . Config::PLUGIN_PUBLIC_NAME . '' ), - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays all options for the footnotes start and end tag short codes. - * - * @since 1.5.0 - */ - public function start_end(): void { - // Footnotes start tag short code options. - $shortcode_start = array( - '((' => '((', - '(((' => '(((', - '{{' => '{{', - '{{{' => '{{{', - '[n]' => '[n]', - '[fn]' => '[fn]', - htmlspecialchars( '' ) => htmlspecialchars( '' ), - '[ref]' => '[ref]', - htmlspecialchars( '' ) => htmlspecialchars( '' ), - // Custom (user-defined) start and end tags bracketing the footnote text inline. - 'userdefined' => __( 'custom short code', 'footnotes' ), - ); - // Footnotes end tag short code options. - $shortcode_end = array( - '))' => '))', - ')))' => ')))', - '}}' => '}}', - '}}}' => '}}}', - '[/n]' => '[/n]', - '[/fn]' => '[/fn]', - htmlspecialchars( '' ) => htmlspecialchars( '' ), - '[/ref]' => '[/ref]', - htmlspecialchars( '' ) => htmlspecialchars( '' ), - // Custom (user-defined) start and end tags bracketing the footnote text inline. - 'userdefined' => __( 'custom short code', 'footnotes' ), - ); - // Options for the syntax validation. - $enable = array( - 'yes' => __( 'Yes', 'footnotes' ), - 'no' => __( 'No', 'footnotes' ), - ); - - // Load template file. - $template = new Template( Template::DASHBOARD, 'settings-start-end' ); - // Replace all placeholders. - $template->replace( - array( - 'description-escapement' => __( 'When delimiters with pointy brackets are used, the diverging escapement schemas will be unified before footnotes are processed.', 'footnotes' ), - - 'label-short-code-start' => $this->add_label( Settings::FOOTNOTES_SHORT_CODE_START, __( 'Footnote start tag short code:', 'footnotes' ) ), - 'short-code-start' => $this->add_select_box( Settings::FOOTNOTES_SHORT_CODE_START, $shortcode_start ), - 'short-code-start-user' => $this->add_text_box( Settings::FOOTNOTES_SHORT_CODE_START_USER_DEFINED ), - - 'label-short-code-end' => $this->add_label( Settings::FOOTNOTES_SHORT_CODE_END, __( 'Footnote end tag short code:', 'footnotes' ) ), - 'short-code-end' => $this->add_select_box( Settings::FOOTNOTES_SHORT_CODE_END, $shortcode_end ), - 'short-code-end-user' => $this->add_text_box( Settings::FOOTNOTES_SHORT_CODE_END_USER_DEFINED ), - - // For script showing/hiding user defined text boxes. - 'short-code-start-id' => Settings::FOOTNOTES_SHORT_CODE_START, - 'short-code-end-id' => Settings::FOOTNOTES_SHORT_CODE_END, - 'short-code-start-user-id' => Settings::FOOTNOTES_SHORT_CODE_START_USER_DEFINED, - 'short-code-end-user-id' => Settings::FOOTNOTES_SHORT_CODE_END_USER_DEFINED, - - 'description-parentheses' => __( 'WARNING: Although widespread industry standard, the double parentheses are problematic because they may occur in scripts embedded in the content and be mistaken as a short code.', 'footnotes' ), - - // Option to enable syntax validation, label mirrored in task.php. - 'label-syntax' => $this->add_label( Settings::FOOTNOTE_SHORTCODE_SYNTAX_VALIDATION_ENABLE, __( 'Check for balanced shortcodes:', 'footnotes' ) ), - 'syntax' => $this->add_select_box( Settings::FOOTNOTE_SHORTCODE_SYNTAX_VALIDATION_ENABLE, $enable ), - 'notice-syntax' => __( 'In the presence of a lone start tag shortcode, a warning displays below the post title.', 'footnotes' ), - - 'description-syntax' => __( 'If the start tag short code is \'((\' or \'(((\', it will not be reported as unbalanced if the following string contains braces hinting that it is a script.', 'footnotes' ), - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays all options for the footnotes numbering. - * - * @since 2.2.0 - */ - public function numbering(): void { - // Define some space for the output. - $space = '     '; - // Options for the combination of identical footnotes. - $enable = array( - 'yes' => __( 'Yes', 'footnotes' ), - 'no' => __( 'No', 'footnotes' ), - ); - // Options for the numbering style of the footnotes. - $counter_style = array( - 'arabic_plain' => __( 'plain Arabic numbers', 'footnotes' ) . $space . '1, 2, 3, 4, 5, …', - 'arabic_leading' => __( 'zero-padded Arabic numbers', 'footnotes' ) . $space . '01, 02, 03, 04, 05, …', - 'latin_low' => __( 'lowercase Latin letters', 'footnotes' ) . $space . 'a, b, c, d, e, …', - 'latin_high' => __( 'uppercase Latin letters', 'footnotes' ) . $space . 'A, B, C, D, E, …', - 'romanic' => __( 'uppercase Roman numerals', 'footnotes' ) . $space . 'I, II, III, IV, V, …', - 'roman_low' => __( 'lowercase Roman numerals', 'footnotes' ) . $space . 'i, ii, iii, iv, v, …', - ); - - // Load template file. - $template = new Template( Template::DASHBOARD, 'settings-numbering' ); - // Replace all placeholders. - $template->replace( - array( - 'label-counter-style' => $this->add_label( Settings::FOOTNOTES_COUNTER_STYLE, __( 'Numbering style:', 'footnotes' ) ), - 'counter-style' => $this->add_select_box( Settings::FOOTNOTES_COUNTER_STYLE, $counter_style ), - - // Algorithmically combine identicals. - 'label-identical' => $this->add_label( COMBINE_IDENTICAL_FOOTNOTES, __( 'Combine identical footnotes:', 'footnotes' ) ), - 'identical' => $this->add_select_box( COMBINE_IDENTICAL_FOOTNOTES, $enable ), - 'notice-identical' => __( 'This option may require copy-pasting footnotes in multiple instances.', 'footnotes' ), - // Support for Ibid. notation added thanks to @meglio in . - 'description-identical' => __( 'Even when footnotes are combined, footnote numbers keep incrementing. This avoids suboptimal referrer and backlink disambiguation using a secondary numbering system. The Ibid. notation and the op. cit. abbreviation followed by the current page number avoid repeating the footnote content. For changing sources, shortened citations may be used. Repeating full citations is also an opportunity to add details.', 'footnotes' ), - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays all options for the scrolling behavior. - * - * @since 2.2.0 - */ - public function scrolling(): void { - - // Options for enabling scroll duration asymmetricity. - $enable = array( - 'yes' => __( 'Yes', 'footnotes' ), - 'no' => __( 'No', 'footnotes' ), - ); - - // Load template file. - $template = new Template( Template::DASHBOARD, 'settings-scrolling' ); - // Replace all placeholders. - $template->replace( - array( - - 'label-scroll-css' => $this->add_label( Settings::FOOTNOTES_CSS_SMOOTH_SCROLLING, __( 'CSS-based smooth scrolling:', 'footnotes' ) ), - 'scroll-css' => $this->add_select_box( Settings::FOOTNOTES_CSS_SMOOTH_SCROLLING, $enable ), - 'notice-scroll-css' => __( 'May slightly disturb jQuery scrolling and is therefore disabled by default. Works in recent browsers.', 'footnotes' ), - - 'label-scroll-offset' => $this->add_label( Settings::FOOTNOTES_SCROLL_OFFSET, __( 'Scroll offset:', 'footnotes' ) ), - 'scroll-offset' => $this->add_num_box( Settings::FOOTNOTES_SCROLL_OFFSET, 0, 100 ), - 'notice-scroll-offset' => __( 'per cent viewport height from the upper edge', 'footnotes' ), - - 'label-scroll-duration' => $this->add_label( Settings::FOOTNOTES_SCROLL_DURATION, __( 'Scroll duration:', 'footnotes' ) ), - 'scroll-duration' => $this->add_num_box( Settings::FOOTNOTES_SCROLL_DURATION, 0, 20000 ), - 'notice-scroll-duration' => __( 'milliseconds. If asymmetric scroll durations are enabled, this is the scroll-up duration.', 'footnotes' ), - - // Enable scroll duration asymmetricity. - 'label-scroll-asymmetricity' => $this->add_label( Settings::FOOTNOTES_SCROLL_DURATION_ASYMMETRICITY, __( 'Enable asymmetric scroll durations:', 'footnotes' ) ), - 'scroll-asymmetricity' => $this->add_select_box( Settings::FOOTNOTES_SCROLL_DURATION_ASYMMETRICITY, $enable ), - 'notice-scroll-asymmetricity' => __( 'With this option enabled, scrolling up may take longer than down, or conversely.', 'footnotes' ), - - 'label-scroll-down-duration' => $this->add_label( Settings::FOOTNOTES_SCROLL_DOWN_DURATION, __( 'Scroll-down duration:', 'footnotes' ) ), - 'scroll-down-duration' => $this->add_num_box( Settings::FOOTNOTES_SCROLL_DOWN_DURATION, 0, 20000 ), - 'notice-scroll-down-duration' => __( 'milliseconds', 'footnotes' ), - - 'label-scroll-down-delay' => $this->add_label( Settings::FOOTNOTES_SCROLL_DOWN_DELAY, __( 'Scroll-down delay:', 'footnotes' ) ), - 'scroll-down-delay' => $this->add_num_box( Settings::FOOTNOTES_SCROLL_DOWN_DELAY, 0, 20000 ), - 'notice-scroll-down-delay' => __( 'milliseconds. Useful to see the effect on input elements when referrers without hard links are clicked in form labels.', 'footnotes' ), - - 'label-scroll-up-delay' => $this->add_label( Settings::FOOTNOTES_SCROLL_UP_DELAY, __( 'Scroll-up delay:', 'footnotes' ) ), - 'scroll-up-delay' => $this->add_num_box( Settings::FOOTNOTES_SCROLL_UP_DELAY, 0, 20000 ), - 'notice-scroll-up-delay' => __( 'milliseconds. Less useful than the scroll-down delay.', 'footnotes' ), - - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays all options for the fragment identifier configuration. - * - * @since 2.2.0 - */ - public function hard_links(): void { - - // Options for enabling hard links for AMP compat. - $enable = array( - 'yes' => __( 'Yes', 'footnotes' ), - 'no' => __( 'No', 'footnotes' ), - ); - - // Load template file. - $template = new Template( Template::DASHBOARD, 'settings-hard-links' ); - // Replace all placeholders. - $template->replace( - array( - - 'label-hard-links' => $this->add_label( Settings::FOOTNOTES_HARD_LINKS_ENABLE, __( 'Enable hard links:', 'footnotes' ) ), - 'hard-links' => $this->add_select_box( Settings::FOOTNOTES_HARD_LINKS_ENABLE, $enable ), - 'notice-hard-links' => __( 'Hard links disable jQuery delays but have the same scroll offset, and allow to share footnotes (accessed if the list is not collapsed by default).', 'footnotes' ), - - 'label-footnote' => $this->add_label( Settings::FOOTNOTE_FRAGMENT_ID_SLUG, __( 'Fragment identifier slug for footnotes:', 'footnotes' ) ), - 'footnote' => $this->add_text_box( Settings::FOOTNOTE_FRAGMENT_ID_SLUG ), - 'notice-footnote' => __( 'This will show up in the address bar after clicking on a hard-linked footnote referrer.', 'footnotes' ), - - 'label-referrer' => $this->add_label( Settings::REFERRER_FRAGMENT_ID_SLUG, __( 'Fragment identifier slug for footnote referrers:', 'footnotes' ) ), - 'referrer' => $this->add_text_box( Settings::REFERRER_FRAGMENT_ID_SLUG ), - 'notice-referrer' => __( 'This will show up in the address bar after clicking on a hard-linked backlink.', 'footnotes' ), - - 'label-separator' => $this->add_label( Settings::HARD_LINK_IDS_SEPARATOR, __( 'ID separator:', 'footnotes' ) ), - 'separator' => $this->add_text_box( Settings::HARD_LINK_IDS_SEPARATOR ), - 'notice-separator' => __( 'May be empty or any string, for example _, - or +, to distinguish post number, container number and footnote number.', 'footnotes' ), - - // Enable backlink tooltips. - 'label-backlink-tooltips' => $this->add_label( Settings::FOOTNOTES_BACKLINK_TOOLTIP_ENABLE, __( 'Enable backlink tooltips:', 'footnotes' ) ), - 'backlink-tooltips' => $this->add_select_box( Settings::FOOTNOTES_BACKLINK_TOOLTIP_ENABLE, $enable ), - 'notice-backlink-tooltips' => __( 'Hard backlinks get ordinary tooltips hinting to use the backbutton instead to keep it usable.', 'footnotes' ), - - 'label-backlink-tooltip-text' => $this->add_label( Settings::FOOTNOTES_BACKLINK_TOOLTIP_TEXT, __( 'Backlink tooltip text:', 'footnotes' ) ), - 'backlink-tooltip-text' => $this->add_text_box( Settings::FOOTNOTES_BACKLINK_TOOLTIP_TEXT ), - 'notice-backlink-tooltip-text' => __( 'Default text is the keyboard shortcut; may be a localized descriptive hint.', 'footnotes' ), - - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays all settings for ‘I love Footnotes’ note. - * - * @since 1.5.0 - */ - public function love(): void { - // Options for the acknowledgment display in the footer. - $love = array( - // Logo only. - 'text-3' => Config::PLUGIN_PUBLIC_NAME, - // Logo followed by heart symbol. - 'text-4' => sprintf( '%s %s', Config::PLUGIN_PUBLIC_NAME, Config::LOVE_SYMBOL ), - // Logo preceded by heart symbol. - 'text-5' => sprintf( '%s %s', Config::LOVE_SYMBOL, Config::PLUGIN_PUBLIC_NAME ), - // Translators: 2: heart symbol 1: footnotes logogram. - 'text-1' => sprintf( __( 'I %2$s %1$s', 'footnotes' ), Config::PLUGIN_PUBLIC_NAME, Config::LOVE_SYMBOL ), - // Translators: %s: Footnotes plugin logo. - 'text-6' => sprintf( __( 'This website uses %s.', 'footnotes' ), Config::PLUGIN_PUBLIC_NAME ), - // Translators: %s: Footnotes plugin logo. - 'text-7' => sprintf( __( 'This website uses the %s plugin.', 'footnotes' ), Config::PLUGIN_PUBLIC_NAME ), - // Translators: %s: Footnotes plugin logo. - 'text-2' => sprintf( __( 'This website uses the awesome %s plugin.', 'footnotes' ), Config::PLUGIN_PUBLIC_NAME ), - 'random' => __( 'randomly determined display of either mention', 'footnotes' ), - // Translators: 1: Plugin logo.2: heart symbol. - 'no' => sprintf( __( 'no display of any "%1$s %2$s" mention in the footer', 'footnotes' ), Config::PLUGIN_PUBLIC_NAME, Config::LOVE_SYMBOL ), - ); - - // Load template file. - $template = new Template( Template::DASHBOARD, 'settings-love' ); - // Replace all placeholders. - $template->replace( - array( - // Translators: %s: Footnotes plugin logo. - 'label-love' => $this->add_label( Settings::FOOTNOTES_LOVE, sprintf( __( 'Tell the world you\'re using %s:', 'footnotes' ), Config::PLUGIN_PUBLIC_NAME ) ), - 'love' => $this->add_select_box( Settings::FOOTNOTES_LOVE, $love ), - // Translators: %s: Footnotes plugin logo. - 'label-no-love' => $this->add_text( sprintf( __( 'Shortcode to inhibit the display of the %s mention on specific pages:', 'footnotes' ), Config::PLUGIN_PUBLIC_NAME ) ), - 'no-love' => $this->add_text( Config::NO_LOVE_SLUG ), - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays the footnotes in excerpt setting. - * - * @since 1.5.0 - */ - public function excerpts(): void { - // Options for options select box. - $excerpt_mode = array( - 'yes' => __( 'Yes, generate excerpts from posts with effectively processed footnotes and other markup', 'footnotes' ), - 'no' => __( 'No, generate excerpts from posts but remove all footnotes and output plain text', 'footnotes' ), - 'manual' => __( 'Yes but run the process only to display tooltips in manual excerpts with footnote short codes', 'footnotes' ), - ); - - // Load template file. - $template = new Template( Template::DASHBOARD, 'settings-excerpts' ); - // Replace all placeholders. - $template->replace( - array( - 'label-excerpts' => $this->add_label( Settings::FOOTNOTES_IN_EXCERPT, __( 'Process footnotes in excerpts:', 'footnotes' ) ), - 'excerpts' => $this->add_select_box( Settings::FOOTNOTES_IN_EXCERPT, $excerpt_mode ), - 'notice-excerpts' => __( 'If the_excerpt is enabled.', 'footnotes' ), - // Translators: %s: link text 'Advanced Excerpt' linked to the plugin\'s WordPress.org front page. - // Translators: %s: Footnotes plugin logo. - 'description-excerpts' => sprintf( __( 'To not display footnotes in excerpts, the %s plugin generates excerpts on the basis of the posts to be able to remove the footnotes. Else, footnotes may be processed in manual excerpts OR processed based on the posts. — For this setting to be effective, the hook the_excerpt must be enabled under Scope and priority.', 'footnotes' ), '' . Config::PLUGIN_PUBLIC_NAME . '' ), - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays all settings for the footnote referrers. - * - * @since 1.5.0 - */ - public function superscript(): void { - // Options for Yes/No select box. - $enabled = array( - 'yes' => __( 'Yes', 'footnotes' ), - 'no' => __( 'No', 'footnotes' ), - ); - // Options for superscript normalize scope. - $normalize_superscript = array( - 'no' => __( 'No', 'footnotes' ), - 'referrers' => __( 'Footnote referrers', 'footnotes' ), - 'all' => __( 'All superscript elements', 'footnotes' ), - ); - // Load template file. - $template = new Template( Template::DASHBOARD, 'customize-superscript' ); - // Replace all placeholders. - $template->replace( - array( - 'label-superscript' => $this->add_label( Settings::FOOTNOTES_REFERRER_SUPERSCRIPT_TAGS, __( 'Display footnote referrers in superscript:', 'footnotes' ) ), - 'superscript' => $this->add_select_box( Settings::FOOTNOTES_REFERRER_SUPERSCRIPT_TAGS, $enabled ), - - 'label-normalize' => $this->add_label( Settings::FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT, __( 'Normalize vertical alignment and font size:', 'footnotes' ) ), - 'normalize' => $this->add_select_box( Settings::FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT, $normalize_superscript ), - 'notice-normalize' => __( 'Most themes don\'t need this fix.', 'footnotes' ), - - 'label-before' => $this->add_label( Settings::FOOTNOTES_STYLING_BEFORE, __( 'At the start of the footnote referrers:', 'footnotes' ) ), - 'before' => $this->add_text_box( Settings::FOOTNOTES_STYLING_BEFORE ), - - 'label-after' => $this->add_label( Settings::FOOTNOTES_STYLING_AFTER, __( 'At the end of the footnote referrers:', 'footnotes' ) ), - 'after' => $this->add_text_box( Settings::FOOTNOTES_STYLING_AFTER ), - - 'label-link' => $this->add_label( Settings::LINK_ELEMENT_ENABLED, __( 'Use the link element for referrers and backlinks:', 'footnotes' ) ), - 'notice-link' => __( 'Please find this setting at the end of the reference container settings. The link element is needed to apply the theme\'s link color.', 'footnotes' ), - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays the setting for the input label issue solution. - * - * @since 2.5.12 - */ - public function label_solution(): void { - // Options for the input label issue solution. - $issue_solutions = array( - 'none' => __( '0. No problem or solved otherwise', 'footnotes' ), - 'move' => __( 'A. Footnotes are moved out and appended after the label\'s end (recommended)', 'footnotes' ), - 'disconnect' => __( 'B. Labels with footnotes are disconnected from input element (discouraged)', 'footnotes' ), - ); - // Load template file. - $template = new Template( Template::DASHBOARD, 'configure-label-solution' ); - // Replace all placeholders. - $template->replace( - array( - 'description-1-selection' => __( 'Clicking a footnote referrer in an input element label toggles the input except when hard links are enabled. In jQuery mode, the recommended solution is to move footnotes and append them after the label (option A).', 'footnotes' ), - 'label-selection' => $this->add_label( Settings::FOOTNOTES_LABEL_ISSUE_SOLUTION, __( 'Solve input label issue:', 'footnotes' ) ), - 'selection' => $this->add_select_box( Settings::FOOTNOTES_LABEL_ISSUE_SOLUTION, $issue_solutions ), - 'description-2-selection' => __( 'Option B is discouraged because disconnecting a label from its input element may compromise accessibility. This option is a last resort in case footnotes must absolutely stay inside the label. (Using jQuery \'event.stopPropagation\' failed.)', 'footnotes' ), - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays enabled status for the footnotes mouse-over box. - * - * @since 1.5.2 - */ - public function mouseover_box(): void { - // Options for Yes/No select box. - $enabled = array( - 'yes' => __( 'Yes', 'footnotes' ), - 'no' => __( 'No', 'footnotes' ), - ); - - // Load template file. - $template = new Template( Template::DASHBOARD, 'mouse-over-box-display' ); - // Replace all placeholders. - $template->replace( - array( - - 'label-enable' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_ENABLED, __( 'Display tooltips:', 'footnotes' ) ), - 'enable' => $this->add_select_box( Settings::FOOTNOTES_MOUSE_OVER_BOX_ENABLED, $enabled ), - 'notice-enable' => __( 'Formatted text boxes allowing hyperlinks, displayed on mouse-over or tap and hold.', 'footnotes' ), - - 'label-alternative' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE, __( 'Display alternative tooltips:', 'footnotes' ) ), - 'alternative' => $this->add_select_box( Settings::FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE, $enabled ), - 'notice-alternative' => __( 'Intended to work around a configuration-related tooltip outage.', 'footnotes' ), - // Translators: %s: Footnotes plugin logo. - 'description-alternative' => sprintf( __( 'These alternative tooltips work around a website related jQuery UI outage. They are low-script but use the AMP incompatible onmouseover and onmouseout arguments, along with CSS transitions for fade-in/out. The very small script is inserted after Footnotes\' internal stylesheet. When this option is enabled, %s does not load jQuery UI nor jQuery Tools.', 'footnotes' ), '' . Config::PLUGIN_PUBLIC_NAME . '' ), - - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays position settings for the footnotes mouse-over box. - * - * @since 2.2.0 - */ - public function mouseover_box_position(): void { - - // Options for the Mouse-over box position. - $position = array( - 'top left' => __( 'top left', 'footnotes' ), - 'top center' => __( 'top center', 'footnotes' ), - 'top right' => __( 'top right', 'footnotes' ), - 'center right' => __( 'center right', 'footnotes' ), - 'bottom right' => __( 'bottom right', 'footnotes' ), - 'bottom center' => __( 'bottom center', 'footnotes' ), - 'bottom left' => __( 'bottom left', 'footnotes' ), - 'center left' => __( 'center left', 'footnotes' ), - ); - // Options for the alternative Mouse-over box position. - $alternative_position = array( - 'top left' => __( 'top left', 'footnotes' ), - 'top right' => __( 'top right', 'footnotes' ), - 'bottom right' => __( 'bottom right', 'footnotes' ), - 'bottom left' => __( 'bottom left', 'footnotes' ), - ); - - // Load template file. - $template = new Template( Template::DASHBOARD, 'mouse-over-box-position' ); - // Replace all placeholders. - $template->replace( - array( - - 'label-position' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_POSITION, __( 'Position:', 'footnotes' ) ), - 'position' => $this->add_select_box( Settings::FOOTNOTES_MOUSE_OVER_BOX_POSITION, $position ), - 'position-alternative' => $this->add_select_box( Settings::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_POSITION, $alternative_position ), - 'notice-position' => __( 'The second column of settings boxes is for the alternative tooltips.', 'footnotes' ), - - 'label-offset-x' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X, __( 'Horizontal offset:', 'footnotes' ) ), - 'offset-x' => $this->add_num_box( Settings::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X, -500, 500 ), - 'offset-x-alternative' => $this->add_num_box( Settings::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_X, -500, 500 ), - 'notice-offset-x' => __( 'pixels; negative value for a leftwards offset; alternative tooltips: direction depends on position', 'footnotes' ), - - 'label-offset-y' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y, __( 'Vertical offset:', 'footnotes' ) ), - 'offset-y' => $this->add_num_box( Settings::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y, -500, 500 ), - 'offset-y-alternative' => $this->add_num_box( Settings::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_Y, -500, 500 ), - 'notice-offset-y' => __( 'pixels; negative value for an upwards offset; alternative tooltips: direction depends on position', 'footnotes' ), - - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays dimensions setting for the footnotes mouse-over box. - * - * @since 2.2.0 - */ - public function mouseover_box_dimensions(): void { - - // Load template file. - $template = new Template( Template::DASHBOARD, 'mouse-over-box-dimensions' ); - // Replace all placeholders. - $template->replace( - array( - - 'label-max-width' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH, __( 'Maximum width:', 'footnotes' ) ), - 'max-width' => $this->add_num_box( Settings::FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH, 0, 1280 ), - 'width' => $this->add_num_box( Settings::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH, 0, 1280 ), - 'notice-max-width' => __( 'pixels; set to 0 for jQuery tooltips without max width; alternative tooltips are given the value in the second box as fixed width.', 'footnotes' ), - - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays timing settings for the footnotes mouse-over box. - * - * @since 2.2.0 - */ - public function mouseover_box_timing(): void { - - // Load template file. - $template = new Template( Template::DASHBOARD, 'mouse-over-box-timing' ); - // Replace all placeholders. - $template->replace( - array( - - 'label-fade-in-delay' => $this->add_label( Settings::MOUSE_OVER_BOX_FADE_IN_DELAY, __( 'Fade-in delay:', 'footnotes' ) ), - 'fade-in-delay' => $this->add_num_box( Settings::MOUSE_OVER_BOX_FADE_IN_DELAY, 0, 20000 ), - 'notice-fade-in-delay' => __( 'milliseconds', 'footnotes' ), - - 'label-fade-in-duration' => $this->add_label( Settings::MOUSE_OVER_BOX_FADE_IN_DURATION, __( 'Fade-in duration:', 'footnotes' ) ), - 'fade-in-duration' => $this->add_num_box( Settings::MOUSE_OVER_BOX_FADE_IN_DURATION, 0, 20000 ), - 'notice-fade-in-duration' => __( 'milliseconds', 'footnotes' ), - - 'label-fade-out-delay' => $this->add_label( Settings::MOUSE_OVER_BOX_FADE_OUT_DELAY, __( 'Fade-out delay:', 'footnotes' ) ), - 'fade-out-delay' => $this->add_num_box( Settings::MOUSE_OVER_BOX_FADE_OUT_DELAY, 0, 20000 ), - 'notice-fade-out-delay' => __( 'milliseconds', 'footnotes' ), - - 'label-fade-out-duration' => $this->add_label( Settings::MOUSE_OVER_BOX_FADE_OUT_DURATION, __( 'Fade-out duration:', 'footnotes' ) ), - 'fade-out-duration' => $this->add_num_box( Settings::MOUSE_OVER_BOX_FADE_OUT_DURATION, 0, 20000 ), - 'notice-fade-out-duration' => __( 'milliseconds', 'footnotes' ), - - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays truncation settings for the footnotes mouse-over box. - * - * @since 2.2.0 - */ - public function mouseover_box_truncation(): void { - // Options for Yes/No select box. - $enabled = array( - 'yes' => __( 'Yes', 'footnotes' ), - 'no' => __( 'No', 'footnotes' ), - ); - - // Load template file. - $template = new Template( Template::DASHBOARD, 'mouse-over-box-truncation' ); - // Replace all placeholders. - $template->replace( - array( - - 'label-truncation' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_ENABLED, __( 'Truncate the note in the tooltip:', 'footnotes' ) ), - 'truncation' => $this->add_select_box( Settings::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_ENABLED, $enabled ), - - 'label-max-length' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH, __( 'Maximum number of characters in the tooltip:', 'footnotes' ) ), - 'max-length' => $this->add_num_box( Settings::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH, 3, 10000 ), - // The feature trims back until the last full word. - 'notice-max-length' => __( 'No weird cuts.', 'footnotes' ), - - 'label-readon' => $this->add_label( Settings::FOOTNOTES_TOOLTIP_READON_LABEL, __( '\'Read on\' button label:', 'footnotes' ) ), - 'readon' => $this->add_text_box( Settings::FOOTNOTES_TOOLTIP_READON_LABEL ), - - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays dedicated tooltip text settings for the footnotes mouse-over box. - * - * @since 2.2.0 - */ - public function mouseover_box_text(): void { - // Options for Yes/No select box. - $enabled = array( - 'yes' => __( 'Yes', 'footnotes' ), - 'no' => __( 'No', 'footnotes' ), - ); - - // Load template file. - $template = new Template( Template::DASHBOARD, 'mouse-over-box-text' ); - // Replace all placeholders. - $template->replace( - array( - - 'description-delimiter' => __( 'Tooltips can display another content than the footnote entry in the reference container. The trigger is a shortcode in the footnote text separating the tooltip text from the note. That is consistent with what WordPress does for excerpts.', 'footnotes' ), - - 'label-delimiter' => $this->add_label( Settings::FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER, __( 'Delimiter for dedicated tooltip text:', 'footnotes' ) ), - 'delimiter' => $this->add_text_box( Settings::FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER ), - 'notice-delimiter' => __( 'If the delimiter shortcode is present, the tooltip text will be the part before it.', 'footnotes' ), - - 'label-mirror' => $this->add_label( Settings::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE, __( 'Mirror the tooltip in the reference container:', 'footnotes' ) ), - 'mirror' => $this->add_select_box( Settings::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE, $enabled ), - 'notice-mirror' => __( 'Tooltips may be harder to use on mobiles. This option allows to read it in the reference container.', 'footnotes' ), - - 'label-separator' => $this->add_label( Settings::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR, __( 'Separator between tooltip text and footnote text:', 'footnotes' ) ), - 'separator' => $this->add_text_box( Settings::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR ), - 'notice-separator' => __( 'May be a simple space, or a line break <br />, or any string in your language.', 'footnotes' ), - - 'description-mirror' => __( 'Tooltips, even jQuery-driven, may be hard to consult on mobiles. This option allows to read the tooltip content in the reference container too.', 'footnotes' ), - - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays style settings for the footnotes mouse-over box. - * - * @since 2.2.0 - */ - public function mouseover_box_appearance(): void { - // Options for Yes/No select box. - $enabled = array( - 'yes' => __( 'Yes', 'footnotes' ), - 'no' => __( 'No', 'footnotes' ), - ); - // Options for the font size unit. - $font_size_units = array( - 'em' => __( 'em', 'footnotes' ), - 'rem' => __( 'rem', 'footnotes' ), - 'px' => __( 'pixels', 'footnotes' ), - 'pt' => __( 'points', 'footnotes' ), - 'pc' => __( 'picas', 'footnotes' ), - 'mm' => __( 'millimeters', 'footnotes' ), - '%' => __( 'per cent', 'footnotes' ), - ); - - // Load template file. - $template = new Template( Template::DASHBOARD, 'mouse-over-box-appearance' ); - // Replace all placeholders. - $template->replace( - array( - - 'label-font-size' => $this->add_label( Settings::MOUSE_OVER_BOX_FONT_SIZE_ENABLED, __( 'Set font size:', 'footnotes' ) ), - 'font-size-enable' => $this->add_select_box( Settings::MOUSE_OVER_BOX_FONT_SIZE_ENABLED, $enabled ), - 'font-size-scalar' => $this->add_num_box( Settings::MOUSE_OVER_BOX_FONT_SIZE_SCALAR, 0, 50, true ), - 'font-size-unit' => $this->add_select_box( Settings::MOUSE_OVER_BOX_FONT_SIZE_UNIT, $font_size_units ), - 'notice-font-size' => __( 'By default, the font size is set to equal the surrounding text.', 'footnotes' ), - - 'label-color' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_COLOR, __( 'Text color:', 'footnotes' ) ), - 'color' => $this->add_color_selection( Settings::FOOTNOTES_MOUSE_OVER_BOX_COLOR ), - // Translators: %s: Clear or leave empty. - 'notice-color' => sprintf( __( 'To use the current theme\'s default text color: %s', 'footnotes' ), __( 'Clear or leave empty.', 'footnotes' ) ), - - 'label-background' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND, __( 'Background color:', 'footnotes' ) ), - 'background' => $this->add_color_selection( Settings::FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND ), - // Translators: %s: Clear or leave empty. - 'notice-background' => sprintf( __( 'To use the current theme\'s default background color: %s', 'footnotes' ), __( 'Clear or leave empty.', 'footnotes' ) ), - - 'label-border-width' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH, __( 'Border width:', 'footnotes' ) ), - 'border-width' => $this->add_num_box( Settings::FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH, 0, 4, true ), - 'notice-border-width' => __( 'pixels; 0 for borderless', 'footnotes' ), - - 'label-border-color' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR, __( 'Border color:', 'footnotes' ) ), - 'border-color' => $this->add_color_selection( Settings::FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR ), - // Translators: %s: Clear or leave empty. - 'notice-border-color' => sprintf( __( 'To use the current theme\'s default border color: %s', 'footnotes' ), __( 'Clear or leave empty.', 'footnotes' ) ), - - 'label-border-radius' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS, __( 'Rounded corner radius:', 'footnotes' ) ), - 'border-radius' => $this->add_num_box( Settings::FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS, 0, 500 ), - 'notice-border-radius' => __( 'pixels; 0 for sharp corners', 'footnotes' ), - - 'label-box-shadow-color' => $this->add_label( Settings::FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR, __( 'Box shadow color:', 'footnotes' ) ), - 'box-shadow-color' => $this->add_color_selection( Settings::FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR ), - // Translators: %s: Clear or leave empty. - 'notice-box-shadow-color' => sprintf( __( 'To use the current theme\'s default box shadow color: %s', 'footnotes' ), __( 'Clear or leave empty.', 'footnotes' ) ), - - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - - /** - * Displays all settings for the backlink symbol. - * - * @since 1.5.0 - */ - public function hyperlink_arrow(): void { - // Load template file. - $template = new Template( Template::DASHBOARD, 'customize-hyperlink-arrow' ); - // Replace all placeholders. - $template->replace( - array( - 'label-symbol' => $this->add_label( Settings::HYPERLINK_ARROW, __( 'Select or input the backlink symbol:', 'footnotes' ) ), - 'symbol-options' => $this->add_select_box( Settings::HYPERLINK_ARROW, Convert::get_arrow() ), - 'symbol-custom' => $this->add_text_box( Settings::HYPERLINK_ARROW_USER_DEFINED ), - 'notice-symbol' => __( 'Your input overrides the selection.', 'footnotes' ), - 'description-symbol' => __( 'This symbol is used in the reference container. But this setting pre-existed under this tab and cannot be moved to another one.', 'footnotes' ), - ) - ); - // Display template with replaced placeholders. - // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped - echo $template->get_content(); - // phpcs:enable - } - /** * Displays the Custom CSS box. * @@ -1218,7 +421,6 @@ class SettingsPage extends Engine { $meta_boxes = array(); $meta_boxes[] = $this->add_meta_box( 'settings', 'amp-compat', __( 'AMP compatibility', 'footnotes' ), 'amp_compat' ); - $meta_boxes[] = $this->add_meta_box( 'settings', 'start-end', __( 'Footnote start and end short codes', 'footnotes' ), 'start_end' ); $meta_boxes[] = $this->add_meta_box( 'settings', 'numbering', __( 'Footnotes numbering', 'footnotes' ), 'numbering' ); $meta_boxes[] = $this->add_meta_box( 'settings', 'scrolling', __( 'Scrolling behavior', 'footnotes' ), 'scrolling' ); $meta_boxes[] = $this->add_meta_box( 'settings', 'hard-links', __( 'URL fragment ID configuration', 'footnotes' ), 'hard_links' ); @@ -1226,7 +428,6 @@ class SettingsPage extends Engine { $meta_boxes[] = $this->add_meta_box( 'settings', 'excerpts', __( 'Footnotes in excerpts', 'footnotes' ), 'excerpts' ); $meta_boxes[] = $this->add_meta_box( 'settings', 'love', Config::PLUGIN_HEADING_NAME . ' ' . Config::LOVE_SYMBOL_HEADING, 'love' ); - $meta_boxes[] = $this->add_meta_box( 'customize', 'hyperlink-arrow', __( 'Backlink symbol', 'footnotes' ), 'hyperlink_arrow' ); $meta_boxes[] = $this->add_meta_box( 'customize', 'superscript', __( 'Referrers', 'footnotes' ), 'superscript' ); $meta_boxes[] = $this->add_meta_box( 'customize', 'label-solution', __( 'Referrers in labels', 'footnotes' ), 'label_solution' ); $meta_boxes[] = $this->add_meta_box( 'customize', 'mouse-over-box', __( 'Tooltips', 'footnotes' ), 'mouseover_box' ); diff --git a/src/includes/class-core.php b/src/includes/class-core.php index 3e57380..18a1e74 100644 --- a/src/includes/class-core.php +++ b/src/includes/class-core.php @@ -114,8 +114,9 @@ class Core { * * @since 2.8.0 */ - public function get_plugin_name(): string { - return $this->plugin_name; + public function get_plugin_name(bool $html = false): string { + if ( ! $html ) return $this->plugin_name; + else return ''; } /** diff --git a/src/includes/class-settings.php b/src/includes/class-settings.php index 0785efa..deb883e 100644 --- a/src/includes/class-settings.php +++ b/src/includes/class-settings.php @@ -32,7 +32,7 @@ use footnotes\includes\settings\customcss\CustomCSSSettingsSection; * @package footnotes * @since 1.5.0 * @since 2.8.0 Renamed class from `Footnotes_Settings` to `Settings`. - * Moved under `footnotes\includes` namespace. + * Moved under `footnotes\includes` namespace. */ class Settings { /** @@ -51,73 +51,6 @@ class Settings { 'vw' => 'viewport width', ); - /** - * Settings container key for the counter style of the footnotes. - * - * @var string - * - * @since 1.5.0 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_COUNTER_STYLE = 'footnote_inputfield_counter_style'; - - /** - * Settings container key for the backlink symbol selection. - * - * @var string - * - * @since 1.5.0 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const HYPERLINK_ARROW = 'footnote_inputfield_custom_hyperlink_symbol'; - - /** - * Settings container key for the user-defined backlink symbol. - * - * @var string - * - * @since 1.5.0 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const HYPERLINK_ARROW_USER_DEFINED = 'footnote_inputfield_custom_hyperlink_symbol_user'; - - /** - * Settings container key to look for footnotes in post excerpts. - * - * @see EXPERT_LOOKUP_THE_EXCERPT - * @var string - * - * @since 1.5.0 - * @since 2.6.3 Enabled by default. - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_IN_EXCERPT = 'footnote_inputfield_search_in_excerpt'; - - /** - * Settings container key for the string before the footnote referrer. - * - * The default footnote referrer surroundings should be square brackets, as - * in English or US American typesetting, for better UX thanks to a more - * button-like appearance, as well as for stylistic consistency with the - * expand-collapse button. - * - * @var string - * - * @since 1.5.0 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_STYLING_BEFORE = 'footnote_inputfield_custom_styling_before'; - - /** - * Settings container key for the string after the footnote referrer. - * - * @var string - * - * @since 1.5.0 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_STYLING_AFTER = 'footnote_inputfield_custom_styling_after'; - /** * Settings container key for the Custom CSS. * @@ -127,53 +60,7 @@ class Settings { * @todo Move to `SettingsSection`/`SettingsGroup`. */ const CUSTOM_CSS = 'footnote_inputfield_custom_css'; - - /** - * Settings container key for the ‘I love footnotes’ text. - * - * @var string - * - * @since 1.5.0 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_LOVE = 'footnote_inputfield_love'; - - /** - * Settings container key to enable the mouse-over box. - * - * @var string - * - * @since 1.5.2 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_MOUSE_OVER_BOX_ENABLED = 'footnote_inputfield_custom_mouse_over_box_enabled'; - - /** - * Settings container key to enable tooltip truncation. - * - * @var string - * - * @since 1.5.4 - * @todo The mouse-over content truncation should be enabled by default to raise - * awareness of the functionality, prevent the screen from being filled on - * mouse-over, and allow the use of ‘Continue Reading’ functionality. - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_ENABLED = 'footnote_inputfield_custom_mouse_over_box_excerpt_enabled'; - - /** - * Settings container key for the mouse-over box to define the max. length of - * the enabled excerpt. - * - * The default truncation length is 200 chars. - * - * @var int - * - * @since 1.5.4 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH = 'footnote_inputfield_custom_mouse_over_box_excerpt_length'; - + /** * Settings container key to enable the `the_title` hook. * @@ -243,65 +130,6 @@ class Settings { */ const EXPERT_LOOKUP_WIDGET_TEXT = 'footnote_inputfield_expert_lookup_widget_text'; - /** - * Settings container key for the mouse-over box to define the color. - * - * @var string - * - * @see FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND - * - * @since 1.5.6 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_MOUSE_OVER_BOX_COLOR = 'footnote_inputfield_custom_mouse_over_box_color'; - - /** - * Settings container key for the mouse-over box to define the background color. - * - * Theme default background color is best, but theme default background color - * doesn't seem to exist. - * - * The default is currently `#ffffff` with `#000000` as the text color. - * - * @var string - * - * @see FOOTNOTES_MOUSE_OVER_BOX_COLOR - * - * @since 1.5.6 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND = 'footnote_inputfield_custom_mouse_over_box_background'; - - /** - * Settings container key for the mouse-over box to define the border width. - * - * @var int - * - * @since 1.5.6 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH = 'footnote_inputfield_custom_mouse_over_box_border_width'; - - /** - * Settings container key for the mouse-over box to define the border color. - * - * @var string - * - * @since 1.5.6 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR = 'footnote_inputfield_custom_mouse_over_box_border_color'; - - /** - * Settings container key for the mouse-over box to define the border radius. - * - * @var int - * - * @since 1.5.6 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS = 'footnote_inputfield_custom_mouse_over_box_border_radius'; - /** * Settings container key for the mouse-over box to define the max. width. * @@ -316,88 +144,6 @@ class Settings { */ const FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH = 'footnote_inputfield_custom_mouse_over_box_max_width'; - /** - * Settings container key for the mouse-over box to define the position. - * - * The default position should not be lateral because of the risk - * the box gets squeezed between note anchor at line end and window edge, - * and top because reading at the bottom of the window is more likely. - * - * @var string - * - * @since 1.5.7 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_MOUSE_OVER_BOX_POSITION = 'footnote_inputfield_custom_mouse_over_box_position'; - - /** - * Settings container key for the mouse-over box to define the _x_-offset. - * - * @var int - * - * @since 1.5.7 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X = 'footnote_inputfield_custom_mouse_over_box_offset_x'; - - /** - * Settings container key for the mouse-over box to define the _y_-offset. - * - * The vertical offset must be negative for the box not to cover the current - * line of text. - * - * @var int - * - * @since 1.5.7 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y = 'footnote_inputfield_custom_mouse_over_box_offset_y'; - - /** - * Settings container key for the mouse-over box to define the box-shadow color. - * - * @var string - * - * @since 1.5.8 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR = 'footnote_inputfield_custom_mouse_over_box_shadow_color'; - - /** - * Settings container key for the label of the Read-on button in truncated tooltips. - * - * @var string - * - * @since 2.1.0 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_TOOLTIP_READON_LABEL = 'footnote_inputfield_readon_label'; - - /** - * Settings container key to enable the alternative tooltips. - * - * These alternative tooltips work around a website-related jQuery UI - * outage. They are low-script but use the AMP-incompatible `onmouseover` - * and `onmouseout` arguments, along with CSS transitions for fade-in/out. - * The very small script is inserted after the plugin's internal stylesheet. - * - * @var string - * - * @since 2.1.1 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE = 'footnote_inputfield_custom_mouse_over_box_alternative'; - - /** - * Settings container key for the referrer element. - * - * @var string - * - * @since 2.1.1 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_REFERRER_SUPERSCRIPT_TAGS = 'footnotes_inputfield_referrer_superscript_tags'; - /** * Settings container key to get the backlink symbol switch side. * @@ -473,80 +219,6 @@ class Settings { * @todo Move to `SettingsSection`/`SettingsGroup`. */ const EXPERT_LOOKUP_THE_EXCERPT_PRIORITY_LEVEL = 'footnote_inputfield_expert_lookup_the_excerpt_priority_level'; - - /** - * Settings container key to enable setting the tooltip font size. - * - * @var string - * - * @since 2.1.4 - * - * Tooltip font size reset to legacy by default since 2.1.4; - * Was set to inherit since 2.1.1 as it overrode custom CSS, - * Called mouse over box not tooltip for consistency. - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const MOUSE_OVER_BOX_FONT_SIZE_ENABLED = 'footnotes_inputfield_mouse_over_box_font_size_enabled'; - - /** - * Settings container key for the scalar value of the tooltip font size. - * - * @var float - * - * @since 2.1.4 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const MOUSE_OVER_BOX_FONT_SIZE_SCALAR = 'footnotes_inputfield_mouse_over_box_font_size_scalar'; - - /** - * Settings container key for the unit of the tooltip font size. - * - * @var string - * - * @since 2.1.4 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const MOUSE_OVER_BOX_FONT_SIZE_UNIT = 'footnotes_inputfield_mouse_over_box_font_size_unit'; - - /** - * Settings container key for tooltip display fade-in delay. - * - * @var int - * - * @since 2.1.4 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const MOUSE_OVER_BOX_FADE_IN_DELAY = 'footnotes_inputfield_mouse_over_box_fade_in_delay'; - - /** - * Settings container key for tooltip display fade-in duration. - * - * @var int - * - * @since 2.1.4 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const MOUSE_OVER_BOX_FADE_IN_DURATION = 'footnotes_inputfield_mouse_over_box_fade_in_duration'; - - /** - * Settings container key for tooltip display fade-out delay. - * - * @var int - * - * @since 2.1.4 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const MOUSE_OVER_BOX_FADE_OUT_DELAY = 'footnotes_inputfield_mouse_over_box_fade_out_delay'; - - /** - * Settings container key for tooltip display fade-out duration. - * - * @var int - * - * @since 2.1.4 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const MOUSE_OVER_BOX_FADE_OUT_DURATION = 'footnotes_inputfield_mouse_over_box_fade_out_duration'; /** * Settings container key for reference container position shortcode. @@ -584,201 +256,6 @@ class Settings { */ const CUSTOM_CSS_LEGACY_ENABLE = 'footnote_inputfield_custom_css_legacy_enable'; - /** - * Settings container key for alternative tooltip position. - * - * Fixed-width is for alternative tooltips, cannot reuse `max-width` nor offsets. - * - * @var string - * - * @since 2.2.5 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_POSITION = 'footnotes_inputfield_alternative_mouse_over_box_position'; - - /** - * Settings container key for alternative tooltip _x_-offset. - * - * @var int - * - * @since 2.2.5 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_X = 'footnotes_inputfield_alternative_mouse_over_box_offset_x'; - - /** - * Settings container key for alternative tooltip _y_-offset. - * - * @var int - * - * @since 2.2.5 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_Y = 'footnotes_inputfield_alternative_mouse_over_box_offset_y'; - - /** - * Settings container key for alternative tooltip width. - * - * @var int - * - * @since 2.2.5 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH = 'footnotes_inputfield_alternative_mouse_over_box_width'; - - /** - * Settings container key to enable hard links. - * - * When the alternative reference container is enabled, hard links are too. - * - * @var string - * - * @since 2.3.0 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_HARD_LINKS_ENABLE = 'footnotes_inputfield_hard_links_enable'; - - /** - * Settings container key for the fragment ID slug in referrers. - * - * @var string - * - * @since 2.3.0 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const REFERRER_FRAGMENT_ID_SLUG = 'footnotes_inputfield_referrer_fragment_id_slug'; - - /** - * Settings container key for the fragment ID slug in footnotes. - - * @var string - * - * @since 2.3.0 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTE_FRAGMENT_ID_SLUG = 'footnotes_inputfield_footnote_fragment_id_slug'; - - /** - * Settings container key for the ID separator in fragment IDs. - * - * @var string - * - * @since 2.3.0 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const HARD_LINK_IDS_SEPARATOR = 'footnotes_inputfield_hard_link_ids_separator'; - - /** - * Settings container key to enable backlink tooltips. - * - * When hard links are enabled, clicks on the backlinks are logged in the - * browsing history, along with clicks on the referrers. - * This tooltip hints to use the backbutton instead, so the history gets - * streamlined again. - * See {@link https://wordpress.org/support/topic/making-it-amp-compatible/#post-13837359 - * here} for more information. - * - * @var string - * - * @since 2.5.4 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_BACKLINK_TOOLTIP_ENABLE = 'footnotes_inputfield_backlink_tooltip_enable'; - - /** - * Settings container key to configure the backlink tooltip. - * - * @var string - * - * @since 2.5.4 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_BACKLINK_TOOLTIP_TEXT = 'footnotes_inputfield_backlink_tooltip_text'; - - /** - * Settings container key to configure the tooltip excerpt delimiter. - * - * The first implementation used a fixed shortcode provided in the changelog, - * but footnotes should have freely-configurable shortcodes. - * - * Tooltips can display another content than the footnote entry in the - * reference container. The trigger is a shortcode in the footnote text - * separating the tooltip text from the note. That is consistent with what - * WordPress does for excerpts. - * - * @var string - * - * @since 2.5.4 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER = 'footnotes_inputfield_tooltip_excerpt_delimiter'; - - /** - * Settings container key to enable mirroring the tooltip excerpt in the - * reference container. - * - * Tooltips, even jQuery-driven, may be hard to consult on mobiles. - * This option allows users to read the tooltip content in the reference - * container too. See {@link https://wordpress.org/support/topic/change-tooltip-text/#post-13935050 - * here} for more information, and {@link https://wordpress.org/support/topic/change-tooltip-text/#post-13935488 - * here} for why this must not be the default behavior. - * - * @var string - * - * @since 2.5.4 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE = 'footnotes_inputfield_tooltip_excerpt_mirror_enable'; - - /** - * Settings container key to configure the tooltip excerpt separator in the - * reference container. - * - * @var string - * - * @since 2.5.4 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR = 'footnotes_inputfield_tooltip_excerpt_mirror_separator'; - - /** - * Settings container key to enable superscript style normalization. - * - * @var string - * - * @since 2.5.4 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT = 'footnotes_inputfield_referrers_normal_superscript'; - - /** - * Settings container key to enable AMP compatibility mode. - * - * @var string - * - * @since 2.6.0 - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_AMP_COMPATIBILITY_ENABLE = 'footnotes_inputfield_amp_compatibility_enable'; - - /** - * Settings container key to set the solution of the input element label issue. - * - * If hard links are not enabled, clicking a referrer in an input element label - * toggles the state of the input element the label is connected to. - * Beside hard links, other solutions include moving footnotes off the label and - * append them, or disconnecting this label from the input element (discouraged). - * See {@link https://wordpress.org/support/topic/compatibility-issue-with-wpforms/#post-14212318 - * here} for more information. - * - * @var string - * - * @since 2.5.12 - * @todo Review, remove? - * @todo Move to `SettingsSection`/`SettingsGroup`. - */ - const FOOTNOTES_LABEL_ISSUE_SOLUTION = 'footnotes_inputfield_label_issue_solution'; - /** * Contains all Settings option group slugs. * @@ -805,94 +282,13 @@ class Settings { * @since 2.8.0 Rename from `default` to `default_settings`. * @deprecated * - * @todo Delete. + * @todo Delete once moved to `SettingsSection`/`SettingsGroup`s. */ private array $default_settings = array( - - // General settings. - 'footnotes_storage' => array( - - // AMP compatibility. - self::FOOTNOTES_AMP_COMPATIBILITY_ENABLE => '', - - // Footnotes numbering. - self::FOOTNOTES_COUNTER_STYLE => 'arabic_plain', - //self::COMBINE_IDENTICAL_FOOTNOTES => 'yes', - - self::FOOTNOTES_HARD_LINKS_ENABLE => 'no', - self::REFERRER_FRAGMENT_ID_SLUG => 'r', - self::FOOTNOTE_FRAGMENT_ID_SLUG => 'f', - self::HARD_LINK_IDS_SEPARATOR => '+', - self::FOOTNOTES_BACKLINK_TOOLTIP_ENABLE => 'yes', - self::FOOTNOTES_BACKLINK_TOOLTIP_TEXT => 'Alt+ ←', - - // Footnotes in excerpts. - self::FOOTNOTES_IN_EXCERPT => 'manual', - - // Footnotes love. - self::FOOTNOTES_LOVE => 'no', - ), - + // Referrers and tooltips. 'footnotes_storage_custom' => array( - - // Backlink symbol. - self::HYPERLINK_ARROW => 0, - self::HYPERLINK_ARROW_USER_DEFINED => '', - - // Referrers. - self::FOOTNOTES_REFERRER_SUPERSCRIPT_TAGS => 'yes', - self::FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT => 'no', - self::FOOTNOTES_STYLING_BEFORE => '[', - self::FOOTNOTES_STYLING_AFTER => ']', - - // Referrers in labels. - self::FOOTNOTES_LABEL_ISSUE_SOLUTION => 'none', - - // Tooltips. - self::FOOTNOTES_MOUSE_OVER_BOX_ENABLED => 'yes', - self::FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE => 'no', - - // Tooltip position. - self::FOOTNOTES_MOUSE_OVER_BOX_POSITION => 'top center', - self::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_POSITION => 'top right', - self::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X => 0, - self::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_X => -50, - self::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y => -7, - self::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_Y => 24, - - // Tooltip dimensions. - self::FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH => 450, - self::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH => 400, - - // Tooltip timing. - self::MOUSE_OVER_BOX_FADE_IN_DELAY => 0, - self::MOUSE_OVER_BOX_FADE_IN_DURATION => 200, - self::MOUSE_OVER_BOX_FADE_OUT_DELAY => 400, - self::MOUSE_OVER_BOX_FADE_OUT_DURATION => 200, - - // Tooltip truncation. - self::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_ENABLED => 'yes', - self::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH => 200, - self::FOOTNOTES_TOOLTIP_READON_LABEL => 'Continue reading', - - // Tooltip text. - self::FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER => '[[/tooltip]]', - self::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE => 'no', - self::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR => ' — ', - - // Tooltip appearance. - self::MOUSE_OVER_BOX_FONT_SIZE_ENABLED => 'yes', - self::MOUSE_OVER_BOX_FONT_SIZE_SCALAR => 13, - self::MOUSE_OVER_BOX_FONT_SIZE_UNIT => 'px', - - self::FOOTNOTES_MOUSE_OVER_BOX_COLOR => '#000000', - self::FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND => '#ffffff', - self::FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH => 1, - self::FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR => '#cccc99', - self::FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS => 0, - self::FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR => '#666666', - + // Your existing Custom CSS code. self::CUSTOM_CSS => '', @@ -940,7 +336,7 @@ class Settings { * @since 1.5.0 * @deprecated * - * @todo Delete. + * @todo Delete once all `SettingsSection`/`SettingsGroup`s set up. */ public array $settings = array(); @@ -1072,7 +468,6 @@ class Settings { return false; } - protected function load_options_group(): void { $options_group = get_option($this->options_group_slug); @@ -1131,6 +526,7 @@ class Settings { // Return a singleton of this class. return self::$instance; } + /** * Loads all settings from each option group. * diff --git a/src/includes/settings/class-settings-group.php b/src/includes/settings/class-settings-group.php index 24fcc84..9a2865b 100644 --- a/src/includes/settings/class-settings-group.php +++ b/src/includes/settings/class-settings-group.php @@ -26,7 +26,16 @@ abstract class SettingsGroup { * * @since 2.8.0 */ - const GROUP_ID = ''; + const GROUP_ID = 'undefined'; + + /** + * Setting group name. + * + * @var string + * + * @since 2.8.0 + */ + const GROUP_NAME = 'undefined'; /** * The setting classes. @@ -105,7 +114,7 @@ abstract class SettingsGroup { } } - public function add_settings_fields(Layout\SettingsPage $component): void { + public function add_settings_fields(Layout\SettingsPage $component): void { foreach ($this->settings as $setting) { add_settings_field( $setting->key, diff --git a/src/includes/settings/general/class-amp-compat-settings-group.php b/src/includes/settings/general/class-amp-compat-settings-group.php new file mode 100644 index 0000000..766e8c5 --- /dev/null +++ b/src/includes/settings/general/class-amp-compat-settings-group.php @@ -0,0 +1,73 @@ + 'footnotes_inputfield_amp_compatibility_enable', + 'name' => 'Enable AMP compatibility mode', + 'description' => 'The official AMP-WP plugin is required when this option is enabled. This option enables hard links with configurable scroll offset in % viewport height.', + 'default_value' => false, + 'type' => 'boolean', + 'input_type' => 'checkbox', + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::FOOTNOTES_AMP_COMPATIBILITY_ENABLE['key'] => $this->add_setting( self::FOOTNOTES_AMP_COMPATIBILITY_ENABLE ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/general/class-excerpts-settings-group.php b/src/includes/settings/general/class-excerpts-settings-group.php new file mode 100644 index 0000000..62668d5 --- /dev/null +++ b/src/includes/settings/general/class-excerpts-settings-group.php @@ -0,0 +1,75 @@ + 'footnote_inputfield_search_in_excerpt', + 'name' => 'Process Footnotes in Excerpts', + 'default_value' => 'manual', + 'type' => 'string', + 'input_type' => 'select', + 'input_options' => array( + 'yes' => 'Yes, generate excerpts from posts with effectively processed footnotes and other markup', + 'no' => 'No, generate excerpts from posts but remove all footnotes and output plain text', + 'manual' => 'Yes but run the process only to display tooltips in manual excerpts with footnote short codes' + ), + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::FOOTNOTES_IN_EXCERPT['key'] => $this->add_setting( self::FOOTNOTES_IN_EXCERPT ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/general/class-general-settings-section.php b/src/includes/settings/general/class-general-settings-section.php index 6efd62e..4c52fda 100644 --- a/src/includes/settings/general/class-general-settings-section.php +++ b/src/includes/settings/general/class-general-settings-section.php @@ -16,6 +16,11 @@ use footnotes\includes\settings\SettingsSection; use footnotes\includes\settings\general\ReferenceContainerSettingsGroup; use footnotes\includes\settings\general\ScrollingSettingsGroup; use footnotes\includes\settings\general\ShortcodeSettingsGroup; +use footnotes\includes\settings\general\NumberingSettingsGroup; +use footnotes\includes\settings\general\HardLinksSettingsGroup; +use footnotes\includes\settings\general\LoveSettingsGroup; +use footnotes\includes\settings\general\ExcerptsSettingsGroup; +use footnotes\includes\settings\general\AMPCompatSettingsGroup; /** * Class defining general plugin settings. @@ -55,13 +60,23 @@ class GeneralSettingsSection extends SettingsSection { require_once plugin_dir_path( __DIR__ ) . 'general/class-reference-container-settings-group.php'; require_once plugin_dir_path( __DIR__ ) . 'general/class-scrolling-settings-group.php'; require_once plugin_dir_path( __DIR__ ) . 'general/class-shortcode-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'general/class-numbering-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'general/class-hard-links-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'general/class-love-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'general/class-excerpts-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'general/class-amp-compat-settings-group.php'; } protected function add_settings_groups(): void { $this->settings_groups = array( + AMPCompatSettingsGroup::GROUP_ID => new AMPCompatSettingsGroup( $this->options_group_slug, $this->section_slug ), ReferenceContainerSettingsGroup::GROUP_ID => new ReferenceContainerSettingsGroup( $this->options_group_slug, $this->section_slug ), ScrollingSettingsGroup::GROUP_ID => new ScrollingSettingsGroup( $this->options_group_slug, $this->section_slug ), ShortcodeSettingsGroup::GROUP_ID => new ShortcodeSettingsGroup( $this->options_group_slug, $this->section_slug ), + NumberingSettingsGroup::GROUP_ID => new NumberingSettingsGroup( $this->options_group_slug, $this->section_slug ), + HardLinksSettingsGroup::GROUP_ID => new HardLinksSettingsGroup( $this->options_group_slug, $this->section_slug ), + ExcerptsSettingsGroup::GROUP_ID => new ExcerptsSettingsGroup( $this->options_group_slug, $this->section_slug ), + LoveSettingsGroup::GROUP_ID => new LoveSettingsGroup( $this->options_group_slug, $this->section_slug ), ); } } diff --git a/src/includes/settings/general/class-hard-links-settings-group.php b/src/includes/settings/general/class-hard-links-settings-group.php new file mode 100644 index 0000000..a62f3e2 --- /dev/null +++ b/src/includes/settings/general/class-hard-links-settings-group.php @@ -0,0 +1,166 @@ + 'footnotes_inputfield_hard_links_enable', + 'name' => 'Enable Hard Links', + 'description' => 'Hard links disable jQuery delays but have the same scroll offset, and allow to share footnotes (accessed if the list is not collapsed by default).', + 'default_value' => false, + 'type' => 'boolean', + 'input_type' => 'checkbox', + ); + + /** + * Settings container key for the fragment ID slug in referrers. + * + * @var array + * + * @since 2.3.0 + * @since 2.8.0 Move from `Settings` to `HardLinksSettingsGroup`. + * Convert from `string` to `array`. + */ + const REFERRER_FRAGMENT_ID_SLUG = array( + 'key' => 'footnotes_inputfield_referrer_fragment_id_slug', + 'name' => 'Fragment Identifier Slug for Footnote Referrers', + 'description' => 'This will show up in the address bar after clicking on a hard-linked backlink.', + 'default_value' => 'r', + 'type' => 'string', + 'input_type' => 'text', + ); + + /** + * Settings container key for the fragment ID slug in footnotes. + * + * @var array + * + * @since 2.3.0 + * @since 2.8.0 Move from `Settings` to `HardLinksSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTE_FRAGMENT_ID_SLUG = array( + 'key' => 'footnotes_inputfield_footnote_fragment_id_slug', + 'name' => 'Fragment Identifier Slug for Footnotes', + 'description' => 'This will show up in the address bar after clicking on a hard-linked footnote referrer.', + 'default_value' => 'f', + 'type' => 'string', + 'input_type' => 'text', + ); + + /** + * Settings container key for the ID separator in fragment IDs. + * + * @var array + * + * @since 2.3.0 + * @since 2.8.0 Move from `Settings` to `HardLinksSettingsGroup`. + * Convert from `string` to `array`. + */ + const HARD_LINK_IDS_SEPARATOR = array( + 'key' => 'footnotes_inputfield_hard_link_ids_separator', + 'name' => 'ID Separator', + 'description' => 'May be empty or any string, for example _, - or +, to distinguish post number, container number and footnote number.', + 'default_value' => '+', + 'type' => 'string', + 'input_type' => 'text', + ); + + /** + * Settings container key to enable backlink tooltips. + * + * When hard links are enabled, clicks on the backlinks are logged in the + * browsing history, along with clicks on the referrers. + * This tooltip hints to use the backbutton instead, so the history gets + * streamlined again. + * See {@link https://wordpress.org/support/topic/making-it-amp-compatible/#post-13837359 + * here} for more information. + * + * @var array + * + * @since 2.5.4 + * @since 2.8.0 Move from `Settings` to `HardLinksSettingsGroup`. + * Convert from `string` to `array`. + * Convert setting data type from `string` to `boolean`. + */ + const FOOTNOTES_BACKLINK_TOOLTIP_ENABLE = array( + 'key' => 'footnotes_inputfield_backlink_tooltip_enable', + 'name' => 'Enable Backlink Tooltips', + 'description' => 'Hard backlinks get ordinary tooltips hinting to use the backbutton instead to keep it usable.', + 'default_value' => true, + 'type' => 'boolean', + 'input_type' => 'checkbox', + ); + + /** + * Settings container key to configure the backlink tooltip. + * + * @var array + * + * @since 2.5.4 + * @since 2.8.0 Move from `Settings` to `HardLinksSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_BACKLINK_TOOLTIP_TEXT = array( + 'key' => 'footnotes_inputfield_backlink_tooltip_text', + 'name' => 'Backlink Tooltip Text', + 'description' => 'Default text is the keyboard shortcut; may be a localized descriptive hint.', + 'default_value' => 'Alt + ←', + 'type' => 'string', + 'input_type' => 'text', + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::FOOTNOTES_HARD_LINKS_ENABLE['key'] => $this->add_setting( self::FOOTNOTES_HARD_LINKS_ENABLE ), + self::REFERRER_FRAGMENT_ID_SLUG['key'] => $this->add_setting( self::REFERRER_FRAGMENT_ID_SLUG ), + self::FOOTNOTE_FRAGMENT_ID_SLUG['key'] => $this->add_setting( self::FOOTNOTE_FRAGMENT_ID_SLUG ), + self::HARD_LINK_IDS_SEPARATOR['key'] => $this->add_setting( self::HARD_LINK_IDS_SEPARATOR ), + self::FOOTNOTES_BACKLINK_TOOLTIP_ENABLE['key'] => $this->add_setting( self::FOOTNOTES_BACKLINK_TOOLTIP_ENABLE ), + self::FOOTNOTES_BACKLINK_TOOLTIP_TEXT['key'] => $this->add_setting( self::FOOTNOTES_BACKLINK_TOOLTIP_TEXT ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/general/class-love-settings-group.php b/src/includes/settings/general/class-love-settings-group.php new file mode 100644 index 0000000..9a1a067 --- /dev/null +++ b/src/includes/settings/general/class-love-settings-group.php @@ -0,0 +1,111 @@ +♥'; + const PLUGIN_SYMBOL = ''; + + /** + * Setting group ID. + * + * @var string + * + * @since 2.8.0 + */ + const GROUP_ID = 'love'; + + /** + * Setting group name. + * + * @var string + * + * @since 2.8.0 + */ + const GROUP_NAME = self::LOVE_SYMBOL . ' Love'; + + /** + * Settings container key for the ‘I love footnotes’ text. + * + * @var array + * + * @since 1.5.0 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_LOVE = array( + 'key' => 'footnote_inputfield_love', + 'name' => 'Tell the world you\'re using the plugin!', + 'default_value' => 'no', + 'type' => 'string', + 'input_type' => 'select', + 'input_options' => array( + // Logo only. + 'text-3' => self::PLUGIN_SYMBOL, + // Logo followed by heart symbol. + 'text-4' => self::PLUGIN_SYMBOL . ' ' . self::LOVE_SYMBOL, + // Logo preceded by heart symbol. + 'text-5' => self::LOVE_SYMBOL . ' ' . self::PLUGIN_SYMBOL, + // Translators: 2: heart symbol 1: footnotes logogram. + 'text-1' => 'I ' . self::LOVE_SYMBOL . ' ' . self::PLUGIN_SYMBOL, + // Translators: %s: Footnotes plugin logo. + 'text-6' => 'This website uses ' . self::PLUGIN_SYMBOL, + // Translators: %s: Footnotes plugin logo. + 'text-7' => 'This website uses the ' . self::PLUGIN_SYMBOL . ' plugin', + // Translators: %s: Footnotes plugin logo. + 'text-2' => 'This website uses the awesome ' . self::PLUGIN_SYMBOL . ' plugin', + 'random' => 'randomly determined display of either mention', + // Translators: 1: Plugin logo.2: heart symbol. + 'no' => 'no display of any mention in the footer', + ), + ); + + /** + * Settings container key for the shortcode to NOT display the ‘LOVE ME’ slug + * on certain pages. + * + * @var array + * + * @since 1.5.0 + * @since 2.8.0 Move from `Config` to `ReferenceContainerSettingsGroup`. + * Rename from `NO_LOVE_SLUG` to `FOOTNOTES_NO_LOVE_SLUG`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_NO_LOVE_SLUG = array( + 'key' => 'footnote_inputfield_no_love_slug', + 'name' => 'Shortcode to inhibit the display of the ' . self::PLUGIN_SYMBOL . ' mention on specific pages', + 'default_value' => '[[no footnotes: love]]', + 'type' => 'string', + 'input_type' => 'text', + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::FOOTNOTES_LOVE['key'] => $this->add_setting( self::FOOTNOTES_LOVE ), + self::FOOTNOTES_NO_LOVE_SLUG['key'] => $this->add_setting( self::FOOTNOTES_NO_LOVE_SLUG ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/general/class-numbering-settings-group.php b/src/includes/settings/general/class-numbering-settings-group.php new file mode 100644 index 0000000..4c43922 --- /dev/null +++ b/src/includes/settings/general/class-numbering-settings-group.php @@ -0,0 +1,90 @@ + 'footnote_inputfield_combine_identical', + 'name' => 'Combine Identical Footnotes', + 'description' => 'This option may require copy-pasting footnotes in multiple instances. Even when footnotes are combined, footnote numbers keep incrementing. This avoids suboptimal referrer and backlink disambiguation using a secondary numbering system. The Ibid. notation and the op. cit. abbreviation followed by the current page number avoid repeating the footnote content. For changing sources, shortened citations may be used. Repeating full citations is also an opportunity to add details.', + 'default_value' => true, + 'type' => 'boolean', + 'input_type' => 'checkbox', + ); + + /** + * Settings container key for the counter style of the footnotes. + * + * @var array + * + * @since 1.5.0 + * @since 2.8.0 Move from `Settings` to `NumberingSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_COUNTER_STYLE = array( + 'key' => 'footnote_inputfield_counter_style', + 'name' => 'Numbering Style', + 'default_value' => 'arabic_plain', + 'type' => 'string', + 'input_type' => 'select', + 'input_options' => array( + 'arabic_plain' => 'plain Arabic numbers (1, 2, 3, 4, 5, …)', + 'arabic_leading' => 'zero-padded Arabic numbers (01, 02, 03, 04, 05, …)', + 'latin_low' => 'lowercase Latin letters (a, b, c, d, e, …)', + 'latin_high' => 'uppercase Latin letters (A, B, C, D, E, …)', + 'romanic' => 'uppercase Roman numerals (I, II, III, IV, V, …)', + 'roman_low' => 'lowercase Roman numerals (i, ii, iii, iv, v, …)', + ), + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::COMBINE_IDENTICAL_FOOTNOTES['key'] => $this->add_setting( self::COMBINE_IDENTICAL_FOOTNOTES ), + self::FOOTNOTES_COUNTER_STYLE['key'] => $this->add_setting( self::FOOTNOTES_COUNTER_STYLE ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/general/class-reference-container-settings-group.php b/src/includes/settings/general/class-reference-container-settings-group.php index 7962164..7c0a867 100644 --- a/src/includes/settings/general/class-reference-container-settings-group.php +++ b/src/includes/settings/general/class-reference-container-settings-group.php @@ -32,24 +32,6 @@ class ReferenceContainerSettingsGroup extends SettingsGroup { */ const GROUP_ID = 'reference-container'; - /** - * Settings container key for combining identical footnotes. - * - * @var array - * - * @since 1.5.0 - * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. - * Convert from `string` to `array`. - * Convert setting data type from `string` to `boolean`. - */ - const COMBINE_IDENTICAL_FOOTNOTES = array( - 'key' => 'footnote_inputfield_combine_identical', - 'name' => 'Combine Identical Footnotes', - 'default_value' => true, - 'type' => 'boolean', - 'input_type' => 'checkbox', - ); - /** * Settings container key for the label of the reference container. * @@ -731,7 +713,6 @@ class ReferenceContainerSettingsGroup extends SettingsGroup { protected function add_settings( array|false $options ): void { $this->settings = array( self::REFERENCE_CONTAINER_NAME['key'] => $this->add_setting( self::REFERENCE_CONTAINER_NAME ), - self::COMBINE_IDENTICAL_FOOTNOTES['key'] => $this->add_setting( self::COMBINE_IDENTICAL_FOOTNOTES ), self::REFERENCE_CONTAINER_NAME['key'] => $this->add_setting( self::REFERENCE_CONTAINER_NAME ), self::REFERENCE_CONTAINER_LABEL_ELEMENT['key'] => $this->add_setting( self::REFERENCE_CONTAINER_LABEL_ELEMENT ), self::REFERENCE_CONTAINER_LABEL_BOTTOM_BORDER['key'] => $this->add_setting( self::REFERENCE_CONTAINER_LABEL_BOTTOM_BORDER ), diff --git a/src/includes/settings/referrers-and-tooltips/class-backlink-symbol-settings-group.php b/src/includes/settings/referrers-and-tooltips/class-backlink-symbol-settings-group.php new file mode 100644 index 0000000..e05a2c0 --- /dev/null +++ b/src/includes/settings/referrers-and-tooltips/class-backlink-symbol-settings-group.php @@ -0,0 +1,92 @@ + 'footnote_inputfield_custom_hyperlink_symbol', + 'name' => 'Select the Backlink Symbol', + 'description' => 'This symbol is used in the reference container. But this setting pre-existed under this tab and cannot be moved to another one.', + 'default_value' => 0, + 'type' => 'string', + 'input_type' => 'select', + 'input_options' => array( + '↑', + '↥', + '↟', + '↩', + '↲', + '↵', + '⇑', + '⇡', + '⇧', + '↑' + ), + //'overridden_by' => self::HYPERLINK_ARROW_USER_DEFINED, + ); + + /** + * Settings container key for the user-defined backlink symbol. + * + * @var array + * + * @since 1.5.0 + * @since 2.8.0 Move from `Settings` to `BacklinkSymbolSettingsGroup`. + * Convert from `string` to `array`. + */ + const HYPERLINK_ARROW_USER_DEFINED = array( + 'key' => 'footnote_inputfield_custom_hyperlink_symbol_user', + 'name' => 'Input the Backlink Symbol', + 'description' => 'Your input overrides the selection.', + 'type' => 'string', + 'input_type' => 'text', + 'enabled_by' => self::HYPERLINK_ARROW + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::HYPERLINK_ARROW['key'] => $this->add_setting( self::HYPERLINK_ARROW ), + self::HYPERLINK_ARROW_USER_DEFINED['key'] => $this->add_setting( self::HYPERLINK_ARROW_USER_DEFINED ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/referrers-and-tooltips/class-referrers-and-tooltips-settings-section.php b/src/includes/settings/referrers-and-tooltips/class-referrers-and-tooltips-settings-section.php index 653fbad..508e792 100644 --- a/src/includes/settings/referrers-and-tooltips/class-referrers-and-tooltips-settings-section.php +++ b/src/includes/settings/referrers-and-tooltips/class-referrers-and-tooltips-settings-section.php @@ -14,9 +14,6 @@ require_once plugin_dir_path( __DIR__ ) . 'class-settings-section.php'; use footnotes\includes\settings\SettingsSection; -// Import settings groups. -//use footnotes\includes\settings\referrers-and-tooltips\...; - /** * Class defining plugin referrer and tooltips settings. * @@ -52,13 +49,30 @@ class ReferrersAndTooltipsSettingsSection extends SettingsSection { protected function load_dependencies(): void { parent::load_dependencies(); - //require_once plugin_dir_path( __DIR__ ) . 'general/class-reference-container-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'referrers-and-tooltips/class-backlink-symbol-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'referrers-and-tooltips/class-referrers-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'referrers-and-tooltips/class-referrers-in-labels-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'referrers-and-tooltips/class-tooltips-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'referrers-and-tooltips/class-tooltip-appearance-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'referrers-and-tooltips/class-tooltip-dimensions-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'referrers-and-tooltips/class-tooltip-position-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'referrers-and-tooltips/class-tooltip-text-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'referrers-and-tooltips/class-tooltip-timing-settings-group.php'; + require_once plugin_dir_path( __DIR__ ) . 'referrers-and-tooltips/class-tooltip-truncation-settings-group.php'; } protected function add_settings_groups(): void { $this->settings_groups = array ( - // Add settings groups. - //...::GROUP_ID => new ...($this->options_group_slug, $this->section_slug), + BacklinkSymbolSettingsGroup::GROUP_ID => new BacklinkSymbolSettingsGroup( $this->options_group_slug, $this->section_slug ), + ReferrersSettingsGroup::GROUP_ID => new ReferrersSettingsGroup( $this->options_group_slug, $this->section_slug ), + ReferrersInLabelsSettingsGroup::GROUP_ID => new ReferrersInLabelsSettingsGroup( $this->options_group_slug, $this->section_slug ), + TooltipsSettingsGroup::GROUP_ID => new TooltipsSettingsGroup( $this->options_group_slug, $this->section_slug ), + TooltipAppearanceSettingsGroup::GROUP_ID => new TooltipAppearanceSettingsGroup( $this->options_group_slug, $this->section_slug ), + TooltipDimensionsSettingsGroup::GROUP_ID => new TooltipDimensionsSettingsGroup( $this->options_group_slug, $this->section_slug ), + TooltipPositionSettingsGroup::GROUP_ID => new TooltipPositionSettingsGroup( $this->options_group_slug, $this->section_slug ), + TooltipTextSettingsGroup::GROUP_ID => new TooltipTextSettingsGroup( $this->options_group_slug, $this->section_slug ), + TooltipTimingSettingsGroup::GROUP_ID => new TooltipTimingSettingsGroup( $this->options_group_slug, $this->section_slug ), + TooltipTruncationSettingsGroup::GROUP_ID => new TooltipTruncationSettingsGroup( $this->options_group_slug, $this->section_slug ), ); } } diff --git a/src/includes/settings/referrers-and-tooltips/class-referrers-in-labels-settings-group.php b/src/includes/settings/referrers-and-tooltips/class-referrers-in-labels-settings-group.php new file mode 100644 index 0000000..2263ec1 --- /dev/null +++ b/src/includes/settings/referrers-and-tooltips/class-referrers-in-labels-settings-group.php @@ -0,0 +1,73 @@ + 'footnotes_inputfield_label_issue_solution', + 'name' => 'Solve Input Label Issue', + 'description' => 'Clicking a footnote referrer in an input element label toggles the input except when hard links are enabled. In jQuery mode, the recommended solution is to move footnotes and append them after the label (option A). Option B is discouraged because disconnecting a label from its input element may compromise accessibility. This option is a last resort in case footnotes must absolutely stay inside the label. (Using jQuery \'event.stopPropagation\' failed.', + 'default_value' => 'none', + 'type' => 'string', + 'input_type' => 'select', + 'input_options' => array( + 'none' => '0. No problem or solved otherwise', + 'move' => 'A. Footnotes are moved out and appended after the label\'s end (recommended)', + 'disconnect' => 'B. Labels with footnotes are disconnected from input element (discouraged)' + ), + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::FOOTNOTES_LABEL_ISSUE_SOLUTION['key'] => $this->add_setting( self::FOOTNOTES_LABEL_ISSUE_SOLUTION ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/referrers-and-tooltips/class-referrers-settings-group.php b/src/includes/settings/referrers-and-tooltips/class-referrers-settings-group.php new file mode 100644 index 0000000..3db9c2a --- /dev/null +++ b/src/includes/settings/referrers-and-tooltips/class-referrers-settings-group.php @@ -0,0 +1,145 @@ + 'footnotes_inputfield_referrer_superscript_tags', + 'name' => 'Display Footnote Referrers in Superscript', + 'default_value' => true, + 'type' => 'boolean', + 'input_type' => 'checkbox', + ); + + /** + * Settings container key to enable superscript style normalization. + * + * @var array + * + * @since 2.5.4 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT = array( + 'key' => 'footnotes_inputfield_referrers_normal_superscript', + 'name' => 'Normalize Vertical Alignment and Font Size', + 'description' => 'Most themes don\'t need this fix.', + 'default_value' => 'no', + 'type' => 'string', + 'input_type' => 'select', + 'input_options' => array( + 'no' => 'No', + 'referrers' => 'Footnote referrers', + 'all' => 'All superscript elements' + ), + ); + + /** + * Settings container key for the string before the footnote referrer. + * + * The default footnote referrer surroundings should be square brackets, as + * in English or US American typesetting, for better UX thanks to a more + * button-like appearance, as well as for stylistic consistency with the + * expand-collapse button. + * + * @var array + * + * @since 1.5.0 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_STYLING_BEFORE = array( + 'key' => 'footnote_inputfield_custom_styling_before', + 'name' => 'At the Start of the Footnote Referrers', + 'default_value' => '[', + 'type' => 'string', + 'input_type' => 'text', + ); + + /** + * Settings container key for the string after the footnote referrer. + * + * @var array + * + * @since 1.5.0 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_STYLING_AFTER = array( + 'key' => 'footnotes_inputfield_referrers_normal_superscript', + 'name' => 'At the End of the Footnote Referrers', + 'default_value' => ']', + 'type' => 'string', + 'input_type' => 'text', + ); + + /** + * Settings container key + * + * @var array + * + * @since 2.1.4 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + * Convert setting data type from `string` to `boolean`. + */ + const LINK_ELEMENT_ENABLED = array( + 'key' => 'footnote_inputfield_link_element_enabled', + 'name' => 'Use the Link Element for Referrers and Backlinks', + 'description' => 'Please find this setting at the end of the reference container settings. The link element is needed to apply the theme\'s link color.', + 'default_value' => true, + 'type' => 'boolean', + 'input_type' => 'checkbox', + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::FOOTNOTES_REFERRER_SUPERSCRIPT_TAGS['key'] => $this->add_setting( self::FOOTNOTES_REFERRER_SUPERSCRIPT_TAGS ), + self::FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT['key'] => $this->add_setting( self::FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT ), + self::FOOTNOTES_STYLING_BEFORE['key'] => $this->add_setting( self::FOOTNOTES_STYLING_BEFORE ), + self::FOOTNOTES_STYLING_AFTER['key'] => $this->add_setting( self::FOOTNOTES_STYLING_AFTER ), + self::LINK_ELEMENT_ENABLED['key'] => $this->add_setting( self::LINK_ELEMENT_ENABLED ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/referrers-and-tooltips/class-tooltip-appearance-settings-group.php b/src/includes/settings/referrers-and-tooltips/class-tooltip-appearance-settings-group.php new file mode 100644 index 0000000..b981160 --- /dev/null +++ b/src/includes/settings/referrers-and-tooltips/class-tooltip-appearance-settings-group.php @@ -0,0 +1,236 @@ + 'footnotes_inputfield_mouse_over_box_font_size_enabled', + 'name' => 'Set Font Size', + 'description' => '', + 'default_value' => '', + 'type' => 'boolean', + 'input_type' => 'checkbox', + ); + + /** + * Settings container key for the scalar value of the tooltip font size. + * + * @var array + * + * @since 2.1.4 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const MOUSE_OVER_BOX_FONT_SIZE_SCALAR = array( + 'key' => 'footnotes_inputfield_mouse_over_box_font_size_scalar', + 'name' => 'Font Size', + 'description' => 'By default, the font size is set to equal the surrounding text.', + 'default_value' => 13, + 'type' => 'number', + 'input_type' => 'number', + 'input_max' => 50, + 'input_min' => 0 + ); + + /** + * Settings container key for the unit of the tooltip font size. + * + * @var array + * + * @since 2.1.4 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const MOUSE_OVER_BOX_FONT_SIZE_UNIT = array( + 'key' => 'footnotes_inputfield_mouse_over_box_font_size_unit', + 'name' => 'Font Size Unit', + 'default_value' => 'px', + 'type' => 'string', + 'input_type' => 'select', + 'input_options' => array( + 'em' => 'em', + 'rem' => 'rem', + 'px' => 'pixels', + 'pt' => 'points', + 'pc' => 'picas', + 'mm' => 'millimeters', + '%' => 'per cent', + ), + ); + + /** + * Settings container key for the mouse-over box to define the color. + * + * @var array + * + * @since 1.5.6 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_MOUSE_OVER_BOX_COLOR = array( + 'key' => 'footnote_inputfield_custom_mouse_over_box_color', + 'name' => 'Text Color', + 'description' => 'To use the current theme\'s default text color, clear or leave empty', + 'default_value' => '#000000', + 'type' => 'string', + 'input_type' => 'color', + ); + + /** + * Settings container key for the mouse-over box to define the background color. + * + * Theme default background color is best, but theme default background color + * doesn't seem to exist. + * + * The default is currently `#ffffff` with `#000000` as the text color. + * + * @var array + * + * @since 1.5.6 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND = array( + 'key' => 'footnote_inputfield_custom_mouse_over_box_background', + 'name' => 'Background Color', + 'description' => 'To use the current theme\'s default background color, clear or leave empty', + 'default_value' => '#ffffff', + 'type' => 'string', + 'input_type' => 'color', + ); + + /** + * Settings container key for the mouse-over box to define the border width. + * + * @var array + * + * @since 1.5.6 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH = array( + 'key' => 'footnote_inputfield_custom_mouse_over_box_border_width', + 'name' => 'Border Width', + 'description' => 'pixels; 0 for borderless', + 'default_value' => 1, + 'type' => 'number', + 'input_type' => 'number', + 'input_max' => 4, + 'input_min' => 0, + ); + + /** + * Settings container key for the mouse-over box to define the border color. + * + * @var array + * + * @since 1.5.6 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR = array( + 'key' => 'footnote_inputfield_custom_mouse_over_box_border_color', + 'name' => 'Border Color', + 'description' => 'To use the current theme\'s default border color, clear or leave empty', + 'default_value' => '#ffffff', + 'type' => 'string', + 'input_type' => 'color', + ); + + /** + * Settings container key for the mouse-over box to define the border radius. + * + * @var array + * + * @since 1.5.6 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS = array( + 'key' => 'footnote_inputfield_custom_mouse_over_box_border_radius', + 'name' => 'Rounded Corner Radius', + 'description' => 'pixels; 0 for sharp corners', + 'default_value' => 0, + 'type' => 'number', + 'input_type' => 'number', + 'input_max' => 500, + 'input_min' => 0, + ); + + /** + * Settings container key for the mouse-over box to define the box-shadow color. + * + * @var array + * + * @since 1.5.8 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR = array( + 'key' => 'footnote_inputfield_custom_mouse_over_box_shadow_color', + 'name' => 'Box Shadow Color', + 'description' => 'To use the current theme\'s default box shadow color, clear or leave empty', + 'default_value' => '#666666', + 'type' => 'string', + 'input_type' => 'color', + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::MOUSE_OVER_BOX_FONT_SIZE_ENABLED['key'] => $this->add_setting( self::MOUSE_OVER_BOX_FONT_SIZE_ENABLED ), + self::MOUSE_OVER_BOX_FONT_SIZE_SCALAR['key'] => $this->add_setting( self::MOUSE_OVER_BOX_FONT_SIZE_SCALAR ), + self::MOUSE_OVER_BOX_FONT_SIZE_UNIT['key'] => $this->add_setting( self::MOUSE_OVER_BOX_FONT_SIZE_UNIT ), + self::FOOTNOTES_MOUSE_OVER_BOX_COLOR['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_COLOR ), + self::FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND ), + self::FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH ), + self::FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR ), + self::FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS ), + self::FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/referrers-and-tooltips/class-tooltip-dimensions-settings-group.php b/src/includes/settings/referrers-and-tooltips/class-tooltip-dimensions-settings-group.php new file mode 100644 index 0000000..34d5528 --- /dev/null +++ b/src/includes/settings/referrers-and-tooltips/class-tooltip-dimensions-settings-group.php @@ -0,0 +1,79 @@ + 'footnote_inputfield_custom_mouse_over_box_max_width', + 'name' => 'Maximum Width', + 'description' => 'pixels; set to 0 for jQuery tooltips without max width', + 'default_value' => 450, + 'type' => 'number', + 'input_type' => 'number', + ); + + /** + * Settings container key for alternative tooltip width. + * + * @var array + * + * @since 2.2.5 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH = array( + 'key' => 'footnotes_inputfield_alternative_mouse_over_box_width', + 'name' => 'Maximum Width (alternative tooltips)', + 'default_value' => 400, + 'type' => 'number', + 'input_type' => 'number', + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH ), + self::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH['key'] => $this->add_setting( self::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/referrers-and-tooltips/class-tooltip-position-settings-group.php b/src/includes/settings/referrers-and-tooltips/class-tooltip-position-settings-group.php new file mode 100644 index 0000000..69aca0c --- /dev/null +++ b/src/includes/settings/referrers-and-tooltips/class-tooltip-position-settings-group.php @@ -0,0 +1,179 @@ + 'footnote_inputfield_custom_mouse_over_box_position', + 'name' => 'Position', + 'description' => 'The second column of settings boxes is for the alternative tooltips.', + 'default_value' => 'top center', + 'type' => 'string', + 'input_type' => 'select', + 'input_options' => array( + 'top left' => 'top left', + 'top center' => 'top center', + 'top right' => 'top right', + 'center right' => 'center right', + 'bottom right' => 'bottom right', + 'bottom center' => 'bottom center', + 'bottom left' => 'bottom left', + 'center left' => 'center left', + ), + ); + + /** + * Settings container key for alternative tooltip position. + * + * Fixed-width is for alternative tooltips, cannot reuse `max-width` nor offsets. + * + * @var array + * + * @since 2.2.5 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_POSITION = array( + 'key' => 'footnotes_inputfield_alternative_mouse_over_box_position', + 'name' => 'Position (alternative Tooltips)', + 'default_value' => 'top right', + 'type' => 'string', + 'input_type' => 'select', + 'input_options' => array( + 'top left' => 'top left', + 'top right' => 'top right', + 'bottom right' => 'bottom right', + 'bottom left' => 'bottom left', + ), + ); + + /** + * Settings container key for the mouse-over box to define the _x_-offset. + * + * @var array + * + * @since 1.5.7 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X = array( + 'key' => 'footnote_inputfield_custom_mouse_over_box_offset_x', + 'name' => 'Horizontal Offset', + 'description' => 'pixels; negative value for a leftwards offset; alternative tooltips: direction depends on position', + 'default_value' => 0, + 'type' => 'number', + 'input_type' => 'number', + ); + + /** + * Settings container key for alternative tooltip _x_-offset. + * + * @var array + * + * @since 2.2.5 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_X = array( + 'key' => 'footnotes_inputfield_alternative_mouse_over_box_offset_x', + 'name' => 'Horizontal Offset (alternative tooltips)', + 'description' => 'pixels; negative value for a leftwards offset; alternative tooltips: direction depends on position', + 'default_value' => -50, + 'type' => 'number', + 'input_type' => 'number', + ); + + /** + * Settings container key for the mouse-over box to define the _y_-offset. + * + * The vertical offset must be negative for the box not to cover the current + * line of text. + * + * @var array + * + * @since 1.5.7 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y = array( + 'key' => 'footnote_inputfield_custom_mouse_over_box_offset_y', + 'name' => 'Vertical Offset', + 'description' => 'pixels; negative value for an upwards offset; alternative tooltips: direction depends on position', + 'default_value' => -7, + 'type' => 'number', + 'input_type' => 'number', + ); + + /** + * Settings container key for alternative tooltip _y_-offset. + * + * @var array + * + * @since 2.5.5 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_Y = array( + 'key' => 'footnotes_inputfield_alternative_mouse_over_box_offset_y', + 'name' => 'Vertical Offset (alternative tooltips)', + 'description' => 'pixels; negative value for an upwards offset; alternative tooltips: direction depends on position', + 'default_value' => 24, + 'type' => 'number', + 'input_type' => 'number', + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::FOOTNOTES_MOUSE_OVER_BOX_POSITION['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_POSITION ), + self::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_POSITION['key'] => $this->add_setting( self::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_POSITION ), + self::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X ), + self::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_X['key'] => $this->add_setting( self::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_X ), + self::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y ), + self::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_Y['key'] => $this->add_setting( self::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_Y ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/referrers-and-tooltips/class-tooltip-text-settings-group.php b/src/includes/settings/referrers-and-tooltips/class-tooltip-text-settings-group.php new file mode 100644 index 0000000..6401bb6 --- /dev/null +++ b/src/includes/settings/referrers-and-tooltips/class-tooltip-text-settings-group.php @@ -0,0 +1,115 @@ + 'footnotes_inputfield_tooltip_excerpt_delimiter', + 'name' => 'Delimiter for Dedicated Tooltip Text', + 'description' => 'Tooltips can display another content than the footnote entry in the reference container. The trigger is a shortcode in the footnote text separating the tooltip text from the note. That is consistent with what WordPress does for excerpts. If the delimiter shortcode is present, the tooltip text will be the part before it.', + 'default_value' => '[[/tooltip]]', + 'type' => 'string', + 'input_type' => 'text', + ); + + /** + * Settings container key to enable mirroring the tooltip excerpt in the + * reference container. + * + * Tooltips, even jQuery-driven, may be hard to consult on mobiles. + * This option allows users to read the tooltip content in the reference + * container too. See {@link https://wordpress.org/support/topic/change-tooltip-text/#post-13935050 + * here} for more information, and {@link https://wordpress.org/support/topic/change-tooltip-text/#post-13935488 + * here} for why this must not be the default behavior. + * + * @var array + * + * @since 2.5.4 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + * Convert setting data type from `string` to `boolean`. + */ + const FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE = array( + 'key' => 'footnotes_inputfield_tooltip_excerpt_mirror_enable', + 'name' => 'Mirror the Tooltip in the Reference Container', + 'description' => 'Tooltips may be harder to use on mobiles. This option allows to read it in the reference container. Tooltips, even jQuery-driven, may be hard to consult on mobiles. This option allows to read the tooltip content in the reference container too.', + 'default_value' => 'false', + 'type' => 'boolean', + 'input_type' => 'checkbox', + ); + + /** + * Settings container key to configure the tooltip excerpt separator in the + * reference container. + * + * @var array + * + * @since 2.5.4 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR = array( + 'key' => 'footnotes_inputfield_tooltip_excerpt_mirror_separator', + 'name' => 'Separator Between Tooltip Text and Footnote Text', + 'description' => 'May be a simple space, or a line break <br />, or any string in your language.', + 'default_value' => ' — ', + 'type' => 'string', + 'input_type' => 'text', + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER['key'] => $this->add_setting( self::FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER ), + self::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE['key'] => $this->add_setting( self::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE ), + self::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR['key'] => $this->add_setting( self::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/referrers-and-tooltips/class-tooltip-timing-settings-group.php b/src/includes/settings/referrers-and-tooltips/class-tooltip-timing-settings-group.php new file mode 100644 index 0000000..6e7de20 --- /dev/null +++ b/src/includes/settings/referrers-and-tooltips/class-tooltip-timing-settings-group.php @@ -0,0 +1,125 @@ + 'footnotes_inputfield_mouse_over_box_fade_in_delay', + 'name' => 'Fade-in Delay', + 'description' => 'milliseconds', + 'default_value' => 0, + 'type' => 'number', + 'input_type' => 'number', + 'input_max' => 20000, + 'input_min' => 0, + ); + + /** + * Settings container key for tooltip display fade-in duration. + * + * @var array + * + * @since 2.1.4 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const MOUSE_OVER_BOX_FADE_IN_DURATION = array( + 'key' => 'footnotes_inputfield_mouse_over_box_fade_in_duration', + 'name' => 'Fade-in Duration', + 'description' => 'milliseconds', + 'default_value' => 200, + 'type' => 'number', + 'input_type' => 'number', + 'input_max' => 20000, + 'input_min' => 0, + ); + + /** + * Settings container key for tooltip display fade-out delay. + * + * @var array + * + * @since 2.1.4 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const MOUSE_OVER_BOX_FADE_OUT_DELAY = array( + 'key' => 'footnotes_inputfield_mouse_over_box_fade_out_delay', + 'name' => 'Fade-out Delay', + 'description' => 'milliseconds', + 'default_value' => 400, + 'type' => 'number', + 'input_type' => 'number', + 'input_max' => 20000, + 'input_min' => 0, + ); + + /** + * Settings container key for tooltip display fade-out duration. + * + * @var array + * + * @since 2.1.4 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const MOUSE_OVER_BOX_FADE_OUT_DURATION = array( + 'key' => 'footnotes_inputfield_mouse_over_box_fade_out_duration', + 'name' => 'Fade-out Duration', + 'description' => 'milliseconds', + 'default_value' => 200, + 'type' => 'number', + 'input_type' => 'number', + 'input_max' => 20000, + 'input_min' => 0, + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::MOUSE_OVER_BOX_FADE_IN_DELAY['key'] => $this->add_setting( self::MOUSE_OVER_BOX_FADE_IN_DELAY ), + self::MOUSE_OVER_BOX_FADE_IN_DURATION['key'] => $this->add_setting( self::MOUSE_OVER_BOX_FADE_IN_DURATION ), + self::MOUSE_OVER_BOX_FADE_OUT_DELAY['key'] => $this->add_setting( self::MOUSE_OVER_BOX_FADE_OUT_DELAY ), + self::MOUSE_OVER_BOX_FADE_OUT_DURATION['key'] => $this->add_setting( self::MOUSE_OVER_BOX_FADE_OUT_DURATION ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/referrers-and-tooltips/class-tooltip-truncation-settings-group.php b/src/includes/settings/referrers-and-tooltips/class-tooltip-truncation-settings-group.php new file mode 100644 index 0000000..442fa34 --- /dev/null +++ b/src/includes/settings/referrers-and-tooltips/class-tooltip-truncation-settings-group.php @@ -0,0 +1,105 @@ + 'footnote_inputfield_custom_mouse_over_box_excerpt_enabled', + 'name' => 'Truncate the Note in the Tooltip', + 'default_value' => true, + 'type' => 'boolean', + 'input_type' => 'checkbox', + ); + + /** + * Settings container key for the mouse-over box to define the max. length of + * the enabled excerpt. + * + * The default truncation length is 200 chars. + * + * @var array + * + * @since 1.5.4 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH = array( + 'key' => 'footnote_inputfield_custom_mouse_over_box_excerpt_length', + 'name' => 'Maximum Number of Characters in the Tooltip', + 'description' => 'No weird cuts.', + 'default_value' => 200, + 'type' => 'number', + 'input_type' => 'number', + 'input_max' => 10000, + 'input_min' => 3, + ); + + /** + * Settings container key for the label of the Read-on button in truncated tooltips. + * + * @var array + * + * @since 2.1.0 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + */ + const FOOTNOTES_TOOLTIP_READON_LABEL = array( + 'key' => 'footnote_inputfield_readon_label', + 'name' => '\'Read on\' Button Label', + 'default_value' => 'Continue reading', + 'type' => 'string', + 'input_type' => 'text', + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_ENABLED['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_ENABLED ), + self::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH ), + self::FOOTNOTES_TOOLTIP_READON_LABEL['key'] => $this->add_setting( self::FOOTNOTES_TOOLTIP_READON_LABEL ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/includes/settings/referrers-and-tooltips/class-tooltips-settings-group.php b/src/includes/settings/referrers-and-tooltips/class-tooltips-settings-group.php new file mode 100644 index 0000000..c58b20b --- /dev/null +++ b/src/includes/settings/referrers-and-tooltips/class-tooltips-settings-group.php @@ -0,0 +1,86 @@ + 'footnote_inputfield_custom_mouse_over_box_enabled', + 'name' => 'Display Tooltips', + 'description' => 'Formatted text boxes allowing hyperlinks, displayed on mouse-over or tap and hold.', + 'default_value' => true, + 'type' => 'boolean', + 'input_type' => 'checkbox', + ); + + /** + * Settings container key to enable the alternative tooltips. + * + * These alternative tooltips work around a website-related jQuery UI + * outage. They are low-script but use the AMP-incompatible `onmouseover` + * and `onmouseout` arguments, along with CSS transitions for fade-in/out. + * The very small script is inserted after the plugin's internal stylesheet. + * + * @var array + * + * @since 2.1.1 + * @since 2.8.0 Move from `Settings` to `ReferenceContainerSettingsGroup`. + * Convert from `string` to `array`. + * Convert setting data type from `string` to `boolean`. + */ + const FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE = array( + 'key' => 'footnote_inputfield_custom_mouse_over_box_alternative', + 'name' => 'Display Alternative Tooltips', + 'description' => 'Intended to work around a configuration-related tooltip outage. These alternative tooltips work around a website related jQuery UI outage. They are low-script but use the AMP incompatible onmouseover and onmouseout arguments, along with CSS transitions for fade-in/out. The very small script is inserted after Footnotes\' internal stylesheet. When this option is enabled, footnotes does not load jQuery UI nor jQuery Tools.', + 'default_value' => false, + 'type' => 'boolean', + 'input_type' => 'checkbox', + ); + + protected function add_settings( array|false $options ): void { + $this->settings = array( + self::FOOTNOTES_MOUSE_OVER_BOX_ENABLED['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_ENABLED ), + self::FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE['key'] => $this->add_setting( self::FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE ), + ); + + $this->load_values( $options ); + } +} diff --git a/src/public/class-general.php b/src/public/class-general.php index b67db93..a3421da 100644 --- a/src/public/class-general.php +++ b/src/public/class-general.php @@ -11,13 +11,16 @@ declare(strict_types=1); namespace footnotes\general; require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/settings/general/class-reference-container-settings-group.php'; +require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/settings/general/class-scrolling-settings-group.php'; use footnotes\includes\{Footnotes, Convert, Settings}; -use const footnotes\includes\settings\general\ReferenceContainerSettingsGroup\{ - FOOTNOTES_REFERENCE_CONTAINER_SCRIPT_MODE, - FOOTNOTES_PAGE_LAYOUT_SUPPORT -}; +/** + * @todo Replace with constant imports. + */ +use footnotes\includes\settings\general\ReferenceContainerSettingsGroup; +use footnotes\includes\settings\general\AMPCompatSettingsGroup; +use footnotes\includes\settings\referrersandtooltips\TooltipsSettingsGroup; /** * Class provide all public-facing functionality of the plugin. @@ -125,10 +128,10 @@ class General { $this->load_dependencies(); // Set conditions re-used for stylesheet enqueuing and in class/task.php. - self::$amp_enabled = Convert::to_bool( Settings::instance()->get( Settings::FOOTNOTES_AMP_COMPATIBILITY_ENABLE ) ); - self::$tooltips_enabled = Convert::to_bool( Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_ENABLED ) ); - self::$alternative_tooltips_enabled = Convert::to_bool( Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE ) ); - self::$script_mode = Settings::instance()->get( 'foo'/*FOOTNOTES_REFERENCE_CONTAINER_SCRIPT_MODE*/ ); + self::$amp_enabled = Settings::instance()->get_setting( AMPCompatSettingsGroup::FOOTNOTES_AMP_COMPATIBILITY_ENABLE['key'] )->get_value(); + self::$tooltips_enabled = Settings::instance()->get_setting( TooltipsSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_ENABLED['key'] )->get_value(); + self::$alternative_tooltips_enabled = Settings::instance()->get_setting( TooltipsSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_ALTERNATIVE['key'] )->get_value(); + self::$script_mode = Settings::instance()->get_setting( ReferenceContainerSettingsGroup::FOOTNOTES_REFERENCE_CONTAINER_SCRIPT_MODE['key'] ); } /** @@ -155,7 +158,7 @@ class General { $this->task = new Parser(); } - + /** * Register the stylesheets for the public-facing side of the site. * diff --git a/src/public/class-parser.php b/src/public/class-parser.php index 5d103a1..b6c64f8 100644 --- a/src/public/class-parser.php +++ b/src/public/class-parser.php @@ -14,37 +14,30 @@ declare(strict_types=1); namespace footnotes\general; use footnotes\includes\{Settings, Convert, Template}; -use const footnotes\includes\settings\general\ReferenceContainerSettingsGroup\{ - COMBINE_IDENTICAL_FOOTNOTES, - REFERENCE_CONTAINER_NAME, - REFERENCE_CONTAINER_LABEL_ELEMENT, - REFERENCE_CONTAINER_LABEL_BOTTOM_BORDER, - REFERENCE_CONTAINER_COLLAPSE, - REFERENCE_CONTAINER_START_PAGE_ENABLE, - REFERENCE_CONTAINER_TOP_MARGIN, - REFERENCE_CONTAINER_BOTTOM_MARGIN, - REFERENCE_CONTAINER_ROW_BORDERS_ENABLE, - BACKLINKS_COLUMN_WIDTH_ENABLED, - BACKLINKS_COLUMN_WIDTH_SCALAR, - BACKLINKS_COLUMN_WIDTH_UNIT, - BACKLINKS_COLUMN_MAX_WIDTH_ENABLED, - BACKLINKS_COLUMN_MAX_WIDTH_SCALAR, - BACKLINKS_COLUMN_MAX_WIDTH_UNIT, - REFERENCE_CONTAINER_POSITION, - FOOTNOTE_SECTION_SHORTCODE, - REFERENCE_CONTAINER_POSITION_SHORTCODE, - FOOTNOTE_URL_WRAP_ENABLED, - LINK_ELEMENT_ENABLED, - REFERENCE_CONTAINER_BACKLINK_SYMBOL_ENABLE, - REFERENCE_CONTAINER_BACKLINK_SYMBOL_SWITCH, - BACKLINKS_SEPARATOR_ENABLED, - BACKLINKS_SEPARATOR_OPTION, - BACKLINKS_SEPARATOR_CUSTOM, - BACKLINKS_TERMINATOR_ENABLED, - BACKLINKS_TERMINATOR_OPTION, - BACKLINKS_TERMINATOR_CUSTOM, - REFERENCE_CONTAINER_3COLUMN_LAYOUT_ENABLE, - BACKLINKS_LINE_BREAKS_ENABLED + +/** + * @todo Replace with constant imports. + */ +use footnotes\includes\settings\general\{ + ExcerptsSettingsGroup, + HardLinksSettingsGroup, + LoveSettingsGroup, + NumberingSettingsGroup, + ReferenceContainerSettingsGroup, + ScrollingSettingsGroup, + ShortcodeSettingsGroup, +}; +use footnotes\includes\settings\referrersandtooltips\{ + BacklinkSymbolSettingsGroup, + ReferrersSettingsGroup, + ReferrersInLabelsSettingsGroup, + TooltipsSettingsGroup, + TooltipAppearanceSettingsGroup, + TooltipDimensionsSettingsGroup, + TooltipPositionSettingsGroup, + TooltipTextSettingsGroup, + TooltipTimingSettingsGroup, + TooltipTruncationSettingsGroup }; /** @@ -441,7 +434,7 @@ class Parser { * * Native smooth scrolling only works in recent browsers. */ - if ( Convert::to_bool( Settings::instance()->get( Settings::FOOTNOTES_CSS_SMOOTH_SCROLLING ) ) ) { + if ( Settings::instance()->get_setting( ScrollingSettingsGroup::FOOTNOTES_CSS_SMOOTH_SCROLLING['key'] )->get_value() ) { echo "html {scroll-behavior: smooth;}\r\n"; } @@ -451,7 +444,7 @@ class Parser { * Cannot be included in external stylesheet, as it is only optional. * The scope is variable too: referrers only, or all superscript elements. */ - $normalize_superscript = Settings::instance()->get( Settings::FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT ); + $normalize_superscript = Settings::instance()->get_setting( ReferrersSettingsGroup::FOOTNOTE_REFERRERS_NORMAL_SUPERSCRIPT['key'] )->get_value(); if ( 'no' !== $normalize_superscript ) { if ( 'all' === $normalize_superscript ) { echo 'sup {'; @@ -462,14 +455,14 @@ class Parser { } // Reference container display on home page. - if ( ! Convert::to_bool( Settings::instance()->get( REFERENCE_CONTAINER_START_PAGE_ENABLE['key'] ) ) ) { + if ( ! ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_START_PAGE_ENABLE['key'] )->get_value() ) ) { echo ".home .footnotes_reference_container { display: none; }\r\n"; } // Reference container top and bottom margins. - $reference_container_top_margin = (int) Settings::instance()->get( REFERENCE_CONTAINER_TOP_MARGIN['key'] ); - $reference_container_bottom_margin = (int) Settings::instance()->get( REFERENCE_CONTAINER_BOTTOM_MARGIN['key'] ); + $reference_container_top_margin = (int) Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_TOP_MARGIN['key'] )->get_value(); + $reference_container_bottom_margin = (int) Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_BOTTOM_MARGIN['key'] )->get_value(); echo '.footnotes_reference_container {margin-top: '; echo empty( $reference_container_top_margin ) ? '0' : $reference_container_top_margin; echo 'px !important; margin-bottom: '; @@ -477,9 +470,9 @@ class Parser { echo "px !important;}\r\n"; // Reference container label bottom border. - if ( Convert::to_bool( Settings::instance()->get( REFERENCE_CONTAINER_LABEL_BOTTOM_BORDER['key'] ) ) ) { + if ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_LABEL_BOTTOM_BORDER['key'] )->get_value() ) ) { echo '.footnote_container_prepare > '; - echo Settings::instance()->get( REFERENCE_CONTAINER_LABEL_ELEMENT ); + echo Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_LABEL_ELEMENT['key'] )->get_value() ; echo " {border-bottom: 1px solid #aaaaaa !important;}\r\n"; } @@ -492,7 +485,7 @@ class Parser { * issues as browsers won’t reload these style sheets after settings are * changed while the version string is not. */ - if ( Convert::to_bool( Settings::instance()->get( REFERENCE_CONTAINER_ROW_BORDERS_ENABLE['key'] ) ) ) { + if ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_ROW_BORDERS_ENABLE['key'] )->get_value() ) ) { echo '.footnotes_table, .footnotes_plugin_reference_row {'; echo 'border: 1px solid #060606;'; echo " !important;}\r\n"; @@ -502,16 +495,16 @@ class Parser { } // Ref container first column width and max-width. - $column_width_enabled = Convert::to_bool( Settings::instance()->get( BACKLINKS_COLUMN_WIDTH_ENABLED['key'] ) ); - $column_max_width_enabled = Convert::to_bool( Settings::instance()->get( BACKLINKS_COLUMN_MAX_WIDTH_ENABLED['key'] ) ); + $column_width_enabled = ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::BACKLINKS_COLUMN_WIDTH_ENABLED['key'] )->get_value() ); + $column_max_width_enabled = ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::BACKLINKS_COLUMN_MAX_WIDTH_ENABLED['key'] )->get_value() ); if ( $column_width_enabled || $column_max_width_enabled ) { echo '.footnote-reference-container { table-layout: fixed; }'; echo '.footnote_plugin_index, .footnote_plugin_index_combi {'; if ( $column_width_enabled ) { - $column_width_scalar = Settings::instance()->get( BACKLINKS_COLUMN_WIDTH_SCALAR['key'] ); - $column_width_unit = Settings::instance()->get( BACKLINKS_COLUMN_WIDTH_UNIT['key'] ); + $column_width_scalar = Settings::instance()->get_setting( ReferenceContainerSettingsGroup::BACKLINKS_COLUMN_WIDTH_SCALAR['key'] )->get_value(); + $column_width_unit = Settings::instance()->get_setting( ReferenceContainerSettingsGroup::BACKLINKS_COLUMN_WIDTH_UNIT['key'] )->get_value(); if ( ! empty( $column_width_scalar ) ) { if ( '%' === $column_width_unit && $column_width_scalar > 100 ) { @@ -525,8 +518,8 @@ class Parser { } if ( $column_max_width_enabled ) { - $column_max_width_scalar = Settings::instance()->get( BACKLINKS_COLUMN_MAX_WIDTH_SCALAR['key'] ); - $column_max_width_unit = Settings::instance()->get( BACKLINKS_COLUMN_MAX_WIDTH_UNIT['key'] ); + $column_max_width_scalar = Settings::instance()->get_setting( ReferenceContainerSettingsGroup::BACKLINKS_COLUMN_MAX_WIDTH_SCALAR['key'] )->get_value(); + $column_max_width_unit = Settings::instance()->get_setting( ReferenceContainerSettingsGroup::BACKLINKS_COLUMN_MAX_WIDTH_UNIT['key'] )->get_value(); if ( ! empty( $column_max_width_scalar ) ) { if ( '%' === $column_max_width_unit && $column_max_width_scalar > 100 ) { @@ -543,14 +536,14 @@ class Parser { } // Hard links scroll offset. - self::$hard_links_enabled = Convert::to_bool( Settings::instance()->get( Settings::FOOTNOTES_HARD_LINKS_ENABLE ) ); + self::$hard_links_enabled = Settings::instance()->get_setting( HardLinksSettingsGroup::FOOTNOTES_HARD_LINKS_ENABLE['key'] )->get_value(); // Correct hard links enabled status depending on AMP-compatible or alternative reference container enabled status. if ( General::$amp_enabled || 'jquery' !== General::$script_mode ) { self::$hard_links_enabled = true; } - self::$scroll_offset = (int) Settings::instance()->get( Settings::FOOTNOTES_SCROLL_OFFSET ); + self::$scroll_offset = (int)Settings::instance()->get_setting( ScrollingSettingsGroup::FOOTNOTES_SCROLL_OFFSET['key'] )->get_value(); if ( self::$hard_links_enabled ) { echo '.footnote_referrer_anchor, .footnote_item_anchor {bottom: '; echo self::$scroll_offset; @@ -563,46 +556,46 @@ class Parser { // Tooltip appearance: Tooltip font size. echo ' font-size: '; - if ( Convert::to_bool( Settings::instance()->get( Settings::MOUSE_OVER_BOX_FONT_SIZE_ENABLED ) ) ) { - echo Settings::instance()->get( Settings::MOUSE_OVER_BOX_FONT_SIZE_SCALAR ); - echo Settings::instance()->get( Settings::MOUSE_OVER_BOX_FONT_SIZE_UNIT ); + if ( Settings::instance()->get_setting( TooltipAppearanceSettingsGroup::MOUSE_OVER_BOX_FONT_SIZE_ENABLED['key'] )->get_value() ) { + echo Settings::instance()->get_setting( TooltipAppearanceSettingsGroup::MOUSE_OVER_BOX_FONT_SIZE_SCALAR['key'] )->get_value(); + echo Settings::instance()->get_setting( TooltipAppearanceSettingsGroup::MOUSE_OVER_BOX_FONT_SIZE_UNIT['key'] )->get_value(); } else { echo 'inherit'; } echo ' !important;'; // Tooltip Text color. - $color = Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_COLOR ); + $color = Settings::instance()->get_setting( TooltipAppearanceSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_COLOR['key'] )->get_value(); if ( ! empty( $color ) ) { printf( ' color: %s !important;', $color ); } // Tooltip Background color. - $background = Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND ); + $background = Settings::instance()->get_setting( TooltipAppearanceSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_BACKGROUND['key'] )->get_value(); if ( ! empty( $background ) ) { printf( ' background-color: %s !important;', $background ); } // Tooltip Border width. - $border_width = Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH ); + $border_width = Settings::instance()->get_setting( TooltipAppearanceSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_BORDER_WIDTH['key'] )->get_value(); if ( ! empty( $border_width ) && (int) $border_width > 0 ) { printf( ' border-width: %dpx !important; border-style: solid !important;', $border_width ); } // Tooltip Border color. - $border_color = Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR ); + $border_color = Settings::instance()->get_setting( TooltipAppearanceSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_BORDER_COLOR['key'] )->get_value(); if ( ! empty( $border_color ) ) { printf( ' border-color: %s !important;', $border_color ); } // Tooltip Corner radius. - $border_radius = Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS ); + $border_radius = Settings::instance()->get_setting( TooltipAppearanceSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_BORDER_RADIUS['key'] )->get_value(); if ( ! empty( $border_radius ) && (int) $border_radius > 0 ) { printf( ' border-radius: %dpx !important;', $border_radius ); } // Tooltip Shadow color. - $box_shadow_color = Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR ); + $box_shadow_color = Settings::instance()->get_setting( TooltipAppearanceSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_SHADOW_COLOR['key'] )->get_value(); if ( ! empty( $box_shadow_color ) ) { printf( ' -webkit-box-shadow: 2px 2px 11px %s;', $box_shadow_color ); printf( ' -moz-box-shadow: 2px 2px 11px %s;', $box_shadow_color ); @@ -616,7 +609,7 @@ class Parser { * * Position and timing of jQuery tooltips are script-defined. */ - $max_width = Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH ); + $max_width = Settings::instance()->get_setting( TooltipDimensionsSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_MAX_WIDTH['key'] )->get_value(); if ( ! empty( $max_width ) && (int) $max_width > 0 ) { printf( ' max-width: %dpx !important;', $max_width ); } @@ -627,7 +620,7 @@ class Parser { echo "}\r\n"; // Dimensions. - $alternative_tooltip_width = (int) Settings::instance()->get( Settings::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH ); + $alternative_tooltip_width = (int) Settings::instance()->get_setting( TooltipDimensionsSettingsGroup::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_WIDTH['key'] )->get_value(); echo '.footnote_tooltip.position {'; echo ' width: max-content; '; @@ -635,8 +628,8 @@ class Parser { echo ' max-width: ' . $alternative_tooltip_width . 'px;'; // Position. - $alternative_position = Settings::instance()->get( Settings::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_POSITION ); - $offset_x = (int) Settings::instance()->get( Settings::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_X ); + $alternative_position = Settings::instance()->get_setting( TooltipPositionSettingsGroup::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_POSITION['key'] )->get_value(); + $offset_x = (int) Settings::instance()->get_setting( TooltipPositionSettingsGroup::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_X['key'] )->get_value(); if ( 'top left' === $alternative_position || 'bottom left' === $alternative_position ) { echo ' right: ' . ( empty( $offset_x ) ? 0 : $offset_x ) . 'px;'; @@ -644,7 +637,7 @@ class Parser { echo ' left: ' . ( empty( $offset_x ) ? 0 : $offset_x ) . 'px;'; } - $offset_y = (int) Settings::instance()->get( Settings::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_Y ); + $offset_y = (int) Settings::instance()->get_setting( TooltipPositionSettingsGroup::FOOTNOTES_ALTERNATIVE_MOUSE_OVER_BOX_OFFSET_Y['key'] )->get_value(); if ( 'top left' === $alternative_position || 'top right' === $alternative_position ) { echo ' bottom: ' . ( empty( $offset_y ) ? 0 : $offset_y ) . 'px;'; @@ -654,13 +647,13 @@ class Parser { echo "}\r\n"; // Timing. - $fade_in_delay = (int) Settings::instance()->get( Settings::MOUSE_OVER_BOX_FADE_IN_DELAY ); + $fade_in_delay = Settings::instance()->get_setting( TooltipTimingSettingsGroup::MOUSE_OVER_BOX_FADE_IN_DELAY['key'] )->get_value(); $fade_in_delay = empty( $fade_in_delay ) ? '0' : $fade_in_delay; - $fade_in_duration = (int) Settings::instance()->get( Settings::MOUSE_OVER_BOX_FADE_IN_DURATION ); + $fade_in_duration = Settings::instance()->get_setting( TooltipTimingSettingsGroup::MOUSE_OVER_BOX_FADE_IN_DURATION['key'] )->get_value(); $fade_in_duration = empty( $fade_in_duration ) ? '0' : $fade_in_duration; - $fade_out_delay = (int) Settings::instance()->get( Settings::MOUSE_OVER_BOX_FADE_OUT_DELAY ); + $fade_out_delay = Settings::instance()->get_setting( TooltipTimingSettingsGroup::MOUSE_OVER_BOX_FADE_OUT_DELAY['key'] )->get_value(); $fade_out_delay = empty( $fade_out_delay ) ? '0' : $fade_out_delay; - $fade_out_duration = (int) Settings::instance()->get( Settings::MOUSE_OVER_BOX_FADE_OUT_DURATION ); + $fade_out_duration = Settings::instance()->get_setting( TooltipTimingSettingsGroup::MOUSE_OVER_BOX_FADE_OUT_DURATION['key'] )->get_value(); $fade_out_duration = empty( $fade_out_duration ) ? '0' : $fade_out_duration; /* @@ -743,11 +736,11 @@ class Parser { * @since 1.5.0 */ public function footnotes_output_footer(): void { - if ( 'footer' === Settings::instance()->get( REFERENCE_CONTAINER_POSITION['key'] ) ) { + if ( 'footer' === Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_POSITION['key'] )->get_value() ) { echo $this->reference_container(); } // Get setting for love and share this plugin. - $love_me_index = Settings::instance()->get( Settings::FOOTNOTES_LOVE ); + $love_me_index = Settings::instance()->get_setting( LoveSettingsGroup::FOOTNOTES_LOVE['key'] )->get_value(); // Check if the admin allows to add a link to the footer. if ( empty( $love_me_index ) || 'no' === strtolower( $love_me_index ) || ! self::$allow_love_me ) { return; @@ -816,8 +809,8 @@ class Parser { */ public function footnotes_in_content( string $content ): string { - $ref_container_position = Settings::instance()->get( REFERENCE_CONTAINER_POSITION['key'] ); - $footnote_section_shortcode = Settings::instance()->get( FOOTNOTE_SECTION_SHORTCODE['key'] ); + $ref_container_position = Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_POSITION['key'] )->get_value(); + $footnote_section_shortcode = Settings::instance()->get_setting( ReferenceContainerSettingsGroup::FOOTNOTE_SECTION_SHORTCODE['key'] )->get_value(); $footnote_section_shortcode_length = strlen( $footnote_section_shortcode ); // TODO: Replace with `str_contains()`, but currently breaks Rector downgrade. @@ -865,7 +858,7 @@ class Parser { * @return string $excerpt Processed or new excerpt. */ public function footnotes_in_excerpt( string $excerpt ): string { - $excerpt_mode = Settings::instance()->get( Settings::FOOTNOTES_IN_EXCERPT ); + $excerpt_mode = Settings::instance()->get_setting( ExcerptsSettingsGroup::FOOTNOTES_IN_EXCERPT['key'] )->get_value(); if ( 'yes' === $excerpt_mode ) { return $this->generate_excerpt_with_footnotes( $excerpt ); @@ -1053,7 +1046,7 @@ class Parser { public function footnotes_in_widget_text( string $content ): string { // phpcs:disable WordPress.PHP.YodaConditions.NotYoda // Appends the reference container if set to "post_end". - return $this->exec( $content, 'post_end' === Settings::instance()->get( REFERENCE_CONTAINER_POSITION['key'] ) ); + return $this->exec( $content, 'post_end' === Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_POSITION['key'] )->get_value() ); // phpcs:enable WordPress.PHP.YodaConditions.NotYoda } @@ -1067,7 +1060,6 @@ class Parser { * @param bool $hide_footnotes_text Hide footnotes found in the string. */ public function exec( string $content, bool $output_references = false, bool $hide_footnotes_text = false ): string { - // Process content. $content = $this->search( $content, $hide_footnotes_text ); @@ -1076,7 +1068,7 @@ class Parser { */ // Append the reference container or insert at shortcode. - $reference_container_position_shortcode = Settings::instance()->get( REFERENCE_CONTAINER_POSITION_SHORTCODE['key'] ); + $reference_container_position_shortcode = Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_POSITION_SHORTCODE['key'] )->get_value(); if ( empty( $reference_container_position_shortcode ) ) { $reference_container_position_shortcode = '[[references]]'; } @@ -1124,11 +1116,11 @@ class Parser { public function unify_delimiters( string $content ): string { // Get footnotes start and end tag short codes. - $starting_tag = Settings::instance()->get( Settings::FOOTNOTES_SHORT_CODE_START ); - $ending_tag = Settings::instance()->get( Settings::FOOTNOTES_SHORT_CODE_END ); + $starting_tag = Settings::instance()->get_setting( ShortcodeSettingsGroup::FOOTNOTES_SHORT_CODE_START )->get_value(); + $ending_tag = Settings::instance()->get_setting( ShortcodeSettingsGroup::FOOTNOTES_SHORT_CODE_END )->get_value(); if ( 'userdefined' === $starting_tag || 'userdefined' === $ending_tag ) { - $starting_tag = Settings::instance()->get( Settings::FOOTNOTES_SHORT_CODE_START_USER_DEFINED ); - $ending_tag = Settings::instance()->get( Settings::FOOTNOTES_SHORT_CODE_END_USER_DEFINED ); + $starting_tag = Settings::instance()->get_setting( ShortcodeSettingsGroup::FOOTNOTES_SHORT_CODE_START_USER_DEFINED )->get_value(); + $ending_tag = Settings::instance()->get_setting( ShortcodeSettingsGroup::FOOTNOTES_SHORT_CODE_END_USER_DEFINED )->get_value(); } // If any footnotes short code is empty, return the content without changes. @@ -1192,6 +1184,8 @@ class Parser { // Get footnote delimiter shortcodes and unify them. $content = self::unify_delimiters( $content ); + print_r('FOO'); + print_r($content); /* * Checks for balanced footnote delimiters; delimiter syntax validation. @@ -1201,7 +1195,7 @@ class Parser { */ // If enabled. - if ( Convert::to_bool( Settings::instance()->get( Settings::FOOTNOTE_SHORTCODE_SYNTAX_VALIDATION_ENABLE ) ) ) { + if ( Settings::instance()->get_setting( ShortcodeSettingsGroup::FOOTNOTE_SHORTCODE_SYNTAX_VALIDATION_ENABLE['key'] ->get_value()) ) { // Apply different regex depending on whether start shortcode is double/triple opening parenthesis. if ( '((' === self::$start_tag || '(((' === self::$start_tag ) { @@ -1270,7 +1264,7 @@ class Parser { } while ( preg_match( $value_regex, $content ) ); // Optionally moves footnotes outside at the end of the label element. - $label_issue_solution = Settings::instance()->get( Settings::FOOTNOTES_LABEL_ISSUE_SOLUTION ); + $label_issue_solution = Settings::instance()->get_setting( ReferrersInLabelsSettingsGroup::FOOTNOTES_LABEL_ISSUE_SOLUTION['key'] )->get_value(); if ( 'move' === $label_issue_solution ) { @@ -1341,7 +1335,7 @@ class Parser { if ( General::$amp_enabled ) { // Whether first clicking a referrer needs to expand the reference container. - if ( Convert::to_bool( Settings::instance()->get( REFERENCE_CONTAINER_COLLAPSE['key'] ) ) ) { + if ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_COLLAPSE['key'] )->get_value() ) ) { // Load 'public/partials/amp-footnote-expand.html'. $template = new Template( Template::PUBLIC, 'amp-footnote-expand' ); @@ -1392,7 +1386,7 @@ class Parser { $footnote_text = substr( $content, $pos_start + strlen( self::$start_tag ), $length - strlen( self::$start_tag ) ); // Get tooltip text if present. - self::$tooltip_shortcode = Settings::instance()->get( Settings::FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER ); + self::$tooltip_shortcode = Settings::instance()->get_setting( TooltipTextSettingsGroup::FOOTNOTES_TOOLTIP_EXCERPT_DELIMITER['key'] )->get_value(); self::$tooltip_shortcode_length = strlen( self::$tooltip_shortcode ); $tooltip_text_length = strpos( $footnote_text, (string) self::$tooltip_shortcode ); $has_tooltip_text = (bool) $tooltip_text_length; @@ -1416,7 +1410,7 @@ class Parser { * * TODO: Split into own method. */ - if ( Convert::to_bool( Settings::instance()->get( FOOTNOTE_URL_WRAP_ENABLED['key'] ) ) ) { + if ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::FOOTNOTE_URL_WRAP_ENABLED['key'] )->get_value() ) ) { $footnote_text = preg_replace( '#(?get( Settings::REFERRER_FRAGMENT_ID_SLUG ); - self::$footnote_link_slug = Settings::instance()->get( Settings::FOOTNOTE_FRAGMENT_ID_SLUG ); - self::$link_ids_separator = Settings::instance()->get( Settings::HARD_LINK_IDS_SEPARATOR ); + self::$referrer_link_slug = Settings::instance()->get_setting( HardLinksSettingsGroup::REFERRER_FRAGMENT_ID_SLUG['key'] )->get_value(); + self::$footnote_link_slug = Settings::instance()->get_setting( HardLinksSettingsGroup::FOOTNOTE_FRAGMENT_ID_SLUG['key'] )->get_value(); + self::$link_ids_separator = Settings::instance()->get_setting( HardLinksSettingsGroup::HARD_LINK_IDS_SEPARATOR['key'] )->get_value(); // Streamline ID concatenation. self::$post_container_id_compound = self::$link_ids_separator; @@ -1447,11 +1441,11 @@ class Parser { // Display the footnote referrers and the tooltips. if ( ! $hide_footnotes_text ) { - $index = Convert::index( $footnote_index, Settings::instance()->get( Settings::FOOTNOTES_COUNTER_STYLE ) ); + $index = Convert::index( $footnote_index, Settings::instance()->get_setting( NumberingSettingsGroup::FOOTNOTES_COUNTER_STYLE['key'] )->get_value() ); // Display only a truncated footnote text if option enabled. - $enable_excerpt = Convert::to_bool( Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_ENABLED ) ); - $max_length = (int) Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH ); + $enable_excerpt = Settings::instance()->get_setting( TooltipTruncationSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_ENABLED['key'] )->get_value(); + $max_length = Settings::instance()->get_setting( TooltipTruncationSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_EXCERPT_LENGTH['key'] )->get_value(); // Define excerpt text as footnote text by default. $excerpt_text = $footnote_text; @@ -1477,7 +1471,7 @@ class Parser { if ( General::$amp_enabled ) { // If the reference container is also collapsed by default. - if ( Convert::to_bool( Settings::instance()->get( REFERENCE_CONTAINER_COLLAPSE['key'] ) ) ) { + if ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_COLLAPSE['key'] )->get_value() ) ) { $excerpt_text .= ' on="tap:footnote_references_container_'; $excerpt_text .= self::$post_id . '_' . self::$reference_container_id; @@ -1511,7 +1505,7 @@ class Parser { $excerpt_text .= '>'; // Configurable read-on button label. - $excerpt_text .= Settings::instance()->get( Settings::FOOTNOTES_TOOLTIP_READON_LABEL ); + $excerpt_text .= Settings::instance()->get_setting( TooltipTruncationSettingsGroup::FOOTNOTES_TOOLTIP_READON_LABEL['key'] )->get_value(); $excerpt_text .= self::$hard_links_enabled ? '' : ''; } @@ -1522,7 +1516,7 @@ class Parser { * * Define the HTML element to use for the referrers. */ - if ( Convert::to_bool( Settings::instance()->get( Settings::FOOTNOTES_REFERRER_SUPERSCRIPT_TAGS ) ) ) { + if ( Settings::instance()->get_setting( ReferrersSettingsGroup::FOOTNOTES_REFERRER_SUPERSCRIPT_TAGS['key'] )->get_value() ) { $sup_span = 'sup'; @@ -1565,7 +1559,7 @@ class Parser { $referrer_anchor_element = ''; // The link element is set independently as it may be needed for styling. - if ( Convert::to_bool( Settings::instance()->get( LINK_ELEMENT_ENABLED['key'] ) ) ) { + if ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::LINK_ELEMENT_ENABLED['key'] )->get_value() ) ) { self::$link_span = 'a'; self::$link_open_tag = ''; @@ -1609,9 +1603,9 @@ class Parser { 'note_id' => $index, 'hard-link' => $footnote_link_argument, 'sup-span' => $sup_span, - 'before' => Settings::instance()->get( Settings::FOOTNOTES_STYLING_BEFORE ), + 'before' => Settings::instance()->get_setting( ReferrersSettingsGroup::FOOTNOTES_STYLING_BEFORE['key'] )->get_value(), 'index' => $index, - 'after' => Settings::instance()->get( Settings::FOOTNOTES_STYLING_AFTER ), + 'after' => Settings::instance()->get_setting( ReferrersSettingsGroup::FOOTNOTES_STYLING_AFTER['key'] )->get_value(), 'anchor-element' => $referrer_anchor_element, 'style' => $tooltip_style, 'text' => $tooltip_content, @@ -1625,12 +1619,12 @@ class Parser { // If tooltips are enabled but neither AMP nor alternative are. if ( General::$tooltips_enabled && ! General::$amp_enabled && ! General::$alternative_tooltips_enabled ) { - $offset_y = (int) Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y ); - $offset_x = (int) Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X ); - $fade_in_delay = (int) Settings::instance()->get( Settings::MOUSE_OVER_BOX_FADE_IN_DELAY ); - $fade_in_duration = (int) Settings::instance()->get( Settings::MOUSE_OVER_BOX_FADE_IN_DURATION ); - $fade_out_delay = (int) Settings::instance()->get( Settings::MOUSE_OVER_BOX_FADE_OUT_DELAY ); - $fade_out_duration = (int) Settings::instance()->get( Settings::MOUSE_OVER_BOX_FADE_OUT_DURATION ); + $offset_y = Settings::instance()->get_setting( TooltipPositionSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_Y['key'] )->get_value(); + $offset_x = Settings::instance()->get_setting( TooltipPositionSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_OFFSET_X['key'] )->get_value(); + $fade_in_delay = Settings::instance()->get_setting( TooltipTimingSettingsGroup::MOUSE_OVER_BOX_FADE_IN_DELAY['key'] )->get_value(); + $fade_in_duration = Settings::instance()->get_setting( TooltipTimingSettingsGroup::MOUSE_OVER_BOX_FADE_IN_DURATION['key'] )->get_value(); + $fade_out_delay = Settings::instance()->get_settingget( TooltipTimingSettingsGroup::MOUSE_OVER_BOX_FADE_OUT_DELAY['key'] )->get_value(); + $fade_out_duration = Settings::instance()->get_setting( TooltipTimingSettingsGroup::MOUSE_OVER_BOX_FADE_OUT_DURATION['key'] )->get_value(); // Fill in 'public/partials/tooltip.html'. $template_tooltip->replace( @@ -1638,7 +1632,7 @@ class Parser { 'post_id' => self::$post_id, 'container_id' => self::$reference_container_id, 'note_id' => $index, - 'position' => Settings::instance()->get( Settings::FOOTNOTES_MOUSE_OVER_BOX_POSITION ), + 'position' => Settings::instance()->get_setting( TooltipPositionSettingsGroup::FOOTNOTES_MOUSE_OVER_BOX_POSITION['key'] )->get_value(), 'offset-y' => empty( $offset_y ) ? 0 : $offset_y, 'offset-x' => empty( $offset_x ) ? 0 : $offset_x, 'fade-in-delay' => empty( $fade_in_delay ) ? 0 : $fade_in_delay, @@ -1711,16 +1705,16 @@ class Parser { */ // If the backlink symbol is enabled. - if ( Convert::to_bool( Settings::instance()->get( REFERENCE_CONTAINER_BACKLINK_SYMBOL_ENABLE['key'] ) ) ) { + if ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_BACKLINK_SYMBOL_ENABLE['key'] )->get_value() ) ) { // Get html arrow. - $arrow = Convert::get_arrow( Settings::instance()->get( Settings::HYPERLINK_ARROW ) ); + $arrow = Convert::get_arrow( Settings::instance()->get_setting( BacklinkSymbolSettingsGroup::HYPERLINK_ARROW['key'] )->get_value() ); // Set html arrow to the first one if invalid index defined. if ( is_array( $arrow ) ) { $arrow = Convert::get_arrow( 0 ); } // Get user defined arrow. - $arrow_user_defined = Settings::instance()->get( Settings::HYPERLINK_ARROW_USER_DEFINED ); + $arrow_user_defined = Settings::instance()->get_setting( BacklinkSymbolSettingsGroup::HYPERLINK_ARROW_USER_DEFINED['key'] )->get_value(); if ( ! empty( $arrow_user_defined ) ) { $arrow = $arrow_user_defined; } @@ -1743,12 +1737,12 @@ class Parser { * Initially an appended comma was hard-coded in this algorithm for enumerations. * The comma in enumerations is not universally preferred. */ - if ( Convert::to_bool( Settings::instance()->get( BACKLINKS_SEPARATOR_ENABLED['key'] ) ) ) { + if ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::BACKLINKS_SEPARATOR_ENABLED['key'] )->get_value() ) ) { if ( empty( $separator ) ) { // If it is not, check which option is on. - $separator_option = Settings::instance()->get( BACKLINKS_SEPARATOR_OPTION['key'] ); + $separator_option = Settings::instance()->get_setting( ReferenceContainerSettingsGroup::BACKLINKS_SEPARATOR_OPTION['key'] )->get_value(); // TODO: replace with `match` (but currently it breaks the Rector // downgrade to PHP 7.4. // https://github.com/rectorphp/rector/issues/6315 @@ -1763,7 +1757,7 @@ class Parser { $separator = ' –'; break; default: - $separator = Settings::instance()->get( BACKLINKS_SEPARATOR_CUSTOM['key'] ); + $separator = Settings::instance()->get_setting( ReferenceContainerSettingsGroup::BACKLINKS_SEPARATOR_CUSTOM['key'] )->get_value(); break; } } @@ -1777,12 +1771,12 @@ class Parser { * * Initially a dot was appended in the table row template. */ - if ( Convert::to_bool( Settings::instance()->get( BACKLINKS_TERMINATOR_ENABLED['key'] ) ) ) { + if ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::BACKLINKS_TERMINATOR_ENABLED['key'] )->get_value() ) ) { if ( empty( $terminator ) ) { // If it is not, check which option is on. - $terminator_option = Settings::instance()->get( BACKLINKS_TERMINATOR_OPTION['key'] ); + $terminator_option = Settings::instance()->get_setting( ReferenceContainerSettingsGroup::BACKLINKS_TERMINATOR_OPTION['key'] )->get_value(); // TODO: replace with `match` (but currently it breaks the Rector // downgrade to PHP 7.4. // https://github.com/rectorphp/rector/issues/6315 @@ -1797,7 +1791,7 @@ class Parser { $terminator = ':'; break; default: - $terminator = Settings::instance()->get( BACKLINKS_TERMINATOR_CUSTOM['key'] ); + $terminator = Settings::instance()->get_setting( ReferenceContainerSettingsGroup::BACKLINKS_TERMINATOR_CUSTOM['key'] )->get_value(); break; } } @@ -1814,7 +1808,7 @@ class Parser { * Variable number length and proportional character width require explicit line breaks. * Otherwise, an ordinary space character offering a line break opportunity is inserted. */ - $line_break = Convert::to_bool( Settings::instance()->get( BACKLINKS_LINE_BREAKS_ENABLED['key'] ) ) ? '
' : ' '; + $line_break = ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::BACKLINKS_LINE_BREAKS_ENABLED['key'] )->get_value() ) ? '
' : ' '; /* * Line breaks for source readability. @@ -1828,7 +1822,7 @@ class Parser { /* * Reference container table row template load. */ - $combine_identical_footnotes = Convert::to_bool( Settings::instance()->get( COMBINE_IDENTICAL_FOOTNOTES['key'] ) ); + $combine_identical_footnotes = ( Settings::instance()->get_setting( NumberingSettingsGroup::COMBINE_IDENTICAL_FOOTNOTES['key'] )->get_value() ); // AMP compatibility requires a full set of AMP compatible table row templates. if ( General::$amp_enabled ) { @@ -1836,9 +1830,9 @@ class Parser { if ( $combine_identical_footnotes ) { // The combining template allows for backlink clusters and supports cell clicking for single notes. $template = new Template( Template::PUBLIC, 'amp-reference-container-body-combi' ); - } elseif ( Convert::to_bool( Settings::instance()->get( REFERENCE_CONTAINER_3COLUMN_LAYOUT_ENABLE['key'] ) ) ) { + } elseif ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_3COLUMN_LAYOUT_ENABLE['key'] )->get_value() ) ) { $template = new Template( Template::PUBLIC, 'amp-reference-container-body-3column' ); - } elseif ( Convert::to_bool( Settings::instance()->get( REFERENCE_CONTAINER_BACKLINK_SYMBOL_SWITCH['key'] ) ) ) { + } elseif ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_BACKLINK_SYMBOL_SWITCH['key'] )->get_value() ) ) { $template = new Template( Template::PUBLIC, 'amp-reference-container-body-switch' ); } else { @@ -1849,9 +1843,9 @@ class Parser { } elseif ( $combine_identical_footnotes ) { // The combining template allows for backlink clusters and supports cell clicking for single notes. $template = new Template( Template::PUBLIC, 'reference-container-body-combi' ); - } elseif ( Convert::to_bool( Settings::instance()->get( REFERENCE_CONTAINER_3COLUMN_LAYOUT_ENABLE['key'] ) ) ) { + } elseif ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_3COLUMN_LAYOUT_ENABLE['key'] )->get_value() ) ) { $template = new Template( Template::PUBLIC, 'reference-container-body-3column' ); - } elseif ( Convert::to_bool( Settings::instance()->get( REFERENCE_CONTAINER_BACKLINK_SYMBOL_SWITCH['key'] ) ) ) { + } elseif ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_BACKLINK_SYMBOL_SWITCH['key'] )->get_value() ) ) { $template = new Template( Template::PUBLIC, 'reference-container-body-switch' ); } else { @@ -1863,7 +1857,7 @@ class Parser { /* * Switch backlink symbol and footnote number. */ - $symbol_switch = Convert::to_bool( Settings::instance()->get( REFERENCE_CONTAINER_BACKLINK_SYMBOL_SWITCH['key'] ) ); + $symbol_switch = ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_BACKLINK_SYMBOL_SWITCH['key'] )->get_value() ); // Loop through all footnotes found in the page. $num_footnotes = count( self::$footnotes ); @@ -1883,7 +1877,7 @@ class Parser { // Get the footnote index string and. // Keep supporting legacy index placeholder. - $footnote_id = Convert::index( ( $index + 1 ), Settings::instance()->get( Settings::FOOTNOTES_COUNTER_STYLE ) ); + $footnote_id = Convert::index( $index + 1, Settings::instance()->get_setting( NumberingSettingsGroup::FOOTNOTES_COUNTER_STYLE['key'] )->get_value() ); /** * Case of only one backlink per table row. @@ -1903,9 +1897,9 @@ class Parser { * * @since 2.5.4 */ - if ( Convert::to_bool( Settings::instance()->get( Settings::FOOTNOTES_BACKLINK_TOOLTIP_ENABLE ) ) ) { + if ( Settings::instance()->get_setting( HardLinksSettingsGroup::FOOTNOTES_BACKLINK_TOOLTIP_ENABLE['key'] )->get_value() ) { $use_backbutton_hint = ' title="'; - $use_backbutton_hint .= Settings::instance()->get( Settings::FOOTNOTES_BACKLINK_TOOLTIP_TEXT ); + $use_backbutton_hint .= Settings::instance()->get_setting( HardLinksSettingsGroup::FOOTNOTES_BACKLINK_TOOLTIP_TEXT['key'] )->get_value(); $use_backbutton_hint .= '"'; } else { $use_backbutton_hint = ''; @@ -2028,7 +2022,7 @@ class Parser { $flag_combined = true; // Update the footnote ID. - $footnote_id = Convert::index( ( $check_index + 1 ), Settings::instance()->get( Settings::FOOTNOTES_COUNTER_STYLE ) ); + $footnote_id = Convert::index( ( $check_index + 1 ), Settings::instance()->get_setting( NumberingSettingsGroup::FOOTNOTES_COUNTER_STYLE['key'] )->get_value() ); // Resume composing the backlinks enumeration. $footnote_backlinks .= "$separatorget( Settings::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE ) ); + self::$mirror_tooltip_text = Settings::instance()->get_setting( TooltipTextSettingsGroup::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_ENABLE['key'] )->get_value(); if ( self::$mirror_tooltip_text ) { $tooltip_text = substr( $footnote_text, 0, $tooltip_text_length ); - $reference_text_introducer = Settings::instance()->get( Settings::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR ); + $reference_text_introducer = Settings::instance()->get_setting( TooltipTextSettingsGroup::FOOTNOTES_TOOLTIP_EXCERPT_MIRROR_SEPARATOR['key'] )->get_value(); $reference_text = $tooltip_text . $reference_text_introducer . $not_tooltip_text; } else { $reference_text = $not_tooltip_text; @@ -2113,7 +2107,7 @@ class Parser { // Used in standard layout W/O COMBINED FOOTNOTES. 'post_id' => self::$post_id, 'container_id' => self::$reference_container_id, - 'note_id' => Convert::index( $first_footnote_index, Settings::instance()->get( Settings::FOOTNOTES_COUNTER_STYLE ) ), + 'note_id' => Convert::index( $first_footnote_index, Settings::instance()->get_setting( NumberingSettingsGroup::FOOTNOTES_COUNTER_STYLE['key'] )->get_value() ), 'link-start' => self::$link_open_tag, 'link-end' => self::$link_close_tag, 'link-span' => self::$link_span, @@ -2141,11 +2135,11 @@ class Parser { } - // Call again for robustness when priority levels don’t match any longer. - self::$scroll_offset = (int) Settings::instance()->get( Settings::FOOTNOTES_SCROLL_OFFSET ); + // Call again for robustness when priority levels don't match any longer. + self::$scroll_offset = Settings::instance()->get_setting( ScrollingSettingsGroup::FOOTNOTES_SCROLL_OFFSET['key'] )->get_value(); // Streamline. - $collapse_default = Convert::to_bool( Settings::instance()->get( REFERENCE_CONTAINER_COLLAPSE['key'] ) ); + $collapse_default = ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_COLLAPSE['key'] )->get_value() ); /* * Reference container label. @@ -2154,14 +2148,14 @@ class Parser { * In case of empty label that would apply to the left half button character. * Hence the point in setting an empty label to U+202F NARROW NO-BREAK SPACE. */ - $reference_container_label = Settings::instance()->get( REFERENCE_CONTAINER_NAME['key'] ); + $reference_container_label = Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_NAME['key'] )->get_value(); // Select the reference container template. // Whether AMP compatibility mode is enabled. if ( General::$amp_enabled ) { // Whether the reference container is collapsed by default. - if ( Convert::to_bool( Settings::instance()->get( REFERENCE_CONTAINER_COLLAPSE['key'] ) ) ) { + if ( ( Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_COLLAPSE['key'] )->get_value() ) ) { // Load 'public/partials/amp-reference-container-collapsed.html'. $template_container = new Template( Template::PUBLIC, 'amp-reference-container-collapsed' ); @@ -2191,11 +2185,11 @@ class Parser { if ( 'jquery' === General::$script_mode ) { $scroll_offset = ( self::$scroll_offset / 100 ); - $scroll_up_duration = (int) Settings::instance()->get( Settings::FOOTNOTES_SCROLL_DURATION ); + $scroll_up_duration = Settings::instance()->get_setting( ScrollingSettingsGroup::FOOTNOTES_SCROLL_DURATION['key'] )->get_value(); - if ( Convert::to_bool( Settings::instance()->get( Settings::FOOTNOTES_SCROLL_DURATION_ASYMMETRICITY ) ) ) { + if ( Settings::instance()->get_setting( ScrollingSettingsGroup::FOOTNOTES_SCROLL_DURATION_ASYMMETRICITY['key'] )->get_value() ) { - $scroll_down_duration = (int) Settings::instance()->get( Settings::FOOTNOTES_SCROLL_DOWN_DURATION ); + $scroll_down_duration = Settings::instance()->get_setting( ScrollingSettingsGroup::FOOTNOTES_SCROLL_DOWN_DURATION['key'] )->get_value(); } else { @@ -2203,8 +2197,8 @@ class Parser { } - $scroll_down_delay = (int) Settings::instance()->get( Settings::FOOTNOTES_SCROLL_DOWN_DELAY ); - $scroll_up_delay = (int) Settings::instance()->get( Settings::FOOTNOTES_SCROLL_UP_DELAY ); + $scroll_down_delay = Settings::instance()->get_setting( ScrollingSettingsGroup::FOOTNOTES_SCROLL_DOWN_DELAY['key'] )->get_value(); + $scroll_up_delay = Settings::instance()->get_setting( ScrollingSettingsGroup::FOOTNOTES_SCROLL_UP_DELAY['key'] )->get_value(); } @@ -2212,7 +2206,7 @@ class Parser { array( 'post_id' => self::$post_id, 'container_id' => self::$reference_container_id, - 'element' => Settings::instance()->get( REFERENCE_CONTAINER_LABEL_ELEMENT ), + 'element' => Settings::instance()->get_setting( ReferenceContainerSettingsGroup::REFERENCE_CONTAINER_LABEL_ELEMENT ), 'name' => empty( $reference_container_label ) ? ' ' : $reference_container_label, 'button-style' => $collapse_default ? '' : 'display: none;', 'style' => $collapse_default ? 'display: none;' : '',