Skip to content

Commit

Permalink
refactor save_post logic to translate before other actions
Browse files Browse the repository at this point in the history
  • Loading branch information
andrefelipe committed Oct 1, 2020
1 parent 6823b64 commit bda83a3
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 237 deletions.
34 changes: 24 additions & 10 deletions src/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -377,18 +377,25 @@ public function savePostHook($post_id, $post = null)

// in case it's attachment, it misses the post object
if (!$post) {
$post = Cast::post($post_id);
$post = Cast::wpPost($post_id);
}

// clear cache
Cache::forget($post->post_type);
Cache::forget('bond/posts');
Cache::forget('global');

// do action
$post = Cast::post($post);
\do_action('Bond/save_post', $post);
\do_action('Bond/save_post/' . $post->post_type, $post);

// Translate before
\do_action('Bond/translate_post', $post_id);

// Now emit actions
if (\has_action('Bond/save_post')) {
\do_action('Bond/save_post', Cast::post($post));
}
if (\has_action('Bond/save_post/' . $post->post_type)) {
\do_action('Bond/save_post/' . $post->post_type, Cast::post($post));
}

// TODO maybe consider the delete_post hook
// OR a more specific usage Bond/post_publish Bond/post_draft ?
Expand Down Expand Up @@ -432,9 +439,12 @@ public function saveTermHook($term_id, $tt_id, $taxonomy)
Cache::forget('global');

// do action
$term = Cast::term($term_id);
\do_action('Bond/save_term', $term);
\do_action('Bond/save_term/' . $taxonomy, $term);
if (\has_action('Bond/save_term')) {
\do_action('Bond/save_term', Cast::term($term_id));
}
if (\has_action('Bond/save_term/' . $taxonomy)) {
\do_action('Bond/save_term/' . $taxonomy, Cast::term($term_id));
}

// TODO save_term doesn't get the delete right?
Expand Down Expand Up @@ -476,9 +486,13 @@ public function saveUserHook($user_id)
Cache::forget('global');

// do action
if (\has_action('Bond/save_user')) {
\do_action('Bond/save_user', Cast::user($user_id));
}
$user = Cast::user($user_id);
\do_action('Bond/save_user', $user);
\do_action('Bond/save_user/' . $user->role, $user);
if (\has_action('Bond/save_user/' . $user->role)) {
\do_action('Bond/save_user/' . $user->role, $user);
}

// turn on posts cache
config()->cache->enabled = $original_state;
Expand Down
4 changes: 0 additions & 4 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,6 @@ protected function translationSettings()
if ($this->translation->service) {
$translation->setService($this->translation->service);
}

if (isset($this->translation->translate_on_save)) {
$translation->translateOnSavePost($this->translation->translate_on_save);
}
}

protected function appSettings()
Expand Down
247 changes: 223 additions & 24 deletions src/Services/Translation.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace Bond\Services;

use Bond\Settings\Languages;
use Bond\Utils\Cast;
use Bond\Utils\Query;
use Bond\Utils\Str;

// AWS Translate
Expand All @@ -21,6 +23,7 @@ class Translation

public function __construct()
{
$this->addTranslatePostHook();
}

public function setService(string $service)
Expand Down Expand Up @@ -262,40 +265,41 @@ protected function awsClient()



// WordPress Helpers
public function translateOnSavePost($post_types)

// Translate Posts Hook

public function addTranslatePostHook()
{
// runs on priority 9, before the default priority 10
// so it's already translated if needed
\add_action('Bond/translate_post', [$this, 'translatePostHook'], 1);
}

