Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 1498 - Adding entity fields #1526

Merged
merged 20 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 67 additions & 3 deletions includes/admin_settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,20 @@ function tsml_settings_page()
tsml_alert(__('Invalid timezone selected.', '12-step-meeting-list'), 'error');
}
}

//save entity fields
if (isset($_POST['tsml_entity']) && isset($_POST['tsml_nonce']) && wp_verify_nonce($_POST['tsml_nonce'], $tsml_nonce)) {
$current_tsml_entity = tsml_get_option_array('tsml_entity');
$tsml_entity = [];
global $tsml_entity_fields;
foreach ( $tsml_entity_fields as $field ) {
$tsml_entity[$field] = isset($current_tsml_entity[$field]) ? $current_tsml_entity[$field] : '';
if (isset($_POST["tsml_$field"])) {
$tsml_entity[$field] = substr(trim(strval($_POST["tsml_$field"])), 0, 100);
}
}
update_option('tsml_entity', $tsml_entity);
}
gkovats marked this conversation as resolved.
Show resolved Hide resolved
?>

<!-- Admin page content should all be inside .wrap -->
Expand Down Expand Up @@ -332,7 +346,59 @@ function tsml_settings_page()
</form>
</div>

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check the order of these on the settings screen. I ended up putting this in spot 2, left column, and moved the Feeds settings to top of the middle column. But I don't stare at this screen much, so it's a guess.

<div class="postbox stack">
<div class="postbox stack">
<!-- Entity Form -->
<?php
$tsml_entity = tsml_get_option_array('tsml_entity');
?>
<div class="stack compact">
<h2>
<?php _e('Service Entity Information', '12-step-meeting-list') ?>
</h2>
<p>
<?php echo sprintf(__('Enter information for your service entity here to help identity the meeting source when sharing feeds with others.', '12-step-meeting-list'), get_post_type_archive_link('tsml_meeting')) ?>
gkovats marked this conversation as resolved.
Show resolved Hide resolved
</p>

<form method="post" class="stack compact" action="<?php echo $_SERVER['REQUEST_URI'] ?>">
<?php wp_nonce_field($tsml_nonce, 'tsml_nonce', false) ?>
<h3>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could these h3s be labels instead? the smaller type should look good as well

i would keep it Entity Name but change:

Entity Contact Email -> Administrative Contact Email
Entity Contact Phone -> Public Phone Number
Entity Location -> Your Service Area
Entity Website -> Website Address

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Your" felt redundant on looking at it, like it could be in all labels. This OK, or you think the "your" belongs?
image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's good! maybe make them labels though, if they're not already

<?php _e('Entity Name', '12-step-meeting-list') ?>
</h3>
<input type="text" name="tsml_entity" value="<?php echo esc_attr(isset($tsml_entity['entity']) ? $tsml_entity['entity'] : ''); ?>"
placeholder="<?php esc_attr_e('Entity Name', '12-step-meeting-list'); ?>" maxlength="100">
<h3>
<?php _e('Entity Contact Email', '12-step-meeting-list') ?>
</h3>
<input type="text" name="tsml_entity_email" value="<?php echo esc_attr(isset($tsml_entity['entity_email']) ? $tsml_entity['entity_email'] : ''); ?>"
placeholder="[email protected]" maxlength="80">
<h3>
<?php _e('Entity Contact Phone', '12-step-meeting-list') ?>
</h3>
<input type="text" name="tsml_entity_phone" value="<?php echo esc_attr(isset($tsml_entity['entity_phone']) ? $tsml_entity['entity_phone'] : ''); ?>"
placeholder="+18005551212" maxlength="50">
<h3>
<?php _e('Entity Location', '12-step-meeting-list') ?>
</h3>
<input type="text" name="tsml_entity_location" value="<?php echo esc_attr(isset($tsml_entity['entity_location']) ? $tsml_entity['entity_location'] : ''); ?>"
placeholder="<?php esc_attr_e('City, State, Country', '12-step-meeting-list')?>" maxlength="50">
<h3>
<?php _e('Entity Website', '12-step-meeting-list') ?>
</h3>
<p>
This will default to your current WordPress url
</p>
<input type="text" name="tsml_entity_url" value="<?php echo esc_attr(isset($tsml_entity['entity_url']) ? $tsml_entity['entity_url'] : ''); ?>"
placeholder="https://" maxlength="50">
<p>
<input type="submit" class="button" value="<?php esc_attr_e('Save', '12-step-meeting-list'); ?>">
</p>
</form>
</div>
</div>
</div>

