PageRenderTime 54ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/autonav-wl.php

https://bitbucket.org/wlindley/autonav
PHP | 1302 lines | 1034 code | 148 blank | 120 comment | 263 complexity | b374e1313373ba751203ad45cba1b5fb MD5 | raw file
  1. <?php
  2. /*
  3. Plugin Name: Autonav Image Table Based Site Navigation
  4. Plugin URI: http://www.wlindley.com/website/autonav/
  5. Description: Displays child pages, posts, attached images or more, in a table of images or a simple list. Automatically resizes thumbnails.
  6. Author: William Lindley
  7. Version: 1.5.10
  8. Author URI: http://www.wlindley.com/
  9. */
  10. /* Copyright 2008-2015 William Lindley (email : wlindley -at- wlindley -dot- com)
  11. This program is free software; you can redistribute it and/or modify
  12. it under the terms of the GNU General Public License as published by
  13. the Free Software Foundation; either version 2 of the License, or
  14. (at your option) any later version.
  15. This program is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. GNU General Public License for more details.
  19. You should have received a copy of the GNU General Public License
  20. along with this program; if not, write to the Free Software
  21. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. define ("AUTONAV_ARBITRARY_SIZE", 900); // for images unsupported by getimagesize()
  24. define ("AUTONAV_FORCE_CONSTRAIN", 4000); // forces WP's image_constrain_size_for_editor
  25. /* *** HTML helpers *** */
  26. function an_create_tag ($html_tag, $html_attr) {
  27. $attrs = array($html_tag);
  28. if (is_array($html_attr)) {
  29. foreach ($html_attr as $attr => $value) {
  30. $attrs[] = $attr . '="' . esc_attr($value) . '"';
  31. }
  32. }
  33. return '<' . implode(' ',$attrs) . '>';
  34. }
  35. /* *** Resize filters **** */
  36. function autonav_internal_resize ($from_image, $attr, $prefix) {
  37. if (is_array($attr[$prefix.'_resample'])) {
  38. $resample_params = $attr[$prefix.'_resample'];
  39. } else {
  40. $resample_params = image_resize_dimensions(imagesx($from_image), imagesy($from_image),
  41. $attr["{$prefix}width"], $attr["{$prefix}height"],
  42. $attr['crop'] > 0 ? 1 : 0);
  43. }
  44. if (is_array($resample_params)) {
  45. // Prepare to resize
  46. list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $resample_params;
  47. $to_image = imagecreatetruecolor($dst_w, $dst_h);
  48. $bkg = substr($attr['background'], 0, 7);
  49. if (preg_match('/#[0-9a-fA-F]{6}/', $bkg)) {
  50. $fill_color = sscanf($bkg, '#%2x%2x%2x');
  51. imagefilledrectangle($to_image, 0, 0, $dst_w, $dst_h, $fill_color);
  52. }
  53. // 1=center x,y; 2=upper-left (x=0,y=0); 3=top-center (center x,y=0)
  54. if (($attr['crop'] & 1) == 0) $src_x = 0;
  55. if ($attr['crop'] & 2) $src_y = 0;
  56. imagecopyresampled( $to_image, $from_image, $dst_x, $dst_y, $src_x, $src_y,
  57. $dst_w, $dst_h, $src_w, $src_h );
  58. }
  59. if (isset($to_image)) {
  60. imagedestroy($from_image);
  61. return $to_image;
  62. }
  63. return $from_image;
  64. }
  65. add_filter('autonav_resize_image', 'autonav_internal_resize', 50, 4);
  66. /* *** Resize function **** */
  67. function resize_crop (&$attr, $prefix) {
  68. // Modifies $attr['pic_thumb'],['thumbwidth'],['thumbheight']
  69. $wp_dir = wp_upload_dir();
  70. $pic_full = $attr['pic_full'];
  71. $pic_full_path = $attr['pic_full_path'];
  72. if ($pic_full_path == '') {
  73. $pic_full_path = trailingslashit($wp_dir['basedir']) . $pic_full;
  74. $attr['pic_full_path'] = $pic_full_path;
  75. }
  76. $pic_full = preg_replace('#-\d+x\d+\.#','.',$pic_full); /* remove, e.g., trailing '-1024x768' */
  77. $info = pathinfo($pic_full); // relative to upload directory
  78. $ext = $info['extension'];
  79. $name = basename($pic_full, ".{$ext}");
  80. // Read source image.
  81. switch (strtolower($ext)) {
  82. case 'jpg':
  83. case 'jpeg':
  84. $from_image = imagecreatefromjpeg($pic_full_path);
  85. break;
  86. case 'png':
  87. $from_image = imagecreatefrompng($pic_full_path);
  88. break;
  89. case 'gif':
  90. $from_image = imagecreatefromgif($pic_full_path);
  91. break;
  92. default:
  93. // Returns either an image resource, or a modified $attr
  94. $from_image = apply_filters('autonav_image_create', NULL, $pic_full_path, $attr, $ext);
  95. if (is_array($from_image)) {
  96. $attr['error'] = $from_image['error'];
  97. return;
  98. }
  99. }
  100. if (!isset($from_image)) {
  101. $attr['error'] = "Failed to read $ext image ($pic_full_path)";
  102. return;
  103. }
  104. if ($prefix == '') {
  105. $prefix = 'thumb'; // default to thumbnail sizes
  106. }
  107. $to_image = apply_filters('autonav_resize_image', $from_image, $attr, $prefix);
  108. if (!isset ($to_image)) {
  109. $attr['error'] = "Resize failed for image ({$pic_full}";
  110. } else {
  111. $to_ext = 'jpg'; // for now, we always create jpeg
  112. $suffix = imagesx($to_image) .'x'. imagesy($to_image);
  113. $to_file = path_join($info['dirname'],"{$name}-{$suffix}.{$to_ext}");
  114. $to_file_path = path_join($wp_dir['basedir'], $to_file);
  115. $to_file_url = path_join($wp_dir['baseurl'], $to_file);
  116. $quality = abs($attr['sharp']);
  117. if ($quality < 10) { $quality = 90; } // specify quality via 'sharpness'
  118. if (!imagejpeg($to_image, $to_file_path, $quality)) { // Creates file
  119. $attr['error'] = "CANNOT CREATE: ".$to_file_path;
  120. } else {
  121. $attr['pic_'.$prefix] = $to_file;
  122. $attr['pic_'.$prefix.'_path'] = $to_file_path;
  123. $attr['pic_'.$prefix.'_url'] = $to_file_url;
  124. }
  125. imagedestroy($to_image);
  126. }
  127. }
  128. /* *** Select filters **** */
  129. function autonav_pick_sort($picked_files, $attr, $pic_size_info) {
  130. // Sort names before picking from Include list:
  131. if (is_array($picked_files)) {
  132. switch (strtolower($attr['order'])) {
  133. case 'desc':
  134. rsort($picked_files, SORT_STRING);
  135. break;
  136. case 'rand':
  137. shuffle($picked_files);
  138. break;
  139. default:
  140. sort($picked_files, SORT_STRING);
  141. }
  142. }
  143. return $picked_files;
  144. }
  145. add_filter('autonav_pick_files','autonav_pick_sort',10,3);
  146. function autonav_select_include ($picked_files, $attr, $pic_size_info) {
  147. // Select pictures based on 'include' parameter
  148. if (strlen($attr['include']) == 0)
  149. return $picked_files;
  150. $included_files = array();
  151. $include_list = explode(',',$attr['include']); // comma split
  152. foreach ($include_list as $ifile) {
  153. // First, match exact filename.
  154. $pf = array_search($ifile, $picked_files);
  155. if ($pf !== FALSE) {
  156. $included_files[] = $ifile;
  157. $picked_files[$pf] = ''; // remove from picked_files
  158. } else {
  159. foreach ($picked_files as &$afile) {
  160. if (!strlen($afile)) continue; // already used this file
  161. if (is_numeric($ifile)) {
  162. // for "include=7" this matches 'file7.jpg' and '7.jpg' but not 'file17.jpg' or '17.jpg'
  163. $match_string = "#^((.*?\\D)?0*$ifile|0*$ifile(.*?\\D)?)\z#";
  164. } else {
  165. $match_string = "#($ifile\z|^$ifile)#i"; // match text at start or end of filename
  166. }
  167. $suffix_match = (preg_match($match_string,$afile));
  168. if ($ifile === $afile || $suffix_match) {
  169. $included_files[] = $afile;
  170. $afile = ''; // do not consider file again (! REMOVES from $picked_files !)
  171. }
  172. }
  173. }
  174. }
  175. return ($included_files);
  176. }
  177. add_filter('autonav_pick_files', 'autonav_select_include', 20, 3);
  178. /* ********************** */
  179. function get_image_thumbnails($pics_info, $attr, $pic_size_info) {
  180. if (!count ($pics_info)) return array();
  181. $wp_dir = wp_upload_dir();
  182. // For each full size image:
  183. // I. Find or create thumbnail:
  184. // if cropping, look for exact cropped size
  185. // else get its size and call wp_constrain_dimensions and look for exactly that size
  186. // II. Find or create constrained full-size image
  187. $full_width = get_option('large_size_w'); $full_height = get_option('large_size_h');
  188. foreach ($pics_info as &$pic_info) { // (! Modifies $pics_info !)
  189. $apic_key = $pic_info['pic_base']; // Picture base name is key into pic_size_info
  190. $pic_info['pic_full'] = $pic_size_info[$apic_key]['full']; // including folder name relative to WP root
  191. $pic_info['pic_full_path'] = path_join($wp_dir['basedir'], $pic_info['pic_full']);
  192. $pic_info['pic_full_url'] = path_join($wp_dir['baseurl'], $pic_info['pic_full']);
  193. // "Full size" images are actually constrained to size chosen in Admin screen.
  194. // This means huge off-the-camera will actually be resized to, for example, 1024 width.
  195. $image_size = getimagesize($pic_info['pic_full_path']);
  196. if (empty($image_size))
  197. $image_size = array(AUTONAV_ARBITRARY_SIZE, AUTONAV_ARBITRARY_SIZE);
  198. $pic_info['fullwidth'] = $image_size[0];
  199. $pic_info['fullheight'] = $image_size[1];
  200. if (($image_size[0] > $full_width) || ($image_size[1] > $full_height)) {
  201. $image_size = wp_constrain_dimensions($image_size[0],$image_size[1],$full_width,$full_height);
  202. $full_size = $image_size[0] . 'x' . $image_size[1];
  203. $pic_info['fullwidth'] = $image_size[0];
  204. $pic_info['fullheight'] = $image_size[1];
  205. $pic_info['crop'] = 0; // always scale these images, never crop
  206. if ($pic_size_info[$apic_key][$full_size] == '') {
  207. // properly sized full image does not exist; create it
  208. resize_crop($pic_info, 'full'); // modifies ['pic_full'], creates ['pic_full_url'] in $pic_info
  209. } else {
  210. $pic_info['pic_full'] = $pic_size_info[$apic_key][$full_size];
  211. $pic_info['pic_full_path'] = path_join($wp_dir['basedir'], $pic_info['pic_full']);
  212. $pic_info['pic_full_url'] = path_join($wp_dir['baseurl'], $pic_info['pic_full']);
  213. }
  214. }
  215. // Find or create thumbnail
  216. if ($pic_info['fullwidth'] <= $attr['width'] && $pic_info['fullheight'] <= $attr['height']) {
  217. // requested full size image already qualifies as a thumbnail
  218. $pic_info['thumbwidth'] = $pic_info['fullwidth'];
  219. $pic_info['thumbheight'] = $pic_info['fullheight'];
  220. $pic_info['pic_thumb'] = $pic_info['pic_full'];
  221. } else {
  222. $size_params = image_resize_dimensions($pic_info['fullwidth'], $pic_info['fullheight'],
  223. $attr['width'], $attr['height'], $attr['crop']);
  224. $pic_info['thumbwidth'] = $size_params[4]; // new width and height, whether cropped or scaled-to-fit
  225. $pic_info['thumbheight'] = $size_params[5];
  226. $thumb_size = $pic_info['thumbwidth']. 'x' . $pic_info['thumbheight'];
  227. $pic_info['pic_thumb'] = $pic_size_info[$apic_key][$thumb_size];
  228. }
  229. $pic_info['sharp'] = $attr['sharp'];
  230. if ($pic_info['pic_thumb'] == '') {
  231. // desired thumbnail does not exist; create it
  232. $pic_info['crop'] = $attr['crop'];
  233. resize_crop($pic_info, 'thumb'); // creates ['pic_thumb'], ['pic_thumb_url'] in $pic_info
  234. } else {
  235. $pic_info['pic_thumb_url'] = path_join($wp_dir['baseurl'], $pic_info['pic_thumb']);
  236. }
  237. // Copy thumbnail properties into image properties
  238. $pic_info['image'] = $pic_info['pic_thumb'];
  239. $pic_info['image_url'] = $pic_info['pic_thumb_url'];
  240. $pic_info['width'] = $pic_info['thumbwidth'];
  241. $pic_info['height'] = $pic_info['thumbheight'];
  242. $pic_info['linkto'] = $attr['linkto'];
  243. $pic_info['class'] = $attr['class'].'-image';
  244. }
  245. return($pics_info);
  246. }
  247. add_filter('autonav_get_thumbnails', 'get_image_thumbnails', 10, 4);
  248. /* ********************** */
  249. function get_images_from_folder($attr) {
  250. global $post;
  251. global $cached_pic_size_info; // since 1.4.3 -- Cache directory info
  252. $wp_dir = wp_upload_dir();
  253. if (!array_key_exists('basedir',$wp_dir)) {
  254. print "<!-- " . $wp_dir['error'] . " -->\n";
  255. return;
  256. }
  257. $pics_info = array();
  258. if (substr($attr['display'],0,1) == '/') {
  259. // Display images from a folder. NOTE: Absolute paths OK and are
  260. // handled properly by path_join(). We then force a relative path.
  261. $full_path = trailingslashit(path_join($wp_dir['basedir'],substr($attr['display'],1)));
  262. $folder = str_replace(trailingslashit($wp_dir['basedir']),'',$full_path);
  263. // Retrieve file list sans reliance on the (possibly unavailable) glob() function.
  264. $picked_files = array();
  265. $pic_size_info = array(); // Sizes available for each picture
  266. if (is_array($cached_pic_size_info[$full_path])) {
  267. $pic_size_info = $cached_pic_size_info[$full_path];
  268. $picked_files = array_keys($pic_size_info);
  269. } else {
  270. if (($dir = opendir(path_join($wp_dir['basedir'], $folder))) == false) {
  271. print "ERROR: opendir('" . path_join($wp_dir['basedir'], $folder) . "') failed";
  272. } else {
  273. while (($file = readdir($dir)) !== false) {
  274. // Each image in the directory is either full-size, or thumbnail
  275. // [See: Note 20120111 in readme.txt]
  276. $afile = strlen($folder) ? path_join($folder, $file) : $file;
  277. if (preg_match('#^(.*?)(?:-(\d+x\d+))?\.(\w+)\Z#',$file,$filebits)) {
  278. switch (strtolower($filebits[3])) {
  279. case 'jpeg':
  280. case 'jpg':
  281. case 'png':
  282. case 'gif':
  283. if (strlen($filebits[2])) { // resized image
  284. $pic_size_info[$filebits[1]][$filebits[2]] = $afile;
  285. } else { // fullsize
  286. $picked_files[] = $filebits[1];
  287. $pic_size_info[$filebits[1]]['full'] = $afile;
  288. $pic_size_info[$filebits[1]]['pic_full_path'] = path_join($full_path,$afile);
  289. }
  290. break;
  291. }
  292. }
  293. }
  294. closedir($dir);
  295. }
  296. $cached_pic_size_info[$full_path] = $pic_size_info;
  297. }
  298. // Sort list, then apply Include list, per defined filters.
  299. $picked_files = apply_filters('autonav_pick_files', $picked_files, $attr, $pic_size_info);
  300. if (!is_array($picked_files))
  301. return ($pics_info);
  302. // Build preliminary pics_info array:
  303. $pics_info = array();
  304. foreach ($picked_files as $pic_base) {
  305. if (strlen($pic_size_info[$pic_base]['full'])) // we have a full-size image
  306. $pics_info[] = array('pic_base' => $pic_base);
  307. }
  308. // Choose from available sizes, or create resized images.
  309. $pics_info = apply_filters('autonav_get_thumbnails', $pics_info, $attr, $pic_size_info);
  310. }
  311. return ($pics_info);
  312. }
  313. /* ********************** */
  314. function create_images_for($attr, $pic_fullsize) {
  315. $info = pathinfo($pic_fullsize);
  316. $dir = $info['dirname'];
  317. $ext = $info['extension'];
  318. $name = basename($pic_fullsize, ".$ext");
  319. // Get attachment image from the folder where it was uploaded.
  320. $attr['display'] = "/$dir";
  321. $attr['include'] = $name;
  322. $pic_info = get_images_from_folder($attr);
  323. return (is_array($pic_info)) ? $pic_info[0] : 0; // first image, or failure
  324. }
  325. function pic_info_for($attr, $id, $attach_info) {
  326. $attached_pic = get_attached_file($id);
  327. if ($attached_pic == '') return; // cannot find the attachment
  328. $pic_info = create_images_for($attr, $attached_pic);
  329. if (is_array($pic_info)) {
  330. $post_info = get_post($id); // the attachment's post
  331. $pic_info['id'] = $id;
  332. // Attachment texts
  333. $pic_info['caption'] = $post_info->post_excerpt;
  334. $pic_info['description'] = $post_info->post_content;
  335. $pic_info['title'] = $post_info->post_title;
  336. if (isset($attach_info['menu_order']))
  337. $pic_info['menu_order'] = $attach_info['menu_order'];
  338. $alt = get_post_meta($id, '_wp_attachment_image_alt', true);
  339. $pic_info['attpage'] = get_attachment_link($id);
  340. if(count($alt)) $pic_info['alt_text'] = $alt; // Attachment: Alternate Text
  341. return $pic_info;
  342. }
  343. return;
  344. }
  345. /* **** postid handlers **** */
  346. function get_actual_pid ($pids) {
  347. // Handle the 'include' list which autonav_get_postid_modifiers()
  348. // (below) splits from the postid="" parameter. Permit list of ids,
  349. // post-slugs, and page-paths
  350. $pids_array = explode(',',$pids);
  351. if (is_array($pids_array)) {
  352. foreach ($pids_array as &$pid) {
  353. if (strlen($pid) && !is_numeric($pid)) {
  354. // Look first for post/page by slug, then for page by full path
  355. $get_obj = get_posts(array('name' => $pid, 'post_type' => array('post', 'page')));
  356. if (count($get_obj)) {
  357. $pid = $get_obj[0]->ID;
  358. } else {
  359. $get_obj = get_page_by_path($pid);
  360. $pid = $get_obj->ID;
  361. }
  362. }
  363. }
  364. return $pids_array;
  365. }
  366. return array();
  367. }
  368. function autonav_get_postid_modifiers ($attr, $param = 'include') {
  369. // Pre-process the postid= parameter, in the form
  370. // "include,include,param1:param1val,param1val, param2:param2val,param2val"
  371. $parsed_bits = array();
  372. $bits = explode(',',$attr['postid']); // may return keys with empty values!
  373. foreach ($bits as $bit) {
  374. $bitvalues = preg_split("/[=:]/",$bit,2);
  375. if (!empty($bitvalues[1])) {
  376. $param = trim(array_shift($bitvalues));
  377. if ($param == 'cat') $param = 'category'; // shortcut
  378. }
  379. $bitvalues[0] = trim($bitvalues[0]);
  380. if (strlen($bitvalues[0])) { // ignore empty
  381. $parsed_bits[$param][] = $bitvalues[0];
  382. }
  383. }
  384. return $parsed_bits;
  385. }
  386. /* ********************** */
  387. function get_images_attached($attr, $pids, $limit) {
  388. global $post;
  389. $query = array();
  390. $child_pages = array();
  391. $attr['postid'] = $pids;
  392. $selectors = autonav_get_postid_modifiers($attr);
  393. foreach ($selectors as $key => $avalue) {
  394. $value = implode(',',$avalue);
  395. switch ($key) {
  396. case 'include':
  397. if (empty($value)) $value = $post->ID;
  398. $child_pages = get_actual_pid($value);
  399. break;
  400. case 'tags':
  401. $key = 'tag';
  402. case 'tag':
  403. case 'category':
  404. $att_tax = $attr["attach_$key"];
  405. if (strlen($att_tax)) {
  406. // Support taxonomies created by the Media Tags or Attachment Taxonomy plugins
  407. $query['tax_query'] = array(array('taxonomy' => $att_tax,
  408. 'field' => 'slug',
  409. 'terms' => explode(',',$value)));
  410. }
  411. break;
  412. case 'author': // NOTE: WP creates but no default way to edit for attachments
  413. $value = preg_replace('#\*#',$post->post_author,$value);
  414. $query['authors']=$value;
  415. break;
  416. case 'status':
  417. $value = preg_replace('#\*#',$post->post_status,$value);
  418. $query['post_status']=$value;
  419. break;
  420. default: // NOTE: attachments don't by default support custom fields
  421. $query['meta_key']=$type;
  422. $query['meta_value']=$value;
  423. }
  424. }
  425. // NOTE: Possibly use $attr['orderby'] directly at risk of breaking backwards compability
  426. $query['orderby'] = strtolower($attr['order']) == 'rand' ? 'rand' :
  427. empty($attr['orderby']) ? 'menu_order' : strtolower($attr['orderby']);
  428. $query['order'] = strtolower($attr['order']) == 'desc' ? 'desc' : 'asc';
  429. $query['post_status'] = 'inherit'; // prevents finding draft or private
  430. $query['numberposts'] = $limit >= 1 ? $limit : -1;
  431. $query['post_type'] = 'attachment';
  432. $query['post_mime_type'] = array('image'); // ,'application/pdf'); // later
  433. if ($attr['count']) { $query['numberposts'] = $attr['count']; }
  434. if ($attr['start']) { $query['offset'] = $attr['start']; }
  435. $pics_info = array();
  436. if (empty($child_pages)) {
  437. $child_pages[0] = $post->ID;
  438. }
  439. if (!empty($attr['ids'])) { // compatibility with WP 3.5+ [gallery ids='']
  440. $child_pages[0] = -1;
  441. $query['include'] = $attr['ids'];
  442. if ( $attr['orderby'] == 'menu_order' ) // menu_order default? instead, use exact ordered list. (user can override)
  443. $query['orderby'] = 'post__in';
  444. }
  445. foreach ($child_pages as $pid) {
  446. if ($pid >= 0) { # '-1' for ANY
  447. $query['post_parent'] = $pid;
  448. }
  449. $attachments = get_posts($query);
  450. if (empty ($attachments)) return $pics_info;
  451. foreach ($attachments as $attach_info) {
  452. if ($attach_info->menu_order < -100) continue; // permit disabling images via menu_order
  453. $pic_info = pic_info_for($attr,$attach_info->ID, array());
  454. if (is_array($pic_info))
  455. $pics_info[] = $pic_info;
  456. }
  457. }
  458. return $pics_info;
  459. }
  460. /* ********************** */
  461. function get_attachments($attr, $pid, $limit) {
  462. global $post;
  463. if (function_exists('attachments_get_attachments')) {
  464. $pids = get_actual_pid(strlen($pid) ? $pid : $post->ID);
  465. if (is_array($pids)) {
  466. $attachments = attachments_get_attachments($pids[0]);
  467. $pics_info = array();
  468. // Title, caption override?
  469. foreach ($attachments as $attach_info) {
  470. $pic_info = pic_info_for($attr,$attach_info['id'], $attach_info);
  471. if (is_array($pic_info))
  472. $pics_info[] = $pic_info;
  473. }
  474. }
  475. return $pics_info;
  476. }
  477. }
  478. /* **************************
  479. Thumbnail helper functions
  480. **************************
  481. */
  482. function autonav_thumb_featured ( $pic_info, $attr, $post ) {
  483. // Use featured image
  484. if (empty($pic_info)) {
  485. /* NOTE: below is undef without add_theme_support('post-thumbnails'); in functions.php */
  486. if (function_exists('get_post_thumbnail_id')) {
  487. $tid = get_post_thumbnail_id($post->ID);
  488. if ($tid) {
  489. $pic_info = pic_info_for($attr, $tid, array());
  490. }
  491. }
  492. }
  493. return $pic_info;
  494. }
  495. add_filter('autonav_thumb', 'autonav_thumb_featured', 10, 4);
  496. function autonav_thumb_specified( $pic_info, $attr, $post ) {
  497. if (empty($pic_info)) {
  498. $ximg = get_post_meta($post->ID, 'subpage_thumb', 1);
  499. if ($ximg != '') { // Specified exact thumbnail image
  500. if ( preg_match( '|^https?://|i', $ximg ) ) {
  501. $pic_info['image_url'] = $ximg; // as explicit URL
  502. $pic_info['class'] = $attr['class'].'-image';
  503. } else {
  504. // local file... assume full-size picture given, and automagically create thumbnail
  505. $pic_info = create_images_for($attr, $ximg);
  506. }
  507. }
  508. }
  509. return $pic_info;
  510. }
  511. add_filter('autonav_thumb', 'autonav_thumb_specified', 20, 4);
  512. function autonav_thumb_attached( $pic_info, $attr, $post ) {
  513. if (empty($pic_info)) {
  514. $attr['order'] = 'ASC';
  515. $pics = get_images_attached($attr, $post->ID, 1);
  516. if (is_array($pics)) {
  517. $pic_info = $pics[0]; // should be exactly one
  518. }
  519. }
  520. return $pic_info;
  521. }
  522. add_filter('autonav_thumb', 'autonav_thumb_attached', 30, 4);
  523. /* ********************** */
  524. function get_pics_info($attr, $pages) {
  525. // Called with a list of either posts or pages (or even custom post-types).
  526. $wp_dir = wp_upload_dir(); // ['basedir'] is local path, ['baseurl'] as seen from browser
  527. $disp_pages = array();
  528. $picpages_only = $attr['pics_only'];
  529. foreach ($pages as $page) {
  530. $pic_info = array();
  531. $pic_info = apply_filters( 'autonav_thumb', $pic_info, $attr, $page );
  532. if ((!$picpages_only) || $pic_info['image_url'] != '') {
  533. $pic_info['linkto'] = $attr['linkto'];
  534. $pic_info['page'] = $page;
  535. switch($pic_info['linkto']) {
  536. case 'pic':
  537. case 'file': // compatibility with [gallery]
  538. $pic_info['permalink'] = $pic_info['pic_full_url'];
  539. case 'none': // no link at all
  540. break;
  541. default:
  542. $pic_info['permalink'] = get_permalink($page->ID);
  543. }
  544. $pic_info['excerpt'] = get_post_meta($page->ID, 'subpage_excerpt', 1);
  545. if ($pic_info['excerpt'] == '') $pic_info['excerpt'] = $page->post_excerpt;
  546. $pic_info['title'] = get_post_meta($page->ID, 'subpage_title', 1);
  547. if ($pic_info['title'] == '') $pic_info['title'] = $page->post_title;
  548. $disp_pages[] = $pic_info;
  549. }
  550. }
  551. return $disp_pages;
  552. }
  553. function autonav_wl_standardize_orderby ($orderby) {
  554. // Prefix with post_ to match database table column names
  555. if ((strpos($$orderby, 'post_') === false) &&
  556. in_array($orderby,
  557. array('author', 'date', 'modified', 'parent', 'title', 'excerpt', 'content'))) {
  558. $orderby = 'post_' . $orderby;
  559. // Not requiring post_ prefix: comment_status, comment_count, menu_order, ID
  560. }
  561. return $orderby;
  562. }
  563. /* **** Page and Post handlers **** */
  564. function get_subpages ($attr) {
  565. global $post;
  566. $query = array();
  567. $child_pages = array();
  568. $selectors = autonav_get_postid_modifiers($attr);
  569. foreach ($selectors as $key => $avalue) {
  570. $value = implode(',',$avalue);
  571. switch ($key) {
  572. case 'include':
  573. $child_pages = get_actual_pid($value);
  574. break;
  575. case 'category': // pages don't support these
  576. case 'tag':
  577. case 'tags':
  578. break;
  579. case 'author': /* postid="author:4" */
  580. $value = preg_replace('#\*#',$post->post_author,$value);
  581. $query['authors']=$value;
  582. break;
  583. case 'status':
  584. $value = preg_replace('#\*#',$post->post_status,$value);
  585. $query['post_status']=$value;
  586. break;
  587. default: /* postid="custom-field:value" */
  588. $query['meta_key']=$key;
  589. $query['meta_value']=$value;
  590. }
  591. }
  592. $my_children = 0;
  593. $home_base = 0;
  594. if ($attr['siblings']) {
  595. if ($post->post_parent) { // children of our parent
  596. $child_pages = array($post->post_parent);
  597. } else {
  598. if ($post->post_type == 'page') {
  599. $child_pages = array(0); // children of home page
  600. }
  601. }
  602. if (!$attr['self']) { // add ourselves to exception list
  603. $attr['exclude'][] = $post->ID;
  604. }
  605. } else {
  606. if (!$child_pages[0]) { // no postid: select our children.
  607. // Are we the static home page?
  608. $home_base = ( (get_option('show_on_front') == 'page') &&
  609. (get_option('page_on_front') == $post->ID ) );
  610. $child_pages = array($post->ID);
  611. $my_children = 1;
  612. }
  613. }
  614. $query['echo'] = 0;
  615. $query['title_li'] = 0;
  616. $query['sort_column'] = autonav_wl_standardize_orderby($attr['orderby']);
  617. if (is_array ($attr['exclude']))
  618. $query['exclude'] = $attr['exclude'];
  619. $base_query = $query;
  620. $pages = array();
  621. foreach ($child_pages as $child_of) {
  622. $query = $base_query;
  623. $query['child_of'] = $child_of;
  624. if (!$attr['family']) { // Only children of this page
  625. $query['hierarchical'] = 0;
  626. $query['parent'] = $child_of;
  627. }
  628. $these_pages = & get_pages($query);
  629. if ($home_base && !count($these_pages)) {
  630. // Static home page, with no children. Look for siblings: children of page '0'.
  631. $query['child_of'] = 0;
  632. $query['parent'] = 0;
  633. if (!$attr['self']) { // except ourself (will the "real" homepage please stand up)
  634. $query['exclude'][] = $post->ID;
  635. }
  636. $these_pages = & get_pages($query);
  637. }
  638. if (count ($these_pages)) {
  639. foreach ($these_pages as $subpage) {
  640. array_push($pages, $subpage);
  641. }
  642. } else {
  643. // If specified a different page with no subpages, use that page alone.
  644. // i.e., If listing "my" subpages, and I haven't any, don't list "me."
  645. if ($my_children == 0) {
  646. $these_pages = get_pages("include=$child_of&echo=0&title_li=0");
  647. array_splice($pages, count($pages), 0, $these_pages);
  648. }
  649. }
  650. }
  651. if (count($pages) == 0) {
  652. return;
  653. }
  654. switch (strtolower($attr['order'])) {
  655. case 'desc':
  656. $pages = array_reverse($pages);
  657. break;
  658. case 'rand':
  659. shuffle($pages);
  660. break;
  661. }
  662. return get_pics_info($attr, $pages);
  663. }
  664. function get_selposts($attr) {
  665. global $post;
  666. $query = array();
  667. $selectors = autonav_get_postid_modifiers($attr);
  668. foreach ($selectors as $key => $avalue) {
  669. $value = implode(',',$avalue);
  670. $numeric_value = preg_match('#^[-0-9,]+#', $value); /* accept '5,-3' as all numeric */
  671. switch ($key) {
  672. case 'include':
  673. $query[$key] = get_actual_pid($value);
  674. break;
  675. case 'tag__and':
  676. case 'tag__in':
  677. case 'tag__not_in':
  678. if (!$numeric_value)
  679. $key = preg_replace('#tag_#', 'tag_slug_', $key);
  680. case 'tag_slug__and':
  681. case 'tag_slug__in':
  682. $query[$key] = $avalue;
  683. $key = 'post_tag';
  684. break;
  685. case 'tag':
  686. case 'tags':
  687. $query[$key] = $value;
  688. $key='post_tag';
  689. break;
  690. case 'category':
  691. $key='category__in';
  692. case 'category__and':
  693. case 'category__in':
  694. case 'category__not_in':
  695. $cur_cats = wp_get_post_categories($post->ID);
  696. if (is_array($cur_cats)) {
  697. $cur_cats = implode(',',$cur_cats);
  698. $numeric_value = 1;
  699. } else {
  700. $cur_cats = '';
  701. }
  702. $value = preg_replace('#\*#',$cur_cats,$value);
  703. $query[$key]=explode(',',$value);
  704. foreach ($query[$key] as &$catvalue) { // modify in situ
  705. if (absint($catvalue) !== $catvalue) {
  706. $cat_obj = get_category_by_slug($catvalue); // support category slugs here
  707. if (is_object($cat_obj)) {
  708. $catvalue = $cat_obj->term_id;
  709. }
  710. }
  711. }
  712. $key='category';
  713. break;
  714. case 'author':
  715. $value = preg_replace('#\*#',$post->post_author,$value);
  716. $query[$numeric_value ? 'author' : 'author_name']=$value;
  717. break;
  718. case 'status':
  719. $value = preg_replace('#\*#',$post->post_status,$value);
  720. $query['post_status']=$value;
  721. break;
  722. default: // First check for custom taxonomies; otherwise, use custom fields.
  723. if (taxonomy_exists($key)) {
  724. $query[$key]=$value;
  725. } else {
  726. $query['meta_key']=$key;
  727. $query['meta_value']=$value;
  728. }
  729. }
  730. if ($key != 'include' && empty($attr['taxonomy']) && strlen($key))
  731. $attr['taxonomy'] = $key; // Purely for CSS purposes
  732. }
  733. if (is_array($attr['exclude']))
  734. $query['exclude'] = $attr['exclude'];
  735. if (!$attr['self']) { // add ourselves to exception list
  736. $query['exclude'][] = $post->ID;
  737. }
  738. if (preg_match('#^posts\s*:\s*(.*)#', $attr['display'], $value)) {
  739. $query['post_type'] = $value[1]; // custom post type
  740. }
  741. if (preg_match("#^meta:(.+)#i", $attr['orderby'], &$value)) {
  742. $query['meta_key'] = $value[1];
  743. $attr['orderby']='meta_value';
  744. }
  745. if (strtolower($attr['order']) == 'rand') {
  746. $attr['orderby'] = 'rand'; // for backwards compatibility
  747. $attr['order'] = '';
  748. }
  749. if (strtolower($attr['orderby']) == 'menu_order') { // useless for posts
  750. $attr['orderby'] = 'post_date'; // a sensible default, and backwards compatible
  751. if (strtoupper($attr['order']) == $attr['order']) { // default order? override
  752. $attr['order'] = 'desc';
  753. }
  754. }
  755. if (strtolower($attr['orderby']) == 'postmash') { // use menu_order, but NOT orderby=post_date.
  756. $attr['orderby'] = 'menu_order';
  757. }
  758. foreach (array('count' => 'numberposts', 'start' => 'offset',
  759. 'order' => 'order', 'orderby' => 'orderby') as $k => $v) {
  760. if ($attr[$k]) { $query[$v] = $attr[$k]; }
  761. }
  762. $these_posts = get_posts($query);
  763. if (count($these_posts) == 0) {
  764. return;
  765. }
  766. return get_pics_info($attr, $these_posts);
  767. }
  768. /* ********************** */
  769. function prepare_picture (&$pic) { /* (! modifies $pic !) */
  770. $alt_text = strlen($pic['alt_text']) ? $pic['alt_text'] : $pic['title'];
  771. if (strlen($pic['error'])) {
  772. $error_print = $pic['pic_full_url'];
  773. } else {
  774. if (strlen($pic['image_url'])) {
  775. $pic['content'] =
  776. an_create_tag('img', array('src' => $pic['image_url'], 'alt' => $alt_text,
  777. 'width' => $pic['width'], 'height' => $pic['height'],
  778. 'class' => $pic['class']));
  779. } else {
  780. $pic['error'] = 'Missing image';
  781. $error_print = apply_filters('autonav_missing_image',__($pic['error']), $pic);
  782. if (is_object($pic['page'])) {
  783. $pic['error'] .= __(' for postid=').$pic['page']->ID;
  784. }
  785. }
  786. }
  787. if (strlen($pic['error'])) {
  788. $pic['content'] = an_create_tag('span', array('class' => implode(' ',array('autonav-error', $pic['class'])))) .
  789. "<!-- {$pic['error']} -->{$error_print}</span>\n";
  790. }
  791. if ($pic['permalink'] == '') {
  792. switch ($pic['linkto']) {
  793. case 'pic':
  794. $pic['permalink'] = $pic['pic_full_url']; // link to fullsize image
  795. break;
  796. case 'attpage':
  797. $pic['permalink'] = $pic['attpage'];
  798. break;
  799. }
  800. }
  801. }
  802. /* **** Output helpers **** */
  803. function an_create_output_picture ($html, $class, $pic, $attr) {
  804. // Outputs the picture in element for a single post/page
  805. $my_html = $pic['content'];
  806. if ( $attr['thumb'] ) {
  807. if (strlen($pic['permalink']) > 0) { // when linkto='none', permalink will be empty
  808. $anchor = array('href' => $pic['permalink']);
  809. if ($pic['linkto'] == 'pic')
  810. $anchor['rel'] = $attr['_img_rel'];
  811. if (strlen($pic['title']) && ! $attr['titles'])
  812. $anchor['title'] = $pic['title'];
  813. if (strlen($attr['target']))
  814. $anchor['target'] = $attr['target'];
  815. $my_html = an_create_tag('a', $anchor) . $my_html . '</a>'; // wrap content
  816. }
  817. $my_html = an_create_tag('span', array('class' => $class.'-'.$attr['display'].'-image')) .
  818. $my_html . '</span>';
  819. }
  820. return $html . $my_html;
  821. }
  822. function an_create_output_text ($html, $class, $pic, $attr) {
  823. // Outputs the text element for a single post/page
  824. $my_html = '';
  825. if (strlen($pic['title']) && $attr['titles']) {
  826. $my_html = $pic['title'];
  827. if (strlen($pic['permalink']) > 0) {
  828. $anchor = array('href' => $pic['permalink']);
  829. if (strlen($attr['target']))
  830. $anchor['target'] = $attr['target'];
  831. $my_html = an_create_tag('a',$anchor) . $my_html . '</a>';
  832. }
  833. if (!$attr['list']) {
  834. $my_html = an_create_tag('p',array('class' => "{$class}-text")) . $my_html . '</p>';
  835. }
  836. }
  837. return $html . $my_html;
  838. }
  839. // backwards compatibility
  840. function an_create_output_table_text ($html, $class, $pic, $attr) {
  841. return an_create_output_text($html, $class, $pic, $attr);
  842. }
  843. function an_create_output_excerpt ($html, $class, $pic, $attr) {
  844. if ($attr['excerpt'] && strlen($pic['excerpt'])) {
  845. $html .= an_create_tag('p', array('class' => "{$class}-excerpt")) . "{$pic['excerpt']}</p>\n";
  846. }
  847. return $html;
  848. }
  849. function an_create_page_links($html, $class, $total_pages, $cur_page) {
  850. $html .= an_create_tag('p', array('class' => "{$class}-pages"));
  851. // Possibly permit override of 'next_text', 'prev_text', etc. - see /wp-includes/general_template.php
  852. $paginate_args = array('base' => get_permalink() . '/%_%',
  853. 'total' => $total_pages, 'current' => $cur_page, 'show_all' => 1);
  854. $mybase = get_permalink();
  855. $paginate_args['format'] = '%#%';
  856. $html .= paginate_links($paginate_args);
  857. $html .= '</p>';
  858. return $html;
  859. }
  860. add_filter('autonav_create_list_item', 'an_create_output_text', 10, 4);
  861. add_filter('autonav_create_list_item', 'an_create_output_picture', 15, 4);
  862. add_filter('autonav_create_list_item', 'an_create_output_excerpt', 20, 4);
  863. add_filter('autonav_create_table_item', 'an_create_output_picture', 10, 4);
  864. add_filter('autonav_create_table_item', 'an_create_output_text', 15, 4);
  865. add_filter('autonav_create_table_item', 'an_create_output_excerpt', 20, 4);
  866. add_filter('autonav_create_page_links', 'an_create_page_links', 10, 4);
  867. /* **** Main output function **** */
  868. function an_create_unit_class($attr, $pic, $class) {
  869. if (is_object($pic['page'])) {
  870. if ($pic['page']->ID == $attr['current']) {
  871. $class .= ' ' . $class . '-current';
  872. }
  873. }
  874. return $class;
  875. }
  876. function create_output($attr, $pic_info) {
  877. if (!array($pic_info)) { return ''; }
  878. if ($attr['start'] > 0) {
  879. $pic_info = array_slice($pic_info, $attr['start']);
  880. }
  881. if ($attr['count'] > 0) {
  882. $pic_info = array_slice($pic_info, 0, $attr['count']);
  883. }
  884. if (!is_array($pic_info) || (count($pic_info) == 0)) { // nothing to do
  885. return '';
  886. }
  887. $total_pages = 1;
  888. // Pagination: Break candidate images, selected above, into pages.
  889. if ($attr['paged'] > 0) {
  890. $total_pages = ceil(count($pic_info) / $attr['paged']);
  891. $cur_page = 1;
  892. global $wp_query; // For pagination
  893. if( isset( $wp_query->query_vars['paged'] )) {
  894. // no page number, or page 1, gives offset 0.
  895. $cur_page = max(1, $wp_query->query_vars['page'] );
  896. }
  897. // Now select only current page.
  898. $pic_info = array_slice($pic_info, ($cur_page - 1) * $attr['paged'], $attr['paged']);
  899. }
  900. $html = '';
  901. $class = $attr['class'];
  902. if ($attr['display'] == 'list' || $attr['list']) { // Produce list output
  903. $html = an_create_tag(($attr['plain'] ? 'div': 'ul'),
  904. array('class' => $class) );
  905. foreach ($pic_info as $pic) { // well, really the page not a picture
  906. if ($attr['thumb']) {
  907. prepare_picture($pic);
  908. }
  909. $my_html = $attr['plain'] ? '' : an_create_tag('li', array('class' => an_create_unit_class($attr, $pic, $class . '-item')));
  910. $html .= apply_filters('autonav_create_list_item', $my_html, $class, $pic, $attr);
  911. if (!$attr['plain']) { $html .= "</li>\n"; }
  912. }
  913. $html .= $attr['plain'] ? "</div>\n" : "</ul>\n";
  914. } else { // Produce table output
  915. $viewer = $attr['imgrel'];
  916. if (strpos($viewer, '*')) {
  917. $viewer = str_replace( '*', ($attr['group']!='') ? '['.$attr['group'].']' : '', $viewer);
  918. }
  919. $attr['_img_rel'] = $viewer;
  920. $html = '';
  921. $col = 0; $row = 0;
  922. $maxcol = $attr['columns'];
  923. $indiv_rows = $attr['combine'] == 'none'; // true when 'none', false otherwise
  924. $widow_row = $attr['combine'] == 'full'; // place widow row in separate table
  925. $start_table = an_create_tag('table', array('class' => $class . '-table'));
  926. $end_table = "</table>\n";
  927. $in_table = 0;
  928. $start_row = an_create_tag('tr', array('class' => $class . '-row'));
  929. $end_row = "</tr>\n";
  930. $in_row = 0;
  931. $html = $start_table; $in_table = 1;
  932. if (strlen($attr['caption'])) { // only on first table
  933. $html .= an_create_tag('caption', array('class' => $class . '-caption')) . $attr['caption'] . '</caption>';
  934. }
  935. foreach ($pic_info as $pic) {
  936. prepare_picture($pic);
  937. if ($col == 0) {
  938. if ($row > 0 && $widow_row && ((count($pic_info) - ($row * $maxcol)) < $maxcol)) {
  939. $indiv_rows = 1; // reached last (widow) row; switch to separate tables.
  940. $html .= $end_table; $in_table = 0;
  941. }
  942. if ($indiv_rows && ($row > 0)) {
  943. $html .= $start_table; $in_table = 1;
  944. }
  945. $html .= $start_row; $in_row = 1;
  946. }
  947. $my_html = an_create_tag('td', array('class' => an_create_unit_class($attr, $pic, $class . '-cell')));
  948. $html .= apply_filters('autonav_create_table_item', $my_html, $class, $pic, $attr) . "</td>\n";
  949. $col++;
  950. if ($col >= $maxcol) {
  951. if ($in_row) { $html .= $end_row; $in_row = 0; }
  952. if ($indiv_rows) {
  953. $html .= $end_table; $in_table = 0;
  954. }
  955. $col = 0;
  956. $row++;
  957. }
  958. }
  959. if ($in_row) { $html .= $end_row; }
  960. if ($in_table) { $html .= $end_table; }
  961. }
  962. if ($total_pages > 1) { // display pagination links
  963. $html = apply_filters('autonav_create_page_links',$html, $class, $total_pages, $cur_page);
  964. }
  965. return $html;
  966. }
  967. /* ********************** */
  968. function autonav_wl_shortcode($attr) {
  969. global $post;
  970. // NOTE: This function can be added as a filter to override the standard Gallery shortcode.
  971. // In that case, this function may return an empty string to restore default behavior.
  972. if (!function_exists('imagecreatefromjpeg')) {
  973. print ("<span style=\"color:red; font-weight: bold;\">ERROR:</span> imagecreatefromjpeg() must be installed. On Ubuntu, \
  974. use: <b><tt>apt-get install php5-gd</tt></b> Use yum on RedHat/CentOS, or similarly for your system.<br>\n");
  975. return;
  976. }
  977. // compatibility with [gallery]
  978. $wp_gallery_codes = array('id' => 'postid', 'link' => 'linkto');
  979. foreach ($wp_gallery_codes as $wp => $autonav) {
  980. if (!empty($attr[$wp]))
  981. $attr[$autonav] = $attr[$wp];
  982. }
  983. $options = get_option('autonav_wl'); // Default values come from saved configuration
  984. // permit in shortcode_atts():
  985. $options['linkto'] = '';
  986. $options['include'] = '';
  987. $attr['order'] = strtolower($attr['order']); // so we can make 'desc' default for posts, regardless of option setting
  988. $attr = (shortcode_atts($options, $attr));
  989. if (in_array($attr['size'],get_intermediate_image_sizes())) {
  990. $size_list = image_constrain_size_for_editor(AUTONAV_FORCE_CONSTRAIN, AUTONAV_FORCE_CONSTRAIN, $attr['size']);
  991. $attr['size'] = $size_list[0].'x'.$size_list[1];
  992. } elseif (substr($attr['size'],0,5) == 'size_') {
  993. $attr['size'] = $attr[$attr['size']]; // e.g., size_small --> 150x120
  994. }
  995. if (!preg_match('#(\d+)x(\d+)#',$attr['size'],$size)) {
  996. if ($attr['columns'] <= $attr['col_large']) {
  997. $attr['size'] = $attr['size_large'];
  998. } elseif ($attr['columns'] >= $attr['col_small']) {
  999. $attr['size'] = $attr['size_small'];
  1000. } else {
  1001. $attr['size'] = $attr['size_med'];
  1002. }
  1003. }
  1004. if (!preg_match('#(\d+)x(\d+)#',$attr['size'],$sizebits)) {
  1005. return 'Incorrect size specified: '. $attr['size'];
  1006. } else {
  1007. $attr['width'] = $sizebits[1];
  1008. $attr['height'] = $sizebits[2];
  1009. }
  1010. if (strlen($attr['exclude'])) {
  1011. $attr['exclude'] = get_actual_pid($attr['exclude']);
  1012. }
  1013. $display_options = explode(',', $attr['display']);
  1014. $attr['display'] = array_shift($display_options);
  1015. if (empty($attr['display']) && !empty($attr['ids'])) { // compatibility with [gallery]
  1016. $attr['display'] = 'attach';
  1017. }
  1018. // mode specific defaults:
  1019. if ($attr['display'] == 'list') {
  1020. $attr['titles'] = 1;
  1021. $attr['list'] = 1;
  1022. $attr['thumb'] = 0;
  1023. } else {
  1024. $attr['thumb'] = 1;
  1025. }
  1026. // Absent user override, default based on mode
  1027. if (!strlen($attr['linkto'])) {
  1028. $attr['linkto'] = (substr($attr['display'],0,6) == 'attach') ? 'pic' : 'page';
  1029. }
  1030. // process options
  1031. foreach ($display_options as $o) {
  1032. $optval = 1;
  1033. $o = trim($o);
  1034. if (substr($o, 0, 2) == 'no') { // no___ = disable option
  1035. $optval = 0;
  1036. $o = substr($o, 2);
  1037. }
  1038. switch ($o) {
  1039. case 'title': $o = 'titles';
  1040. case 'titles': // eponymous boolean options
  1041. case 'excerpt':
  1042. case 'thumb':
  1043. case 'siblings':
  1044. case 'family':
  1045. case 'self':
  1046. case 'plain':
  1047. case 'list': $attr[$o] = $optval; break;
  1048. case 'image': $attr['linkto'] = 'pic'; break;
  1049. case 'page': $attr['linkto'] = 'attpage'; break;
  1050. case 'link': $attr['linkto'] = 'none'; break;
  1051. }
  1052. }
  1053. if (!strlen($attr['class'])) $attr['class'] = 'subpages';
  1054. // Plugin/Theme can override here
  1055. $attr = apply_filters('autonav_pre_select', $attr, $display_options);
  1056. $attr['current'] = $post->ID;
  1057. if (($attr['display'] == 'list') || ($attr['display'] == 'images')) {
  1058. $pic_info = get_subpages($attr);
  1059. } elseif (substr($attr['display'],0,6) == 'attach') {
  1060. $post_id = $attr['postid'];
  1061. if (strlen($post_id)==0) {
  1062. $post_id = $post->ID;
  1063. }
  1064. if ($attr['display'] == 'attachments') {
  1065. $pic_info = get_attachments($attr, $post_id, 0);
  1066. } else {
  1067. $pic_info = get_images_attached($attr, $post_id, 0);
  1068. $attr['start'] = 0; // start,count handled by get
  1069. $attr['count'] = 0;
  1070. }
  1071. } elseif (substr($attr['display'], 0, 5) == 'posts') {
  1072. $pic_info = get_selposts($attr);
  1073. $attr['start'] = 0; // start,count handled by get
  1074. $attr['count'] = 0;
  1075. } elseif (substr($attr['display'], 0, 1) == '/') { // looks like a directory name
  1076. if ($attr['linkto'] != 'none') $attr['linkto'] = 'pic'; // unless explicitly no links
  1077. $pic_info = get_images_from_folder($attr);
  1078. } else { // permit custom hook to handle everything else
  1079. $pic_info = apply_filters('autonav_select', array(), $attr);
  1080. }
  1081. $pic_info = apply_filters('autonav_post_select', $pic_info, $attr);
  1082. $html = create_output($attr, $pic_info);
  1083. $html = apply_filters('autonav_html', $html, $attr); // permit custom hook post HTML creation
  1084. return $html;
  1085. }
  1086. add_shortcode('autonav','autonav_wl_shortcode');
  1087. /* ****
  1088. Plugin Options handling
  1089. **** */
  1090. // White-list plugin our option page
  1091. function autonav_wloptions_init(){
  1092. register_setting( 'autonav_wloptions_options', 'autonav_wl', 'autonav_wloptions_validate' );
  1093. }
  1094. add_action('admin_init', 'autonav_wloptions_init' );
  1095. function autonav_wl_options() {
  1096. if (is_admin())
  1097. include 'autonav-wl-options.php';
  1098. }
  1099. function autonav_wl_activate_admin_options() {
  1100. $my_info = pathinfo(__FILE__);
  1101. $my_name = basename(__FILE__,'.'.$my_info['extension']);
  1102. add_submenu_page('options-general.php','AutoNav Options','AutoNav','manage_options',
  1103. $my_name, 'autonav_wl_options');
  1104. }
  1105. add_action('admin_menu', 'autonav_wl_activate_admin_options');
  1106. // Run at plugin activation time: Force update of preferences.
  1107. function autonav_wlactivate ($input) {
  1108. // Retrieve current options (if any), call our validate function, and store.
  1109. $options = get_option('autonav_wl');
  1110. $options = autonav_wloptions_validate($options);
  1111. update_option('autonav_wl', $options);
  1112. }
  1113. register_activation_hook( __FILE__, 'autonav_wlactivate' );
  1114. /* ********************** */
  1115. /*
  1116. Options validation. In this file because our *-options.php not loaded
  1117. during post-input validation phase. Returns a sanitized array.
  1118. */
  1119. function autonav_wloptions_validate($input) {
  1120. $plain_defaults = array('order' => 'ASC', 'orderby' => 'menu_order',
  1121. 'background' => '#000000', 'class' => 'subpages',
  1122. 'size_small' => '120x90', 'size_med' => '160x120',
  1123. 'size_large' => '240x180', 'display' => 'attached',
  1124. 'combine' => 'all', 'size' => 'auto', 'exclude' => '',
  1125. 'paged' => 0, 'sharp' => 0, 'target' => '');
  1126. foreach ($plain_defaults as $name => $default) {
  1127. $input[$name] = wp_filter_nohtml_kses($input[$name]);
  1128. if ($input[$name] == '') $input[$name]=$default;
  1129. }
  1130. $int_options = array('titles' => 1, 'pics_only' => 1, 'crop' => 3, 'columns' => 63);
  1131. foreach ($int_options as $name => $bitfield) {
  1132. $input[$name] = intval($input[$name]) & $bitfield;
  1133. }
  1134. if ($input['columns'] == 0) { $input['columns'] = 3; }
  1135. $input['caption'] = '';
  1136. $input['postid'] = '';
  1137. $input['ids'] = '';
  1138. $input['start'] = 0;
  1139. $input['count'] = 0;
  1140. return $input;
  1141. }
  1142. function autonav_add_settings_link($links, $file) {
  1143. static $this_plugin;
  1144. if (!$this_plugin) $this_plugin = plugin_basename(__FILE__);
  1145. if ($file == $this_plugin){
  1146. $settings_link = '<a href="admin.php?page=autonav-wl">'.__("Settings", "autonav").'</a>';
  1147. array_unshift($links, $settings_link);
  1148. }
  1149. return $links;
  1150. }
  1151. add_filter('plugin_action_links', 'autonav_add_settings_link', 10, 2 );