Belarusian (беларуская мова) translation by Katharina Grigorovich-Nevolina (you can also view the original English article)
У гэтым уроку вы даведаецеся, як стварыць плагін, які дазваляе карыстальнікам адпраўляць малюнкі і загружаць іх у медыя-бібліятэку WordPress. Вы таксама даведаецеся, як правільна выдаляць выявы з медыя-бібліятэкі WordPress, а таксама выконваць базавую праверку загружаных малюнкаў.
Папярэдне ...
Гэты ўрок створаны па просьбе некаторых карыстальнікаў, якія знайшлі цікавым урок па плагінам quotes, але былі асабліва зацікаўлены ў тым, як выкарыстоўваць той жа метад для загрузкі малюнкаў з інтэрфейсу. Такім чынам, вось паўтор гэтага ўроку, які робіць менавіта гэта. Падрабязную інфармацыю пра наладу плагінаў, кароткіх кодаў і nonces см. у папярэднім уроке.
Плагін будзе:
- адлюстроўваць форму загрузкі малюнка з выкарыстаннем кароткага кода
- прымаць толькі малюнкі пэўнага тыпу і максімальнага памеру
- дадаваць карыстацкі тып паведамлення для карыстацкіх малюнкаў
- дадаваць малюнкі ў медыятэку WordPress з адпаведным прымацаваным надпісам
- адлюстроўваць неапублікаваныя малюнкі
- дазволіць карыстальнікам выдаляць свае неапублікаваныя малюнкі
Мы будзем выкарыстоўваць убудаванае тэкставае поле для малюнкаў у WordPress (aka Рэкамендуемый малюнак), каб утрымаць малюнак для кожнага паведамлення. Гэта таксама палягчае адлюстраванне і працу з нашым малюнкам, так як мы можам выкарыстоўваць функцыі post_thumbnail.
Вось да чаго мы імкнемся:



Увесь код даступны ў крыніцы плагіна ў пачатку гэтага кіраўніцтва.
Крок 1 Налада плагіна
Стварыце файл плагіна з імем submit_user_images.php
ў каталогу wp-content / plugins / submit-user-images
.
Звярніцеся да крыніцы плагіна для інфармацыі загалоўка плагіна.
Крок 2 Функцыя ініцыялізацыі плагіна
Мы збіраемся стварыць персаналізаваны тып паведамлення з імем user_images для захоўвання нашых малюнкаў карыстальнікаў і карыстацкай таксанаміі з імем user_image_category. Гэта ўключыць больш чыстае адміністраванне малюнкаў, чым проста прыпісваць іх звычайным паведамленням і катэгорыям.
Ініцыятыўная пастка і функцыя
Мы будзем выкарыстоўваць наступны код ініцыялізацыі для стварэння нашага наладжвальнага тыпу паведамленняў і карыстацкай таксанаміі:
add_action('init', 'sui_plugin_init'); function sui_plugin_init(){ $image_type_labels = array( 'name' => _x('User images', 'post type general name'), 'singular_name' => _x('User Image', 'post type singular name'), 'add_new' => _x('Add New User Image', 'image'), 'add_new_item' => __('Add New User Image'), 'edit_item' => __('Edit User Image'), 'new_item' => __('Add New User Image'), 'all_items' => __('View User Images'), 'view_item' => __('View User Image'), 'search_items' => __('Search User Images'), 'not_found' => __('No User Images found'), 'not_found_in_trash' => __('No User Images found in Trash'), 'parent_item_colon' => '', 'menu_name' => 'User Images' ); $image_type_args = array( 'labels' => $image_type_labels, 'public' => true, 'query_var' => true, 'rewrite' => true, 'capability_type' => 'post', 'has_archive' => true, 'hierarchical' => false, 'map_meta_cap' => true, 'menu_position' => null, 'supports' => array('title', 'editor', 'author', 'thumbnail') ); register_post_type('user_images', $image_type_args); $image_category_labels = array( 'name' => _x( 'User Image Categories', 'taxonomy general name' ), 'singular_name' => _x( 'User Image', 'taxonomy singular name' ), 'search_items' => __( 'Search User Image Categories' ), 'all_items' => __( 'All User Image Categories' ), 'parent_item' => __( 'Parent User Image Category' ), 'parent_item_colon' => __( 'Parent User Image Category:' ), 'edit_item' => __( 'Edit User Image Category' ), 'update_item' => __( 'Update User Image Category' ), 'add_new_item' => __( 'Add New User Image Category' ), 'new_item_name' => __( 'New User Image Name' ), 'menu_name' => __( 'User Image Categories' ), ); $image_category_args = array( 'hierarchical' => true, 'labels' => $image_category_labels, 'show_ui' => true, 'query_var' => true, 'rewrite' => array( 'slug' => 'user_image_category' ), ); register_taxonomy('sui_image_category', array('user_images'), $image_category_args); $default_image_cats = array('humor', 'landscapes', 'sport', 'people'); foreach($default_image_cats as $cat){ if(!term_exists($cat, 'sui_image_category')) wp_insert_term($cat, 'sui_image_category'); } }
Што робіць гэты код:
- выкарыстоўвае зачэпку ініцыяцыі WordPress для выкліку функцыі ініцыялізацыі плагіна
- рэгіструе карыстацкі тып паведамлення з імем user_images
- рэгіструе карыстацкую таксанамію з імем user_image_category і прысвойвае яе тыпу паведамлення user_images
- дадае некаторыя катэгорыі па змаўчанні ў таксанаміі user_image_category, калі яны яшчэ не існуюць
Зараз у нас з'явіцца меню User Images ў нашай панэлі кіравання адміністратара і спосаб адміністравання малюнкаў карыстальнікаў і іх катэгорый.
Крок 3 Налада некаторых значэнняў па змаўчанні
Нам трэба зрабіць некаторую базавую праверку, таму давайце вызначым дзве канстанты для далейшага выкарыстання:
define('MAX_UPLOAD_SIZE', 200000); define('TYPE_WHITELIST', serialize(array( 'image/jpeg', 'image/png', 'image/gif' )));
Крок 4 Вызначце кароткі код
Мы вызначым кароткі код, які дазволіць нам адлюстроўваць (і апрацоўваць) форму адпраўкі малюнкаў карыстальніка ў паведамленні або на старонцы:
add_shortcode('sui_form', 'sui_form_shortcode');
Бяспека
Паколькі наш плагін прымае дадзеныя ад карыстальніка, мы рэалізуем наступныя механізмы бяспекі:
- толькі зарэгістраваныя карыстальнікі маюць доступ да формы адпраўкі малюнка
- мы выкарыстоўваем nonces для праверкі таго, што формы былі згенераваны нашым плагінам
- малюнкі перадаюцца з выкарыстаннем wp_insert_post, які дэзактывіруе дадзеныя перад захаваннем іх у базе дадзеных
- карыстальнікі могуць праглядаць толькі свае ўласныя малюнкі, а nonces не дазваляе ім выдаляць паведамленні іншых карыстальнікаў
Крок 5 Асноўная функцыя
Гэта функцыя, выкліканая нашым кароткім кодам. Ён адлюстроўвае і апрацоўвае форму адпраўкі малюнка і форму для раздрукоўкі / выдалення малюнка. Мы будзем браць яго маленькімі кавалачкамі, і на кроку 6 мы разгледзім дапаможныя функцыі.
function sui_form_shortcode(){ if(!is_user_logged_in()){ return '<p>You need to be logged in to submit an image.</p>'; } global $current_user;
- праверце, ці ўвайшоў карыстач у сістэму
- захапіце зменную WordPress $ current_user, якую нам трэба атрымаць для ID нашага карыстальніка
if(isset( $_POST['sui_upload_image_form_submitted'] ) && wp_verify_nonce($_POST['sui_upload_image_form_submitted'], 'sui_upload_image_form') ){ $result = sui_parse_file_errors($_FILES['sui_image_file'], $_POST['sui_image_caption']); if($result['error']){ echo '<p>ERROR: ' . $result['error'] . '</p>'; }else{ $user_image_data = array( 'post_title' => $result['caption'], 'post_status' => 'pending', 'post_author' => $current_user->ID, 'post_type' => 'user_images' ); if($post_id = wp_insert_post($user_image_data)){ sui_process_image('sui_image_file', $post_id, $result['caption']); wp_set_object_terms($post_id, (int)$_POST['sui_image_category'], 'sui_image_category'); } } }
- калі форма выявы была адпраўлена, будзе поле sui_upload_image_form_submitted, якое было створана нашай функцыяй wp_nonce_field. Затым мы можам праверыць nonce і прыступіць да апрацоўкі прадстаўленага малюнка
- выканайце праверку шляхам перадачы ўваходнага файла (дзе захоўваюцца дадзеныя загружанага малюнка) і ўваходных дадзеных загалоўка ў функцыю праверкі, sui_parse_file_errors і адлюстравання любых вернутых памылак
- пабудуйце масіў, у якім стан паведамлення трэба адкласці (адміністратару зараз трэба будзе зацвердзіць яго для публікацыі), усталюйце тып паведамлення user_images (наш карыстацкі тып паведамлення) і ўсталюйце аўтара паведамлення з выявай ў бягучы ўваход у сістэму карыстальніка
- калі паведамленне аб малюнку было паспяхова ўстаўлена, захавайце малюнак у медыятэцы WordPress (sui_process_image) і, нарэшце, усталюйце катэгорыю для паведамлення малюнка і адлюструйце паведамленне аб паспяховым завяршэнні
if (isset( $_POST['sui_form_delete_submitted'] ) && wp_verify_nonce($_POST['sui_form_delete_submitted'], 'sui_form_delete')){ if(isset($_POST['sui_image_delete_id'])){ if($user_images_deleted = sui_delete_user_images($_POST['sui_image_delete_id'])){ echo '<p>' . $user_images_deleted . ' images(s) deleted!</p>'; } } }
- калі была адпраўлена форма выдалення малюнка, будзе поле sui_form_delete_submitted, якое было створана нашай функцыяй wp_nonce_field. Затым мы можам праверыць nonce і перайсці да апрацоўкі масіва малюнкаў, правераных для выдалення
- мы правяраем, што на самой справе ў нас ёсць некаторыя малюнкі, правераныя для выдалення, шляхам тэставання $ _POST ['sui_image_delete_id']. Калі гэта так, мы перадаем іх функцыі sui_delete_user_images (гл. Крок 6)
- калі выявы былі выдалены, адлюстроўваецца паведамленне аб паспяховым завяршэнні
echo sui_get_upload_image_form($sui_image_caption = $_POST['sui_image_caption'], $sui_image_category = $_POST['sui_image_category']); if($user_images_table = sui_get_user_images_table($current_user->ID)){ echo $user_images_table; }
- мы выводзім форму загрузкі малюнка
- нарэшце, мы выводзім форму спісу / выдалення малюнкаў, перадаючы ідэнтыфікатар карыстальніка функцыі sui_get_user_images_table (гл . Крок 6)
Крок 6 Дапаможныя функции
Тут мы разгледзім функцыі, якія генеруюць формы, дадаюць выявы ў медыя-бібліятэку і функцыю, якая выдаляе выбраныя малюнкі.
function sui_get_upload_image_form($sui_image_caption = '', $sui_image_category = 0){ $out = ''; $out .= '<form id="sui_upload_image_form" method="post" action="" enctype="multipart/form-data">'; $out .= wp_nonce_field('sui_upload_image_form', 'sui_upload_image_form_submitted'); $out .= '<label for="sui_image_caption">Image Caption - Letters, Numbers and Spaces</label><br/>'; $out .= '<input type="text" id="sui_image_caption" name="sui_image_caption" value="' . $sui_image_caption . '"/><br/>'; $out .= '<label for="sui_image_category">Image Category</label><br/>'; $out .= sui_get_image_categories_dropdown('sui_image_category', $sui_image_category) . '<br/>'; $out .= '<label for="sui_image_file">Select Your Image - ' . MAX_UPLOAD_SIZE . ' bytes maximum</label><br/>'; $out .= '<input type="file" size="60" name="sui_image_file" id="sui_image_file"><br/>'; $out .= '<input type="submit" id="sui_submit" name="sui_submit" value="Upload Image">'; $out .= '</form>'; return $out; }
- функцыя прымае 2 апцыянальных аргумента для паўторнага запаўнення палёў формы. Гэта зручна для карыстальніка. Гэта зручна для карыстальніка.
- выводзіцца поле nonce, якое мы правяраем пры адпраўке формы;
- выводзім выпадальнае меню для катэгорый малюнкаў, выклікаючы sui_get_image_categories_dropdown (гл. Наступную функцыю);
function sui_get_image_categories_dropdown($taxonomy, $selected){ return wp_dropdown_categories(array('taxonomy' => $taxonomy, 'name' => 'sui_image_category', 'selected' => $selected, 'hide_empty' => 0, 'echo' => 0)); }
- функцыя прымае 2 аргумента, уключая элемент ID, абранай ў дадзены момант катэгорыі
- мы выкарыстоўваем функцыю WordPress wp_dropdown_categories для стварэння расчыняючага спісу, у якім пералічаны катэгорыі карыстацкіх малюнкаў з таксанаміі user_image_category (наша карыстацкая таксанамія).
function sui_get_user_images_table($user_id){ $args = array( 'author' => $user_id, 'post_type' => 'user_images', 'post_status' => 'pending' ); $user_images = new WP_Query($args); if(!$user_images->post_count) return 0; $out = ''; $out .= '<p>Your unpublished images - Click to see full size</p>'; $out .= '<form method="post" action="">'; $out .= wp_nonce_field('sui_form_delete', 'sui_form_delete_submitted'); $out .= '<table id="user_images">'; $out .= '<thead><th>Image</th><th>Caption</th><th>Category</th><th>Delete</th></thead>'; foreach($user_images->posts as $user_image){ $user_image_cats = get_the_terms($user_image->ID, 'sui_image_category'); foreach($user_image_cats as $cat){ $user_image_cat = $cat->name; } $post_thumbnail_id = get_post_thumbnail_id($user_image->ID); $out .= wp_nonce_field('sui_image_delete_' . $user_image->ID, 'sui_image_delete_id_' . $user_image->ID, false); $out .= '<tr>'; $out .= '<td>' . wp_get_attachment_link($post_thumbnail_id, 'thumbnail') . '</td>'; $out .= '<td>' . $user_image->post_title . '</td>'; $out .= '<td>' . $user_image_cat . '</td>'; $out .= '<td><input type="checkbox" name="sui_image_delete_id[]" value="' . $user_image->ID . '" /></td>'; $out .= '</tr>'; } $out .= '</table>'; $out .= '<input type="submit" name="sui_delete" value="Delete Selected Images" />'; $out .= '</form>'; return $out; }
- прымае ID карыстальніка, таму што нам трэба атрымаць спіс карыстацкіх малюнкаў толькі для бягучага карыстальніка
- стварае $ args, каб паказаць нашага карыстальніка, тып паведамлення user_images і прыстасаваныя малюнкі, якія знаходзяцца на разглядзе (яшчэ не апублікаваныя адміністратарам);
- выконвае карыстацкі запыт з выкарыстаннем WP_Query
- вярнуць false, калі наш запыт не вяртае ніякія малюнкі карыстальніка
- запусціць форму і згенераваць nonce для формы
- пракруціць запісы малюнкаў, каб пераканацца, што мы таксама захопім катэгорыю паведамлення аб малюнку
- стварыце сцяжок nonce для выдалення малюнка, прысвойце унікальнае імя для nonce, аб'яднаўшы ID паведамлення малюнка карыстальніка
- выснову радка табліцы, якая змяшчае інфармацыю аб паведамленні малюнка, а таксама флажок выдалення.
Навошта дадаваць nonce для кожнага малюнка?
Формамі можна маніпуляваць у браўзэры для адпраўкі нечаканых дадзеных. У нашым выпадку кожнаму флажку delete прысвойваецца значэнне паведамлення. Але што, калі зламысны карыстальнік змяніў гэта значэнне і прымусіў нашу функцыю выдалення адмяніць паведамленне, якое на самай справе не пазначана?
Адзін са спосабаў пазбегнуць гэтага - выкарыстоўваць nonces для кожнага радка паштовых дадзеных, забяспечваючы унікальнасць імя nonce, пры гэтым значэнне слупка павінна быць выдалена. Затым мы правяраем паведамленне nonce пры адпраўцы формы, каб пераканацца, што гэта сапраўднае вяртальнае значэнне.
function sui_delete_user_images($images_to_delete){ $images_deleted = 0; foreach($images_to_delete as $user_image){ if (isset($_POST['sui_image_delete_id_' . $user_image]) && wp_verify_nonce($_POST['sui_image_delete_id_' . $user_image], 'sui_image_delete_' . $user_image)){ if($post_thumbnail_id = get_post_thumbnail_id($user_image)){ wp_delete_attachment($post_thumbnail_id); } wp_trash_post($user_image); $images_deleted ++; } } return $images_deleted; }
- функцыя прымае масіў ID паведамленняў малюнка для выдалення
- кожны ID паведамлення малюнка правяраецца, каб даведацца, ці было для яго згенеравана nonce
- калі nonce правяраецца, мы выдаляем ўкладанне малюнка, якое існуе ў медыя-бібліятэцы, перадаючы ID малюнка паведамлення ў функцыю WordPress wp_delete_attachment.
- мы таксама выдаляем паведамленне малюнка з дапамогай функцыі WordPress wp_trash_post
Але не выдаляецца ці ўкладанне эскізаў, калі паведамленне абарвана?
Не, і гэта таму, што WordPress захоўвае ўкладання як звычайныя запісы ў табліцы базы дадзеных паведамленняў. Паглядзіце самі: усе ўкладанні захоўваюцца ў табліцы паведамленняў з post_type attachment. Простае выдаленне тыпу карыстальніка user_images не выдаляе яго ўкладанне ў мініяцюру. Ён застаецца ў медыя-бібліятэцы для будучага выкарыстання, калі мы спецыяльна не выдалім яго з дапамогай wp_delete_attachment. Для нашых мэтаў я падумаў, што лепш выдаляць ўкладанне, калі паведамленне карыстальніка было выдаленае.
Крок 7 Функцыі апрацоўкі малюнкаў
Нагадаем, як выглядае выснова ўводу файла html, калі ён змяшчае малюнак у ваш скрыпт:
Array ( [name] => ref_blind.jpg [type] => image/jpeg [tmp_name] => /tmp/php79xI4e [error] => 0 [size] => 106290 )
Мы перадаем гэты масіў да функцыі sui_process_image разам з ідэнтыфікатарам захаванага запісу выявы карыстальніка і загалоўкам падчышчанага малюнка.
function sui_process_image($file, $post_id, $caption){ require_once(ABSPATH . "wp-admin" . '/includes/image.php'); require_once(ABSPATH . "wp-admin" . '/includes/file.php'); require_once(ABSPATH . "wp-admin" . '/includes/media.php'); $attachment_id = media_handle_upload($file, $post_id); update_post_meta($post_id, '_thumbnail_id', $attachment_id); $attachment_data = array( 'ID' => $attachment_id, 'post_excerpt' => $caption ); wp_update_post($attachment_data); return $attachment_id; }
- нам трэба ўключыць сцэнарыі адміністратара WordPress, якія апрацоўваюць загрузку малюнкаў за кадрам
- мы выклікаем функцыю media_handle_upload (якая з'яўляецца часткай мэдыяфайла .php), перадаючы яму загружаны масіў файлаў і ідэнтыфікатар паведамлення.
- зараз у нас ёсць ідэнтыфікатар ўкладання, які мы можам выкарыстоўваць з дапамогай update_post_meta, каб прызначыць укладанне для паведамлення ў выглядзе мініяцюры. Заўвага: "_thumbnail_id" спасылаецца на мета-поле ўнутранай мініяцюры (апрацаваны малюнак). Ўнутраныя паля Wordpress пачынаюцца з падкрэслення.
- затым мы выкарыстоўваем ідэнтыфікатар ўкладання, каб абнавіць загаловак ўкладання, выкарыстоўваючы функцыю wp_update_post.
Паколькі ўкладанні - эт проста рэгулярныя паведамленні, калі мы абнаўляем поле post_excerpt для ўкладання, мы фактычна абнаўляем поле загалоўка ўкладання, як паказана на экране рэдагавання медыя-библиотеки.
Функция праверкі.
Мы таксама правяраем масіў файлаў і карыстацкі подпіс выявы з дапамогай функцыі sui_parse_file_errors.
function sui_parse_file_errors($file = '', $image_caption){ $result = array(); $result['error'] = 0; if($file['error']){ $result['error'] = "No file uploaded or there was an upload error!"; return $result; } $image_caption = trim(preg_replace('/[^a-zA-Z0-9\s]+/', ' ', $image_caption)); if($image_caption == ''){ $result['error'] = "Your caption may only contain letters, numbers and spaces!"; return $result; } $result['caption'] = $image_caption; $image_data = getimagesize($file['tmp_name']); if(!in_array($image_data['mime'], unserialize(TYPE_WHITELIST))){ $result['error'] = 'Your image must be a jpeg, png or gif!'; }elseif(($file['size'] > MAX_UPLOAD_SIZE)){ $result['error'] = 'Your image was ' . $file['size'] . ' bytes! It must not exceed ' . MAX_UPLOAD_SIZE . ' bytes.'; } return $result; }
- праверыць элемент памылкі масіва файлаў для памылкі загрузкі html, калі ён знойдзены, вяртае масіў вынікаў з памылкай
- запусціце некаторы рэгулярны выраз у загалоўку выявы, каб выдаліць усё, акрамя літарна-лічбавых дадзеных і прабелаў, замяняючы прабелы для зручнасці чытання
- калі ў нас заканчваецца пустой загаловак пасля яго ачысткі, мы вяртаем памылку
- праверце ўнутраны тып малюнка (не давярайце пашырэнню файла) з дапамогай функцыі PHP getimagesize з пастаяннай TYPE_WHITELIST
- праверце памер малюнка насуперак канстанце MA X_UPLOAD_SIZE
Крок 8 Некаторыя стылі.
Проста адкіньце гэтую інфармацыю пра стыль у файл style.css ў папке тэмы:
#sui_upload_image_form #sui_image_caption{ width:500px; } #user_images{ font-size:12px; } #user_images th{ text-align:left; } #user_images td{ vertical-align:middle; } #user_images td input{ margin:0px; }
Крок 9 Паспрабуйце
Актывуйце плагін, увядзіце кароткі код на старонцы, зайдзіце на свой сайт і праверце яго. Калі вы загрузіце малюнак, вы ўбачыце новае паведамленне ў меню Карыстацкія малюнкі. Ён будзе апублікаваны. Вы таксама ўбачыце новы малюнак, уключанае ў вашу медыя-бібліятэку, прымацаванае да вашага новага паведамлення, з загалоўкам, як прадугледжана.
Полная крыніца кода плагіна і спасылка на дэма-сайт пазначаны ў верхняй частцы гэтага ўрока.
Зыходная папка таксама змяшчае шаблон старонкі Wordpress з наладжвальным цыклам, які адлюстроўвае апублікаваныя малюнкі для ўсіх карыстальнікаў.
Апошнія думкі
Магчыма, вы захочаце ўсталяваць больш строгую праверку на загрузку малюнкаў. Памятайце, што вы прымаеце дадзеныя ад карыстальнікаў, якія могуць выпадкова ці зламысна загружаць непрымальныя файлы. Праверка тыпу і памеру файла з'яўляецца добрым пачаткам.
Таксама мы стварылі загаловак прыкладання, абнавілі поле ўкладання post_excerpt. Вы таксама можаце ўсталяваць апісанне ўкладання, выкарыстоўваючы поле ўкладання post_content.