| | |
| | | <?php |
| | | // /content/progress.php |
| | | use JVBase\meta\MetaManager; |
| | | use JVBase\meta\Meta; |
| | | |
| | | function altr_progress():array |
| | | { |
| | |
| | | 'hide_children' => true, |
| | | 'is_timeline' => true, |
| | | 'show_feed' => true, |
| | | 'show_directory'=> true, |
| | | 'directory_extra'=> ['goal', 'skin-type','age'], |
| | | 'hierarchical' => true, |
| | | 'icon' => 'arrows-left-right', |
| | | 'rewrite' => [ |
| | |
| | | 'label' => 'Progression', |
| | | ] |
| | | ], |
| | | 'custom_order' => [ |
| | | 'number' => [ |
| | | 'label' => 'Number of Treatments', |
| | | 'icon' => 'hash-straight', |
| | | 'for' => 'progress', |
| | | ] |
| | | ], |
| | | 'seo' => [ |
| | | 'schema' => [ |
| | | 'type' => 'BeforeAfter', |
| | | 'name' => '{{post_title}}', |
| | | 'description' => '{{post_excerpt}}', |
| | | 'about' => ['@id' => '{{site_url}}/#laser-removal-service'], |
| | | 'temporalCoverage' => '{{post_date}}/{{last_date}}', |
| | | 'additionalProperty' => [ |
| | | ['name' => 'Number of sessions', 'value' => '{{number.name}}'], |
| | | ['name' => 'Treatment area', 'value' => '{{body-part.name}}'], |
| | | ['name' => 'Tattoo style', 'value' => '{{style.name}}'], |
| | | ['name' => 'Skin type', 'value' => '{{skin-type.name}}'], |
| | | ['name' => 'Goal', 'value' => '{{goal.name}}'], |
| | | ], |
| | | 'associatedMedia' => '{{timeline_photos}}', // parent post thumbnail = before; each child post has a post thumbnail, too |
| | | 'associatedMedia' => '{{timeline_photos}}', |
| | | ], |
| | | 'meta' => [ |
| | | 'title' => '{{body-part.name}} Laser Tattoo Removal – Before & After', |
| | | 'description' => 'Documented progress of {{body-part.name}} laser tattoo removal over {{number.name}} sessions.', |
| | | 'title' => '{{style.name}} {{theme.name}} Tattoo – Before & After {{number}} Laser Removal Sessions', |
| | | 'description' => 'See this {{style.name}} {{theme.name}} {{age.name}}-old tattoo before and after {{number}} laser tattoo removal treatments on the {{body-part.name}}.', |
| | | ], |
| | | 'archive' => [ |
| | | 'type' => 'CollectionPage', |
| | | 'name' => 'Tattoos Before and After Laser Tattoo Removal', |
| | | 'type' => 'CollectionPage', |
| | | 'name' => 'Tattoos Before and After Laser Tattoo Removal', |
| | | ], |
| | | ], |
| | | 'feed' => [ |
| | |
| | | 'trash' => 'Scrap', |
| | | 'delete' => 'Permanently Delete' |
| | | ], |
| | | 'section' => 'progression', |
| | | 'for_all' => true, |
| | | ], |
| | | 'post_date' => [ |
| | |
| | | 'section' => 'progression', |
| | | 'hint' => 'Not public, just to make it easier to find' |
| | | ], |
| | | 'body-part' => [ |
| | | 'type' => 'taxonomy', |
| | | 'taxonomy' => 'body-part', |
| | | 'label' => 'Body Part', |
| | | 'autocomplete' => true, |
| | | 'quickEdit' => true, |
| | | 'createNew' => true, |
| | | 'section' => 'progression' |
| | | ], |
| | | 'goal' => [ |
| | | 'type' => 'taxonomy', |
| | | 'taxonomy' => 'goal', |
| | |
| | | 'createNew' => true, |
| | | 'section' => 'progression', |
| | | 'for_all' => true, |
| | | ], |
| | | 'body-part' => [ |
| | | 'type' => 'taxonomy', |
| | | 'taxonomy' => 'body-part', |
| | | 'label' => 'Body Part', |
| | | 'autocomplete' => true, |
| | | 'quickEdit' => true, |
| | | 'createNew' => true, |
| | | 'section' => 'progression' |
| | | 'hidden' => true, |
| | | ], |
| | | 'style' => [ |
| | | 'type' => 'taxonomy', |
| | |
| | | 'createNew' => true, |
| | | 'section' => 'progression' |
| | | ], |
| | | 'theme' => [ |
| | | 'type' => 'taxonomy', |
| | | 'taxonomy' => 'theme', |
| | | 'autocomplete' => true, |
| | | 'label' => 'Tattoo Theme', |
| | | 'quickEdit' => true, |
| | | 'createNew' => true, |
| | | 'section' => 'progression' |
| | | ], |
| | | 'skin-type' => [ |
| | | 'type' => 'taxonomy', |
| | | 'taxonomy' => 'skin-type', |
| | |
| | | 'section' => 'progression' |
| | | ], |
| | | 'number' => [ |
| | | 'type' => 'taxonomy', |
| | | 'taxonomy' => 'number', |
| | | 'autocomplete' => true, |
| | | 'type' => 'text', |
| | | 'subtype' => 'number', |
| | | 'label' => 'Number of Treatments', |
| | | 'quickEdit' => true, |
| | | 'createNew' => true, |
| | | 'section' => 'progression' |
| | | 'section' => 'progression', |
| | | 'for_all' => true, |
| | | 'hidden' => true, //auto calculated |
| | | ], |
| | | 'post_content' => [ |
| | | 'type' => 'textarea', |
| | |
| | | 'label' => 'Notes', |
| | | 'section' => 'progression', |
| | | 'for_all' => true, |
| | | ], |
| | | 'last_date' => [ |
| | | 'type' => 'number', |
| | | 'label' => 'Last Date', |
| | | 'hidden' => true, |
| | | 'default' => 0, |
| | | 'for_all' => true, |
| | | ] |
| | | ], |
| | | 'upload_title' => 'Upload Before & Afters', |
| | |
| | | |
| | | add_filter('jvbFeedItem', 'altr_progress_item', 10, 2); |
| | | |
| | | function altr_progress_item(string $out, array $config):string |
| | | function altr_progress_item(string $out, string $content):string |
| | | { |
| | | if (!in_array('progress', $config['content'])) { |
| | | if ($content !== 'progress') { |
| | | return $out; |
| | | } |
| | | |
| | | ob_start(); |
| | | ?> |
| | | <details class="item feed col a-start" data-timeline> |
| | | <summary> |
| | | <div class="feed item col progress" data-timeline> |
| | | <div class="images"> |
| | | <a> |
| | | <span>Before</span> |
| | | <img width="300px" height="300px" loading="lazy" decoding="async" class="before"> |
| | | <img width="300px" height="300px" loading="lazy" decoding="async" class="after"> |
| | | <span>After</span> |
| | | <span class="before-text">Before</span> |
| | | <img data-field="before" width="300px" height="300px" sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 800px" loading="lazy" decoding="async" class="before"> |
| | | <img data-field="after" width="300px" height="300px" sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 800px" loading="lazy" decoding="async" class="after"> |
| | | <span class="after-text">After</span> |
| | | </a> |
| | | </summary> |
| | | <div class="more"> |
| | | <p class="started">Started:<time></time></p> |
| | | <p class="updated">Last treated:<time></time></p> |
| | | <p class="total">Total Treatments: <b></b></p> |
| | | <ul class="term-list"><li><a></a></li></ul> |
| | | </div> |
| | | </details> |
| | | <details> |
| | | <summary> |
| | | <?= jvbIcon('dots-three')?> |
| | | </summary> |
| | | <div class="item-info"> |
| | | <p data-field="started">Started: <time></time></p> |
| | | <p data-field="updated">Last treated: <time></time></p> |
| | | <p data-field="number">Total Treatments: <b></b></p> |
| | | <ul data-field="goal" class="term-list"><?= array_key_exists('icon', JVB_TAXONOMY['goal']) ? jvbIcon(JVB_TAXONOMY['goal']['icon']) : '' ?><li><a></a></li></ul> |
| | | <ul data-field="body-part" class="term-list"><?= array_key_exists('icon', JVB_TAXONOMY['body-part']) ? jvbIcon(JVB_TAXONOMY['body-part']['icon']) : '' ?><li><a><i></i></a></li></ul> |
| | | <ul data-field="skin-type" class="term-list"><?= array_key_exists('icon', JVB_TAXONOMY['skin-type']) ? jvbIcon(JVB_TAXONOMY['skin-type']['icon']) : '' ?><li><a><i></i></a></li></ul> |
| | | <ul data-field="age" class="term-list"><?= array_key_exists('icon', JVB_TAXONOMY['age']) ? jvbIcon(JVB_TAXONOMY['age']['icon']) : '' ?><li><a><i></i></a></li></ul> |
| | | <ul data-field="style" class="term-list"><?= array_key_exists('icon', JVB_TAXONOMY['style']) ? jvbIcon(JVB_TAXONOMY['style']['icon']) : '' ?><li><a><i></i></a></li></ul> |
| | | <ul data-field="theme" class="term-list"><?= array_key_exists('icon', JVB_TAXONOMY['theme']) ? jvbIcon(JVB_TAXONOMY['theme']['icon']) : '' ?><li><a><i></i></a></li></ul> |
| | | </div> |
| | | </details> |
| | | </div> |
| | | |
| | | <?php |
| | | return ob_get_clean(); |
| | | } |
| | |
| | | return $first.$last; |
| | | } |
| | | |
| | | add_filter('jvb_directory_render_item', 'altr_progress_directory_item', 10, 4); |
| | | |
| | | function altr_progress_directory_item(string $out, array $item, string $content, string $extra):string |
| | | { |
| | | if ($content !== 'progress') return $out; |
| | | $parent = (int)$item['id']; |
| | | $children = get_children($parent); |
| | | $before = jvbFormatImage(get_post_thumbnail_id($parent),'tiny','directory-preview',false); |
| | | $after = ''; |
| | | if ($children) { |
| | | $last = array_key_last($children); |
| | | $after = jvbIcon('logo-triangle-fill').jvbFormatImage(get_post_thumbnail_id($last),'tiny','directory-preview',false); |
| | | } |
| | | |
| | | return '<li class="row btw"> |
| | | |
| | | <a href="'.$item['url'].'" title="More about '.$item['name'].'"> |
| | | '.$item['name'].'</a>'.$extra.' |
| | | <div class="image">'.$before.$after.'</div> |
| | | </li>'; |
| | | } |
| | | |
| | | |
| | | add_filter('jvbSEOResolveVariable', 'altr_progress_variables', 10, 6); |
| | | function altr_progress_variables(mixed $return, string $variable, ?int $ID, ?string $objectType, ?string $contentType, ?MetaManager $meta):mixed |
| | | function altr_progress_variables(mixed $return, string $variable, ?int $ID, ?string $objectType, ?string $contentType, ?Meta $meta):mixed |
| | | { |
| | | if ($contentType !== 'progress' || !in_array($variable, ['timeline_photos', 'last_date'])) { |
| | | return $return; |
| | |
| | | // $variable === 'last_date' |
| | | return get_the_date('c', $children[array_key_last($children)]); |
| | | } |
| | | |
| | | |
| | | add_action('wp_after_insert_post', 'altr_update_progress_alt_text', 999, 3); |
| | | |
| | | function altr_update_progress_alt_text(int $ID, WP_Post $post, bool $update, ?WP_Post $before = null) { |
| | | if ($post->post_type !== 'altr_progress') { |
| | | return; |
| | | } |
| | | $thumbnail = get_post_thumbnail_id($ID); |
| | | if (!$thumbnail || $thumbnail === 0) { |
| | | return; |
| | | } |
| | | $meta = new Meta($ID, 'post'); |
| | | $number = $meta->get('number'); |
| | | $terms = $meta->getAll(['style', 'body-part','goal', 'skin-type', 'age', 'timeline']); |
| | | foreach($terms as $slug => $value) { |
| | | $terms = array_filter( |
| | | array_map(function($term) use($slug) { |
| | | return get_term((int)$term, BASE.$slug); |
| | | },explode(',', $value) |
| | | ), function($term) { |
| | | return $term && !is_wp_error($term); |
| | | } |
| | | ); |
| | | |
| | | switch ($slug) { |
| | | case 'skin-type': |
| | | $slug = 'skinType'; |
| | | break; |
| | | case 'body-part': |
| | | $slug = 'bodyPart'; |
| | | break; |
| | | } |
| | | |
| | | if (empty($terms)) { |
| | | $$slug = ''; |
| | | } else { |
| | | $$slug = jvbCommaList(array_map(function($term){ return $term->name; }, $terms)); |
| | | } |
| | | } |
| | | $title = sprintf( |
| | | "%s | %s Before & After Laser Tattoo Removal", |
| | | $post->post_title, |
| | | $style |
| | | ); |
| | | $style = ($style === '') ? $style : ' '.$style; |
| | | $age = ($age === '') ? $age : ' '.$age.' old'; |
| | | $bodyPart = ($bodyPart === '') ? $bodyPart : ' on the '.$bodyPart; |
| | | $skinType = ($skinType === '') ? $skinType : ' on a person with FitzPatrick Skin Type '.$skinType; |
| | | $timeline = ($timeline === '') ? $timeline : ' '.$timeline.' after their '.$number.' treatment'; |
| | | $goal = ($goal === '') ? $goal : ' This client is hoping for '.$goal; |
| | | |
| | | $alt = sprintf( |
| | | "A photo of a%s%s tattoo%s%s%s.%s", |
| | | $style, |
| | | $age, |
| | | $bodyPart, //on the ... |
| | | $skinType, //on a person with FitzPatrick Scale skin type ... |
| | | $timeline, //", x weeks after their %number% treatment" |
| | | $goal //"This client is hoping for %goal%." |
| | | ); |
| | | |
| | | wp_update_post([ |
| | | 'ID' => $thumbnail, |
| | | 'post_title' => $title |
| | | ]); |
| | | update_post_meta($thumbnail, '_wp_attachment_image_alt', $alt); |
| | | } |