<div class="stack">
<div class="postbox stack">
<!-- Feed Management -->
<h2>
<?php _e('Feed Management', '12-step-meeting-list') ?>
Expand Down Expand Up @@ -412,9 +478,7 @@ function tsml_settings_page()
</div>
<?php } ?>
</div>
</div>

<div class="stack">
<div class="postbox stack">
<!-- Switch UI -->
<div class="stack compact">
Expand Down
5 changes: 3 additions & 2 deletions includes/ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ function tsml_ajax_geocodes()
//ajax function to import the meetings in the import buffer
//used by admin_import.php
add_action('wp_ajax_tsml_import', function () {
global $tsml_data_sources, $tsml_custom_meeting_fields, $tsml_source_fields_map, $tsml_contact_fields;
global $tsml_data_sources, $tsml_custom_meeting_fields, $tsml_source_fields_map, $tsml_contact_fields, $tsml_entity_fields;

tsml_require_meetings_permission();

Expand Down Expand Up @@ -565,7 +565,8 @@ function tsml_ajax_geocodes()
//add custom meeting fields if available
$custom_meeting_fields = array_merge(
['types', 'data_source', 'conference_url', 'conference_url_notes', 'conference_phone', 'conference_phone_notes'],
array_keys($tsml_source_fields_map)
array_keys($tsml_source_fields_map),
$tsml_entity_fields
);
if (!empty($tsml_custom_meeting_fields)) {
$custom_meeting_fields = array_merge($custom_meeting_fields, array_keys($tsml_custom_meeting_fields));
Expand Down
50 changes: 43 additions & 7 deletions includes/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -1169,7 +1169,9 @@ function tsml_feedback_url($meeting)
//used: tsml_ajax_meetings(), single-locations.php, archive-meetings.php
function tsml_get_meetings($arguments = [], $from_cache = true, $full_export = false)
{
global $tsml_cache, $tsml_cache_writable, $tsml_contact_fields, $tsml_contact_display, $tsml_data_sources, $tsml_custom_meeting_fields, $tsml_source_fields_map;
global $tsml_cache, $tsml_cache_writable, $tsml_contact_fields, $tsml_contact_display, $tsml_data_sources, $tsml_custom_meeting_fields, $tsml_source_fields_map, $tsml_entity_fields;

$tsml_entity = tsml_get_entity();

//start by grabbing all meetings
if ($from_cache && $tsml_cache_writable && $meetings = file_get_contents(WP_CONTENT_DIR . $tsml_cache)) {
Expand Down Expand Up @@ -1221,7 +1223,7 @@ function tsml_get_meetings($arguments = [], $from_cache = true, $full_export = f
'conference_phone' => isset($meeting_meta[$post->ID]['conference_phone']) ? $meeting_meta[$post->ID]['conference_phone'] : null,
'conference_phone_notes' => isset($meeting_meta[$post->ID]['conference_phone_notes']) ? $meeting_meta[$post->ID]['conference_phone_notes'] : null,
'types' => empty($meeting_meta[$post->ID]['types']) ? [] : array_values(unserialize($meeting_meta[$post->ID]['types'])),
'author' => get_the_author_meta('user_login', $post->post_author)
'author' => get_the_author_meta('user_login', $post->post_author),
], $locations[$post->post_parent]);

// include user-defined meeting fields when doing a full export
Expand Down Expand Up @@ -1285,10 +1287,24 @@ function tsml_get_meetings($arguments = [], $from_cache = true, $full_export = f
}

//add feedback_url only if present
//@TODO: check if this is in use? conflict with entity?
if ($feedback_url = tsml_feedback_url($meeting)) {
$meeting['feedback_url'] = $feedback_url;
}

//add entity fields
if (!empty($meeting_meta[$post->ID]['data_source'])) {
//add sourced entity fields
foreach ($tsml_entity_fields as $entity_field) {
if (isset($meeting_meta[$post->ID][$entity_field])) {
$meeting[$entity_field] = $meeting_meta[$post->ID][$entity_field];
}
}
} else {
//else add local entity info
$meeting = array_merge($meeting, $tsml_entity);
}

$meetings[] = $meeting;
}

Expand Down Expand Up @@ -1392,7 +1408,7 @@ function tsml_get_meetings($arguments = [], $from_cache = true, $full_export = f
//called in tsml_get_meetings(), tsml_get_locations()
function tsml_get_meta($type, $id = null)
{
global $wpdb, $tsml_custom_meeting_fields, $tsml_contact_fields, $tsml_source_fields_map;
global $wpdb, $tsml_custom_meeting_fields, $tsml_contact_fields, $tsml_source_fields_map, $tsml_entity_fields;
$keys = [
'tsml_group' => array_keys($tsml_contact_fields),
'tsml_location' => ['formatted_address', 'latitude', 'longitude', 'approximate', 'timezone'],
Expand All @@ -1411,6 +1427,7 @@ function tsml_get_meta($type, $id = null)
],
array_keys($tsml_contact_fields),
array_keys($tsml_source_fields_map),
$tsml_entity_fields,
empty($tsml_custom_meeting_fields) ? [] : array_keys($tsml_custom_meeting_fields)
),
];
Expand Down Expand Up @@ -1488,7 +1505,7 @@ function tsml_meeting_types($types)
//sanitizes imported meetings before processing
function tsml_sanitize_import_meetings($meetings, $data_source_url = null, $data_source_parent_region_id = null) {

global $tsml_programs, $tsml_program, $tsml_days, $tsml_meeting_attendance_options, $tsml_data_sources, $tsml_contact_fields;
global $tsml_programs, $tsml_program, $tsml_days, $tsml_meeting_attendance_options, $tsml_data_sources, $tsml_contact_fields, $tsml_entity_fields;

//track group fields and unique_group_values
$group_fields = array_keys($tsml_contact_fields);
Expand Down Expand Up @@ -1774,6 +1791,11 @@ function tsml_sanitize_import_meetings($meetings, $data_source_url = null, $data
}
}

//cleanup entity fields
foreach($tsml_entity_fields as $field) {
gkovats marked this conversation as resolved.
Show resolved Hide resolved
$meetings[$i][$field] = substr(trim(strval(isset($meetings[$i][$field]) ? $meetings[$i][$field] : '')), 0, 100);
joshreisner marked this conversation as resolved.
Show resolved Hide resolved
}

//preserve row number for errors later
$meetings[$i]['row'] = $i + 2;
}
Expand Down Expand Up @@ -2029,6 +2051,20 @@ function tsml_log($type, $info = null, $input = null)
update_option('tsml_log', $tsml_log);
}

//function: build and return the entity array of fields
//used: tsml_get_meetings, to supply entity for locally managed meetings / non-imported meetings
function tsml_get_entity()
{
$saved_tsml_entity = tsml_get_option_array('tsml_entity');
return [
'entity' => isset($saved_tsml_entity['entity']) ? $saved_tsml_entity['entity'] : get_bloginfo('name'),
'entity_email' => isset($saved_tsml_entity['entity_email']) ? $saved_tsml_entity['entity_email'] : get_bloginfo('admin_email'),
'entity_phone' => isset($saved_tsml_entity['entity_phone']) ? $saved_tsml_entity['entity_phone'] : '',
'entity_location' => isset($saved_tsml_entity['entity_location']) ? $saved_tsml_entity['entity_location'] : '',
'entity_url' => isset($saved_tsml_entity['entity_url']) ? $saved_tsml_entity['entity_url'] : get_bloginfo('url'),
];
}

//function: link to meetings page with parameters (added to link dropdown menus for SEO)
//used: archive-meetings.php
function tsml_meetings_url($parameters)
Expand Down Expand Up @@ -2550,7 +2586,7 @@ function tsml_get_changed_import_meetings($feed_meetings, $data_source_url, $dat
*/
function tsml_compare_imported_meeting($local_meeting, $import_meeting)
{
global $tsml_export_columns, $tsml_source_fields_map;
global $tsml_export_columns, $tsml_source_fields_map, $tsml_entity_fields;

$local_meeting = (array) $local_meeting;
$import_meeting = (array) $import_meeting;
Expand All @@ -2561,9 +2597,9 @@ function tsml_compare_imported_meeting($local_meeting, $import_meeting)
$local_meeting[$field] = $local_meeting[$source_field];
}
}

$compare_fields = array_merge(array_keys($tsml_export_columns), $tsml_entity_fields);
$compare_fields = array_diff(
array_keys($tsml_export_columns),
$compare_fields,
//these fields are unique internal fields, not content fields for comparison
explode(',', 'id,slug,author,data_source,data_source_name')
);
Expand Down
9 changes: 9 additions & 0 deletions includes/variables.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@
}
}

