Acțiunea add_action pentru articole complet noi în WordPress
publish_post rulează când un articol este publicat sau când este editat și statusul său este "published". Argumentele funcției de acțiune: ID-ul articolului.
-Documentația API-ului pentru Plugin-uri
Am adăugat hook-ul publish_post într-un plugin WordPress pe care îl dezvolt. Funcția apelată de hook este menită să modifice categoriile mai multor articole folosind funcția wp_update_post.
Totuși, acest hook nu funcționează deoarece rezultatul returnat de wp_update_post este întotdeauna 0. Cea mai bună presupunere a mea este că rularea wp_update_post cauzează o altă instanță a hook-ului meu să ruleze pentru că republicată articolul... ceea ce cred că aduce în discuție partea "...sau dacă este editat și statusul său este "published"" din afirmația de mai sus.
Există vreun alt action-hook pe care îl pot folosi care va fi apelat doar când articolul adăugat este complet nou și nu editat?
<?php
/*
Plugin Name: Plugin pentru Schimbarea Categoriilor
Plugin URI: http://www.example.com
Description: Când este creat un articol nou, acest plugin va cauza
Version: 0.1
Author: Eu
License: GPL2
?>
<?php
class categoryShifter {
function shiftCategories($post_ID) {
$maxNumPostsFirstTeir = 4;
$first_teir_cat = "Știri Proaspete 1";
$second_teir_cat = "Știri Ușor Depășite 2";
$firephp = FirePHP::getInstance(true);
$firephp->info('ÎNCEPUT: categoryShifter.shiftCategories()');
$firephp->log($post_ID, 'post_ID: ');
$firephp->trace('urmărire până aici');
$first_teir_id = categoryShifter::getIDForCategory($first_teir_cat, $firephp);
$second_teir_id = categoryShifter::getIDForCategory($second_teir_cat, $firephp);
$firephp->log($first_teir_id, '$first_teir_id');
$firephp->log($second_teir_id, '$second_teir_id');
$qPostArgs = array(
'numberposts' => 100,
'order' => 'DESC',
'orderby' => 'post_date',
'post_type' => 'post',
'post_status' => 'published',
'category_name' => $first_teir_cat
);
$firstTeirPosts = get_posts($qPostArgs);
$firephp->log($firstTeirPosts, 'articole obținute:');
$firephp->log(sizeof($firstTeirPosts), 'dimensiune');
// NOTĂ: Pare să funcționeze.
for($i = sizeof($firstTeirPosts)-1; $i > $maxNumPostsFirstTeir-4; $i--)
{
$newCats = array($second_teir_id);
$editingId = $firstTeirPosts->ID;
$result = wp_set_post_categories($editingId, $newCats); /* NOTĂ: Nu funcționează momentan... returnează un array cu $second_teir_id în el. */
$firephp->log($result, 'Rezultat');
}
/*
$my_post = array();
$my_post['ID'] = 132;
$my_post['post_category'] = array($second_teir_id);
$firephp->log('Înainte', 'Înainte');
if(wp_update_post( $my_post ) == 0) {
$firephp->Error('Eroare Fatală, Articolul nu a fost actualizat', 'eroare');
}
$firephp->log('După', 'După');
*/
return $post_ID;
}
function getIDForCategory($cat_name, $logger) {
$logger->Info("Început: getIDForCategory()");
$cats = get_categories();
$whichCatId = "";
foreach($cats as $single_cat) {
if($single_cat->name == $cat_name) {
$whichCatId = $single_cat->term_id;
break;
}
}
$logger->Info("Sfârșit: getIDForCategory()");
return (int)$whichCatId;
}
}
/* Hook pentru Crearea Articolului */
/* add_action('publish_post', array('categoryShifter','shiftCategories')); */
add_action('wp_insert_post', array('categoryShifter', 'shiftCategories'));
?>
Am trecut la folosirea hook-ului wp_insert_post pentru moment... dar tot nu pot face funcția wp_set_post_categories să modifice categoriile articolelor.
Înțeleg că probabil va trebui să actualizez acest cod astfel încât să țină cont de categoriile existente ale articolului și să modifice doar cele specificate de plugin, dar pentru moment este doar o versiune alfa.

Cum rămâne cu acțiunea wp_insert_post
? http://core.trac.wordpress.org/browser/tags/3.3.1/wp-includes/post.php#L2656

Dar acestea se vor executa din nou dacă, de exemplu, statusul este schimbat din publicat înapoi la draft și apoi din nou la publicat?

@soulseekah Hook-ul wp_insert_post
va fi apelat din nou la editarea și salvarea unui articol existent. Testat pe WordPress 5.9. Știu că comentariul tău este din 2012, dar în caz că cineva este curios despre asta.

