{"id":4479,"date":"2011-02-26T03:01:48","date_gmt":"2011-02-26T11:01:48","guid":{"rendered":"http:\/\/www.oeconomist.com\/blogs\/daniel\/?page_id=4479"},"modified":"2023-11-02T14:09:04","modified_gmt":"2023-11-02T21:09:04","slug":"favicons-apple-touch-icons-site-thumbnail-images-php-and-wordpress-coding-issues","status":"publish","type":"page","link":"https:\/\/www.oeconomist.com\/blogs\/daniel\/?page_id=4479","title":{"rendered":"FavIcons, Apple Touch Icons, Site Thumbnail Images: PHP and WordPress Coding Issues"},"content":{"rendered":"<p>This is the third part of <a href=\"?p=4489\">a three-part discussion of <code>favicon<\/code>s, Apple-Touch icons, site thumbnail images, and how to tag pages (especially WordPress pages) to associate them with such graphics<\/a>.  <a href=\"?page_id=4400\">The first part<\/a> explained the purpose of these graphics, and the required <abbr title=\"HyperText Mark-up Language\">HTML<\/abbr>.  <a href=\"?page_id=4424\">The second part<\/a> provides working code that can be dropped into a <a href=\"https:\/\/www.wordpress.org\/\">WordPress<\/a> theme (specifically, into <code>functions.php<\/code>).  This final, very <em>boring<\/em> part motivates that code, and provides some more general discussion which could be applied to <a href=\"https:\/\/www.php.net\/\"><abbr title=\"Personal Home Pages Hypertext Processor\">PHP<\/abbr><\/a> other than <a href=\"https:\/\/www.wordpress.org\/\">WordPress<\/a>.<\/p> <p>In <a href=\"\">discussing the nature of <code>favicon<\/code>s, Apple Touch icons, and thumbnail graphics used by linking sites<\/a>, I tried to give some indication as to how I thought the <abbr title=\"HyperText Mark-up Language\">HTML<\/abbr> ought to be handled.  Even in the case of dynamically generated webpages, some of the code that I've seen out there just hard-codes the <abbr title=\"HyperText Mark-up Language\">HTML<\/abbr> for these graphics.  Such code is very breakable, as when, for example, a &#39;blog is relocated to a different directory (perhaps of a different domain).  And, in the case of dynamically generated individual posts and pages which are to have their own thumbnail images, the handling too must be dynamic.<\/p> <p>There are further issues in how generating <a href=\"https:\/\/www.php.net\/\"><abbr title=\"Personal Home Pages Hypertext Processor\">PHP<\/abbr><\/a> code should be designed, some general, and some specific to <a href=\"https:\/\/www.wordpress.org\/\">WordPress<\/a>.<\/p> <p><span style=\"font-weight: bolder ; font-variant: small-caps ;\">&#91;Up-Date<\/span> (2020:05\/19)<span style=\"font-weight: bolder ;\">:<\/span> I up-dated the code to-day, but have only partially up-dated the discussion around the code.  So the <em>explanations<\/em> are a bit <em>crufty<\/em>.<span style=\"font-weight: bolder ;\">&#93;<\/span><\/p> <h4>General <a href=\"https:\/\/www.php.net\/\"><abbr title=\"Personal Home Pages Hypertext Processor\">PHP<\/abbr><\/a> Issues<\/h4> <p>From the perspective of user-friendliness, perhaps the best route would involve cre&auml;ting a webpage interface that would allow the user to upload graphics files, and declare these or files already present to be the <code>favicon<\/code>, Apple Touch icons, or default thumbnail graphic icons.  For the aforementioned sorts of files, my code just looks for candidates from within restricted sets of names, and uses the first of each that it encounters.  In the case of <code>favicon<\/code>s and thumbnail images, the differences amongst allowed file names is to support different extensions, corresponding to different formats; but a single file-name could have been imposed, with no extension or with the extension ignored.  In the case of Apple Touch icons, the names themselves pass further information to the client device interface.<\/p> <p>The <em>basic<\/em> idea is just<\/p> <blockquote style=\"width: 91%; overflow: auto ; white-space: nowrap ;\"><code>$filespec = \"\";<br \/>if (file_exists(&#34;<var>candidateNameFirst<\/var>&#34;)<br \/>&nbsp;&nbsp;$filespec = <var>$siteURL<\/var> . &#34;<var>candidateNameFirst<\/var>&#34;;<br \/>else if (file_exists(&#34;<var>candidateNameSecond<\/var>&#34;)<br \/>&nbsp;&nbsp;$filespec = <var>$siteURL<\/var> . &#34;<var>candidateNameSecond<\/var>&#34;;<br \/>&#8230;<br \/>else if (file_exists(&#34;<var>candidateNameLast<\/var>&#34;)<br \/>&nbsp;&nbsp;$filespec = <var>$siteURL<\/var> . &#34;<var>candidateNameLast<\/var>&#34;;<br \/>if ($filespec)<br \/>&nbsp;&nbsp;echo &#34;&lt;<var>tagStuff<\/var>&#34; . $filespec . &#34;<var>moreTagStuff<\/var> \/&gt;\\n&#34;;<\/code><\/blockquote> <p>for each sort of image (the <code>favicon<\/code>, the Apple touch icons, and the default thumbnail images).  The site <abbr title=\"Uniform Resource Locator\">URL<\/abbr> isn't in the code as a (sub)string literal so that the user doesn't have to mess with it at each installation.  The major complication is when the user has selected a distinct image file to be used as a thumbnail graphic for a particular page.  That file then has to be invoked.<\/p> <p>Some of the tags to be generated have a <code>type<\/code> attribute, in which a <abbr title=\"Multipurpose Internet Mail Extensions\">MIME<\/abbr> image type is supposed to be identified.  The <em>easiest<\/em> way to infer an image type is from the file-name <em>extension<\/em> (eg <q><code>jpg<\/code><\/q>), but I've encountered many files of one sort with the extension of another.  So my thinking was to call a function to identify the <abbr title=\"Multipurpose Internet Mail Extensions\">MIME<\/abbr> type.  I didn't find a standard function that did just that, but the ill-named <code>getimagesize<\/code> function actually returns an array, one element of which (since <a href=\"https:\/\/www.php.net\/\"><abbr title=\"Personal Home Pages Hypertext Processor\">PHP<\/abbr><\/a> version 4.3.0) is <abbr title=\"Multipurpose Internet Mail Extensions\">MIME<\/abbr> type information.  So I could call <code>getimagesize<\/code> within another function, which would just return that type information.<\/p> <blockquote style=\"width: 91%; overflow: auto ; white-space: nowrap ;\"><code>\/* First Attempt *\/<br \/>function getimagemimetype ($filespec)<br \/>{<br \/>&nbsp;&nbsp;$imagesizearray = getimagesize($filespec);<br \/>&nbsp;&nbsp;return($imagesizearray&#91;&#39;mime&#39;&#93;);<br \/>}<\/code><\/blockquote> <p>Unfortunately, while I found that this worked fine for <abbr title=\"Graphics Interchange Format\">GIF<\/abbr>, <abbr title=\"Joint Photographic Experts Group\">JPEG<\/abbr> <abbr title=\"File Interchange Format\">FIF<\/abbr>, and <abbr title=\"Portable Network Graphics\">PNG<\/abbr> files, it returned an empty string for <abbr title=\"Microsoft\">MS<\/abbr> icon files.  In cases where an empty string is returned, I resorted to reading the first four bytes of the file, and comparing these with the first four bytes of the <abbr title=\"Microsoft\">MS<\/abbr> icon file specification. (The comparison itself is somewhat kludgy, because <a href=\"https:\/\/www.php.net\/\"><abbr title=\"Personal Home Pages Hypertext Processor\">PHP<\/abbr><\/a> is not good about reading bytes as such nor about comparing characters in strings to integral values, and treats a byte <code>0x00<\/code> as an <abbr title=\"end of string\">EOS<\/abbr>).<\/p> <blockquote style=\"width: 91%; overflow: auto ; white-space: nowrap ;\"><code>function getimagemimetype ($filespec)<br \/>{<br \/>&nbsp;&nbsp;$imagesizearray = getimagesize($filespec);<br \/>&nbsp;&nbsp;$type = $imagesizearray&#91;&#39;mime&#39;&#93;;<br \/>&nbsp;&nbsp;if (strlen($type) == 0)<br \/>&nbsp;&nbsp;{ \/* See if it might be a .ICO *\/<br \/>&nbsp;&nbsp;&nbsp;&nbsp;$identifier = fread(fopen($filespec,&#39;r&#39;),4);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;$bytes = &#34;\\x0\\x1\\x2&#34;;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;if ( ($identifier&#91;0&#93; == $bytes&#91;0&#93;) && ($identifier&#91;1&#93; == $bytes&#91;0&#93;)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(($identifier&#91;2&#93; == $bytes&#91;1&#93;) || ($identifier&#91;2&#93; == $bytes&#91;2&#93;))<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;($identifier&#91;3&#93; == $bytes&#91;0&#93;))<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$type = &#34;image\/vnd.microsoft.icon&#34;;<br \/>&nbsp;&nbsp;}<br \/>&nbsp;&nbsp;return ($type);<br \/>}<\/code><\/blockquote> <p>Hypothetically, I could have just punted to looking for a file-name extension of <q><code>.ico<\/code><\/q> exactly and only when <code>getimagesize<\/code> failed, or even never invoked it for files with that extension.  Also, the results of experimentation suggest that setting the <code>type<\/code> attribute to an empty string will not prevent a <abbr title=\"Microsoft\">MS<\/abbr> icon from working as a <code>favicon<\/code>.<\/p> <p>Another possibility would be to read the first few bytes of <em>any<\/em> file, rather than calling <code>getimagesize<\/code>.  A <abbr title=\"Graphics Interchange Format\">GIF<\/abbr> file begins <q><code>GIF87a<\/code><\/q> or <q><code>GIF89a<\/code><\/q> and its proper <abbr title=\"Multipurpose Internet Mail Extensions\">MIME<\/abbr> type is <q><code>image\/gif<\/code><\/q>; a <abbr title=\"Joint Photographic Experts Group\">JPEG<\/abbr> <abbr title=\"File Interchange Format\">FIF<\/abbr> file begins <q><code>\\xFF\\xD8\\xFF\\xE0\\x<var>dd<\/var>\\x<var>dd<\/var>JFIF\\x00<\/code><\/q> (where <q><code><var>d<\/var><\/code><\/q> is some hexadecimal digit) and its proper <abbr title=\"Multipurpose Internet Mail Extensions\">MIME<\/abbr> type is <q><code>image\/jp<strong>e<\/strong>g<\/code><\/q>; an ICO file begins <q><code>\\x00\\x00\\0x00\\0x01<\/code><\/q> or <q><code>\\x00\\x00\\0x00\\0x02<\/code><\/q> and its proper <abbr title=\"Multipurpose Internet Mail Extensions\">MIME<\/abbr> type is <q><code>image\/vnd.microsoft.icon<\/code><\/q>; a <abbr title=\"Portable Network Graphics\">PNG<\/abbr> file begins <q><code>\\x89PNG\\x0D\\x0A\\x1A\\x0A<\/code><\/q> and its proper <abbr title=\"Multipurpose Internet Mail Extensions\">MIME<\/abbr> type is <q><code>image\/png<\/code><\/q>.  But (as noted parenthetically above) <a href=\"https:\/\/www.php.net\/\"><abbr title=\"Personal Home Pages Hypertext Processor\">PHP<\/abbr><\/a> is not good about handling the comparison in cases where a zero byte is part of the header; it might be best to provide a separate function to handle the byte comparisons as such, if there are going to be many of them.<\/p> <p>The code to identify <abbr title=\"Multipurpose Internet Mail Extensions\">MIME<\/abbr> type could be put in-line everywhere it were used; but, unless it is going to be from bald acceptance of the file-name extension (in which case it might be done when the file existence were detected), there would be dubious efficiencies in doing that.<\/p> <p>My code for the <code>favicon<\/code> conforms pretty closely to the basic structure sketched above, but the <abbr title=\"Multipurpose Internet Mail Extensions\">MIME<\/abbr> type is handled by introducing a variable <code>$favicon_type<\/code>, set as part of the positive outcome of any condition.<\/p> <blockquote style=\"width: 91%; overflow: auto ; white-space: nowrap ;\"><code>if (file_exists(&#34;favicon.<var>xxx<\/var>&#34;))<br \/>{<br \/>&nbsp;&nbsp;$favicon_spec = get_bloginfo(&#39;siteurl&#39;) . &#34;\/favicon.png&#34;;<br \/>&nbsp;&nbsp;<u>$favicon_type = getimagemimetype(&#34;favicon.<var>xxx<\/var>&#34;);<\/u><br \/>}<\/code><\/blockquote> <p>(<abbr title=\"nota bene\">NB<\/abbr>: The function <code>get_bloginfo<\/code> is here drawn from <a href=\"https:\/\/www.wordpress.org\/\">WordPress<\/a>.) My order of pre&euml;mption was fairly aribitrary.<\/p> <p>My code for the AppleTouch icons actually just puts the <code>echo<\/code> commands within the conditionals.<\/p> <blockquote style=\"width: 91%; overflow: auto ; white-space: nowrap ;\"><code>$siteurl = get_bloginfo('siteurl');<br \/>$apple_touch_icon_possible_size = array(\"57\", \"72\", \"76\", \"120\", \"144\", \"152\", \"180\"); <br \/>foreach ($apple_touch_icon_possible_size as $apple_touch_icon_size)<br \/>{<br \/>&nbsp;&nbsp;&nbsp;&nbsp;$apple_touch_icon_sizes = $apple_touch_icon_size . \"x\" . $apple_touch_icon_size;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;$apple_touch_icon_name_partial = \"apple-touch-icon-\" . $apple_touch_icon_sizes;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;if (file_exists($apple_touch_icon_name_partial . \"-precomposed.png\"))<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo \" &lt;link rel=\\\"apple-touch-icon-precomposed\\\" sizes=\\\"\" . $apple_touch_icon_sizes . \"\\\" href=\\\"\"<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. $siteurl . $apple_touch_icon_name_partial . \"-precomposed.png\\\" \/&gt;\\n\";<br \/>&nbsp;&nbsp;&nbsp;&nbsp;else if (file_exists($apple_touch_icon_name_partial . \".png\"))<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo \" &lt;link rel=\\\"apple-touch-icon\\\" sizes=\\\"\" . $apple_touch_icon_sizes . \"\\\" href=\\\"\" . $siteurl<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;. $apple_touch_icon_name_partial . \".png\\\" \/&gt;\\n\";<br \/>}<\/code><\/blockquote> <p>The order of pre&euml;mption conforms to what an standard client would do in the absence of tags.<\/p> <p>My code for the thumbnail graphics is very much like that for the <code>favicon<\/code>, except that it first looks for a page-specific image.<\/p> <h4><a href=\"https:\/\/www.wordpress.org\/\">WordPress<\/a> Issues<\/h4> <p>The first question is of what, if anything, to put in <code>functions.php<\/code> and of what, if anything, to put in <code>header.php<\/code>.  In order to use the <q>featured image<\/q> facility of <a href=\"https:\/\/www.wordpress.org\/\">WordPress<\/a> version 2.9 and later, <code>functions.php<\/code> must have<\/p> <blockquote style=\"width: 91%; overflow: auto ; white-space: nowrap ;\"><code>add_theme_support(&#39;post-thumbnails&#39;);<\/code><\/blockquote> <p>(preferably prefaced with <q><code>if&nbsp;(function_exists(&#39;add_theme_support&#39;))<\/code><\/q>) inserted into it.  All of the remaining code here could be put into either <code>.php<\/code> file, though <code>getimagemimetype<\/code> should probably be defined in <code>functions.php<\/code>.<\/p> <p>I chose to put everything remaining also into <code>functions.php<\/code>.  That meant wrapping it into one or more functions, and then adding each such function as an <code>action<\/code> to <code>wp_head<\/code>.  If, instead, that code were placed in <code>header.php<\/code>, then the code should be inserted somewhere within the <code>head<\/code> element, and only the code of <code>getimagemimetype<\/code> should be wrapped into a function.  Given that the code is all being placed in <code>functions.php<\/code>, the next question is of whether to put the code for all three sorts of graphics into just one function.  If one is always going to use all of the functionality, and never modify the implementation once it's effected, then one function is fine.  But, for ease of maintainability, I chose to cre&auml;te three functions, one for each basic sort of graphic; that required three calls to <code>add_action<\/code>, one for each of those functions.<\/p> <p>I've seen code for the thumbnail graphic that provides a default for <q><code>singular<\/code><\/q> pages (individual entries, and those pages which <a href=\"https:\/\/www.wordpress.org\/\">WordPress<\/a> calls <q>Pages<\/q>) that do not have a Featured Image, but that does <em>not<\/em> provide thumbnails for non-<code>singular<\/code> pages.  I don't see why the default thumbnail graphic should not be used in such cases.  In any event, the code for extracting the page-specific thumbnail specification is a bit rococco.<\/p> <blockquote style=\"width: 91%; overflow: auto ; white-space: nowrap ;\"><code>if (is_singular())<br \/>&nbsp;&nbsp;if (function_exists(&#39;has_post_thumbnail&#39;))<br \/>&nbsp;&nbsp;&nbsp;&nbsp;if (has_post_thumbnail())<br \/>&nbsp;&nbsp;&nbsp;&nbsp;{<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$image_array = wp_get_attachment_image_src(get_post_thumbnail_id());<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$thumbnail_graphic_spec = esc_attr($image_array&#91;0&#93;);<br \/>&nbsp;&nbsp;&nbsp;&nbsp;}<\/code><\/blockquote> <p><code>get_post_thumbnail_id<\/code> (with no argument) returns an integer associated with the featured image for the present page.  Basically by look-up, <code>wp_get_attachment_image_src<\/code> converts that integer into an array, the initial element of which is a <abbr title=\"Uniform Resource Locator\">URL<\/abbr> for the featured image.  <code>esc_attr<\/code> makes sure that characters that could cause awkwardness are removed or escaped.<\/p> <p style=\"text-align: right ;\"><a href=\"?p=4489#respond\">Comments<\/a><\/p>","protected":false},"excerpt":{"rendered":"This is the third part of a three-part discussion of favicons, Apple-Touch icons, site thumbnail images, and how to tag pages (especially WordPress pages) to associate them with such graphics. The first part explained the purpose of these graphics, and the required HTML. The second part provides working code that can be dropped into a [&hellip;]","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"footnotes":""},"class_list":["post-4479","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.oeconomist.com\/blogs\/daniel\/index.php?rest_route=\/wp\/v2\/pages\/4479","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.oeconomist.com\/blogs\/daniel\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.oeconomist.com\/blogs\/daniel\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.oeconomist.com\/blogs\/daniel\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.oeconomist.com\/blogs\/daniel\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4479"}],"version-history":[{"count":1,"href":"https:\/\/www.oeconomist.com\/blogs\/daniel\/index.php?rest_route=\/wp\/v2\/pages\/4479\/revisions"}],"predecessor-version":[{"id":12170,"href":"https:\/\/www.oeconomist.com\/blogs\/daniel\/index.php?rest_route=\/wp\/v2\/pages\/4479\/revisions\/12170"}],"wp:attachment":[{"href":"https:\/\/www.oeconomist.com\/blogs\/daniel\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4479"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}