//define entity fields (stored in option tsml_entity)
$tsml_entity_fields = [
'entity',
'entity_email',
'entity_phone',
'entity_location',
'entity_url',
];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to add feedback email here? the idea is that they should pass through from the imported service entity


//empty global curl handle in case we need it
$tsml_curl_handle = null;

Expand Down
31 changes: 29 additions & 2 deletions templates/single-meetings.php
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,35 @@ class="btn btn-default btn-block contact-phone">
<?php
} ?>
<li class="list-group-item list-group-item-updated">
<?php _e('Updated', '12-step-meeting-list') ?>
<?php the_modified_date() ?>
<p class="meeting-updated">
<?php _e('Updated', '12-step-meeting-list') ?>
<?php the_modified_date() ?>
</p>
<?php
if (!empty($meeting->{'data_source'})) {
Copy link
Contributor

@joshreisner joshreisner Sep 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we need some intro text here potentially like "This meeting listing is provided by:"

let's not show the email address - this is more for administrative purposes

the feedback email form should either be hidden and we add something here, or it should send to the entity's feedback_email addresses if present

minor: could we use the $meeting->data_source pattern for this and the other vars?

minor: i would like to steer away from using <br> tags - could this be Ps or a UL?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding "This meeting listing is provided by:" only concern it will show up everywhere if we display for local and imported meetings, and it just adds that one more line to what your eye is scanning for
image

Look correct to you? Should it be smaller?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or it should send to the entity's feedback_email addresses if present

Honestly this raises questions I want to talk about, cause it'll be a mess typing it out. Don't feel equipped with enough history on this tool to answer them myself.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, yeah, i'm not so sure. perhaps less is more?

my reason for wanting to add it is that we want to make it clear what this section is - some users might get confused and think it is meeting information.

the purpose of this section is to be like this section in the app:
Screenshot 2024-09-24 at 3 11 42 PM

if we could replicate the headline style for the other sections for the entity name, and make the url and phone buttons like in this pic:

Screenshot 2024-09-24 at 3 14 05 PM

we might try the This meeting listing is provided by: above the headline in a <small>?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here's what it currently looks like in this PR for TSML UI:

image

not that it needs to match per se but just for context

$entity = !empty($meeting->{'entity'}) ? $meeting->{'entity'} : '';
$entity_url = !empty($meeting->{'entity_url'}) ? $meeting->{'entity_url'} : '';
$entity_label = ($entity_url) ? '<a href="'. esc_attr($entity_url) . '" target="_blank">' . $entity . '</a>' : $entity;
$entity_lines = [];
if (trim($entity_label)) {
$entity_lines[] = $entity_label;
}
if (!empty($meeting->{'entity_location'})) {
$entity_lines[] = $meeting->{'entity_location'};
}
if (!empty($meeting->{'entity_email'})) {
$entity_lines[] = '<a href="mailto:' . esc_attr($meeting->{'entity_email'}) . '">' . $meeting->{'entity_email'} . '</a>';
}
if (!empty($meeting->{'entity_phone'})) {
$entity_lines[] = '<a href="tel:' . esc_attr($meeting->{'entity_phone'}) . '">' . $meeting->{'entity_phone'} . '</a>';
}
if (count($entity_lines)) {
?>
<p class="meeting-entity"><?php echo implode( '<br/>' . PHP_EOL, $entity_lines ); ?></p>
<?php
}
}
?>
</li>
</ul>
</div>
Expand Down