Am citit în detaliu nucleul WordPress și am încercat tot. wp_transition_post_status()
, new_to_publish()
, new_{post_type}()
, wp_insert_post()
.
Toate acestea sunt, în final, nesigure.
wp_transition_post_status()
nu este sigură deoarece noul status "publish" este statusul implicit atât pentru crearea de postări noi, cât și pentru actualizarea celor existente. Statusul vechi nu este sigur pentru a defini ce este o postare nouă și ce nu, deoarece poate fi draft, auto-draft, publish, etc.
new_to_publish()
nu funcționează pentru tipuri de postări personalizate.
new_{post_type}
trece doar $post ca parametru și nu poți ști dacă este nou sau actualizează unul existent
wp_insert_post()
are un parametru $update care ar trebui să fie TRUE dacă actualizează postări existente și FALSE dacă creează postări noi, dar este nesigur deoarece returnează TRUE pentru postări noi din cauza auto-draft.
Soluție: Utilizarea unei meta pentru postări
Am ajuns să folosesc o meta personalizată pentru postări pe care am numit-o check_if_run_once
care va executa o anumită logică doar o singură dată:
/**
* Faceți ceva când este creată o nouă carte
*/
function new_book($post_id, $post, $update) {
if ( $post->post_type == 'book' && $post->post_status == 'publish' && empty(get_post_meta($post_id, 'check_if_run_once')) ) {
# Postare nouă
# Faceți ceva aici...
# Și actualizați meta astfel încât să nu mai ruleze din nou
update_post_meta( $post_id, 'check_if_run_once', true );
}
}
add_action( 'wp_insert_post', 'new_book', 10, 3 );
Opțional, dacă trebuie să vă actualizați postările existente cu meta-ul "check_if_run_once", astfel încât să nu ruleze codul de mai sus pentru postările existente create înainte de a adăuga acea funcție, puteți face:
/**
* Aceasta este o funcție temporară pentru actualizarea postărilor existente cu meta-ul "check_if_run_once"
* Accesați site-ul dvs. conectat ca administrator și adăugați ?debug la URL.
*/
function temporary_function() {
if (current_user_can('manage_options')) {
$posts = get_posts(array(
'post_type' => 'book',
'posts_per_page' => -1, // S-ar putea să fie nevoie să paginați acest lucru în funcție de câte postări aveți
'fields' => 'ids'
));
foreach($posts as $post_id) {
update_post_meta($post_id, 'check_if_run_once', true);
}
}
}
if (isset($_GET['debug'])) {
add_action('init', 'temporary_function');
}

De ce nu are mai multe voturi pozitive și de ce nu este răspunsul acceptat. Răspunsul acceptat nu explică lucrurile și nu ține cont de faptul că oamenii tind să folosească asta pentru CPT etc..

Direcționarea precisă a creării unui articol nou este de fapt mai complicată decât pare. Din punct de vedere tehnic, există multiple modalități prin care un articol poate fi creat sau actualizat și există multe aspecte care nu sunt atât de evidente, dar care sunt din punct de vedere tehnic tot articole (de exemplu, reviziile).
WordPress oferă cârlige dinamice care urmăresc nu doar crearea articolului, ci și ce a fost și ce a devenit. Consultă Tranzițiile stării articolului în Codex.

Mai mult prin experimentare decât urmărind documentația, această soluție funcționează pentru mine (WP 3.3). Primesc un apel al hook-ului transition_post_status cu $new_status setat la "auto-draft" când creezi un articol nou.
function my_post_new($new_status, $old_status=null, $post=null){
if ($new_status == "auto-draft"){
// faci operațiuni aici
}
}
add_action('transition_post_status', 'my_post_new');

Acest lucru se va declanșa de fiecare dată când un draft automat este salvat, adică cam la fiecare minut în timpul editării.

Bun punct. În cazul meu aceasta nu este o problemă, dar ar putea fi pentru alții, în funcție de ceea ce faci.

am vrut să votez pozitiv, dar încă nu pot. așa că felicitările merg aici, @PapaFreud. apropo, acum acest lucru este documentat la http://codex.wordpress.org/Post_Status_Transitions. din nou, mulțumesc omule

@soulseekah Punct interesant pe care l-ai ridicat, am testat acest lucru și auto-draft
este atribuit ca $new_status
al unui articol la crearea sa (adică Adăugare Nouă), o singură dată. De îndată ce primul procedeu AUTOSAVE
se declanșează după 1 minut, valoarea $new_status
este actualizată la draft
. $old_status
rămâne NULL
până când articolul este salvat manual sau publicat. Deci, tehnic, acest lucru ar funcționa și nu s-ar declanșa de fiecare dată când editorul salvează automat munca ta. Ca măsură suplimentară, poți verifica dacă $old_status
este NULL
pentru a confirma -> if ($new_status == "auto-draft" && $old_status === NULL)

Am descoperit că cea mai bună opțiune este să verific starea postului atunci când este apelat wp_insert_post
.
Când un post nou este creat, starea inițială este auto-draft
.
if (!function_exists('benyonsFunction')) {
function benyonsFunction($postId, $post) {
if ($post->post_status == "auto-draft") {
error_log('POST NOU!!!');
}
}
}
add_action('wp_insert_post', 'benyonsFunction', 10, 2);
Acest error_log
se va executa doar o singură dată.

Cea mai curată și sigură metodă de a gestiona acest lucru pentru un tip de postare cunoscut este să folosești hook-ul {$new_status}_{$post->post_type}
care oferă vechiul status și îl compară cu "publish".
De exemplu, dacă dorești să declanșezi o acțiune atunci când o nouă "pagină" este creată, ai folosi:
add_action( 'publish_page', function( int $post_id, \WP_Post $post, string $old_status ) {
if ( 'publish' === $old_status ) {
// Nimic de văzut aici.
return;
}
// Logica de afaceri se pune aici.
}, 10, 3 );

Nu, acest lucru se va declanșa de fiecare dată când o pagină trece de la orice stare la 'publicată', deci se va declanșa de mult mai multe ori decât doar la prima creare.