if (!app()->hasAcf()) {
public function removeTranslatePostHook()
{
\remove_action('Bond/translate_post', [$this, 'translatePostHook'], 1);
}

public function translatePostHook(int $post_id)
{
if (!Languages::isMultilanguage()) {
return;
}

if ($post_types === true) {
\add_action(
'Bond/save_post',
[$this, 'translateAllFields'],
9
);
} elseif (is_array($post_types)) {
foreach ($post_types as $post_type) {
\add_action(
'Bond/save_post/' . $post_type,
[$this, 'translateAllFields'],
9
);
}
}
// Translate all fields
// auto activated, later can allow config
$this->translateAllFields($post_id);

// Mulilanguage titles and slugs
$this->ensureTitleAndSlug($post_id);
}

public function translateAllFields($post)

public function translateAllFields(int $post_id)
{
if (!Languages::isMultilanguage()) {
if (!$this->hasService() || !app()->hasAcf()) {
return;
}

$fields = \get_fields($post->ID);
$fields = \get_fields($post_id);
if (empty($fields)) {
return;
}
Expand All @@ -309,7 +313,7 @@ public function translateAllFields($post)
// dd($translated, $updated);

foreach ($translated as $name => $value) {
\update_field($name, $value, $post->ID);
\update_field($name, $value, $post_id);
}
}

Expand Down Expand Up @@ -381,4 +385,199 @@ protected function translateMissingFields(

return $translated;
}


public function ensureTitleAndSlug(int $post_id)
{
if (!app()->hasAcf()) {
return;
}

$post = Cast::wpPost($post_id);
if (!$post) {
return;
}
// not for front page
if ($post->post_type === 'page' && \is_front_page()) {
return;
}

$codes = Languages::codes();

// get default language's title
$default_code = Languages::getDefault();
$default_suffix = Languages::fieldsSuffix($default_code);
$default_title = \get_field('title' . $default_suffix, $post->ID);

// or get the next best match
if (empty($default_title)) {
foreach ($codes as $code) {
if ($code === $default_code) {
continue;
}

$suffix = Languages::fieldsSuffix($code);
$title = \get_field('title' . $suffix, $post->ID);

// if found, we will translate and set the default_title
if (!empty($title)) {
$default_title = $this->fromTo($code, $default_code, $title);

\update_field(
'title' . $default_suffix,
$default_title,
$post->ID
);
break;
}
}
}

// no title yet, just skip
if (empty($default_title)) {
return;
}

// if WP title is different, update it
if ($post->post_title !== $default_title) {
\wp_update_post([
'ID' => $post->ID,
'post_title' => $default_title,
]);
$post->post_title = $default_title;
}

// we don't allow empty titles
foreach ($codes as $code) {
if ($code === $default_code) {
continue;
}

$suffix = Languages::fieldsSuffix($code);
$title = \get_field('title' . $suffix, $post->ID);

if (empty($title)) {
\update_field(
'title' . $suffix,
$this->fromTo($default_code, $code, $default_title) ?: $default_title,
$post->ID
);
}
}


// title is done
// now it's time for the slug

// not published yet, don't need to handle
if (empty($post->post_name)) {
return;
}

$is_hierarchical = \is_post_type_hierarchical($post->post_type);

foreach ($codes as $code) {
$suffix = Languages::fieldsSuffix($code);

$slug = \get_field('slug' . $suffix, $post->ID);

// remove parent pages
if (strpos($slug, '/') !== false) {
$slug = substr($slug, strrpos($slug, '/') + 1);
}

// get from title if empty
if (empty($slug)) {
$slug = \get_field('title' . $suffix, $post->ID);
}

// sanitize user input
$slug = Str::slug($slug);


// handle
if (Languages::isDefault($code)) {

// define full path if is hierarchical
$parent_path = [];
if ($is_hierarchical) {
$p = $post;

while ($p->post_parent) {
$p = \get_post($p->post_parent);
$parent_path[] = $p->post_name;
}
$parent_path = array_reverse($parent_path);

$post_path = implode('/', array_merge($parent_path, [$slug]));
} else {
$post_path = $slug;
}

// always update both WP and ACF
// WP always needs, as the user can change anytime
// ACF needs the first time, or if programatically changed
$id = \wp_update_post([
'ID' => $post->ID,
'post_name' => $slug,
]);
if ($id) {

// sync with the actual WP slug
// the slug above might have changed in some scenarios, like multiple posts with same slug
// so we fetch again
$slug = Query::slug($id);

// join if hierarchical
if ($is_hierarchical) {
$post_path = implode('/', array_merge($parent_path, [$slug]));
} else {
$post_path = $slug;
}
}
\update_field('slug' . $suffix, $post_path, $post->ID);
} else {


// prepend parent path
// only one level down, because the parent already has the translated slug
if ($is_hierarchical) {
$parent_path = [];

if ($post->post_parent) {
$p = Cast::post($post->post_parent);
if ($p) {
$parent_path[] = $p->slug($code);
}
}

$post_path_intent = implode('/', array_merge($parent_path, [$slug]));
} else {
$post_path_intent = $slug;
}

$post_path = $post_path_intent;

// search for posts with same slug, and increment until necessary
$i = 1;
while (Query::wpPostBySlug(
$post_path,
$post->post_type,
$code,
[
'post__not_in' => [$post->ID],
]
)) {
$post_path = $post_path_intent . '-' . (++$i);
}

// done, update ACF field
\update_field(
'slug' . $suffix,
$post_path,
$post->ID
);
}
}
}
}
Loading

0 comments on commit bda83a3

Please sign in to comment.