5, 'message' => ''], $arguments, 'tsml_next_meetings');
$meetings = tsml_get_meetings([
'day' => intval(current_time('w')),
'time' => 'upcoming',
'attendance_option' => 'active',
]);
if (!count($meetings) && empty($arguments['message'])) {
return false;
}
if (!count($meetings) && !empty($arguments['message'])) {
return '
' . sanitize_text_field($arguments['message']) . '
';
}
$meetings = array_slice($meetings, 0, $arguments['count']);
$rows = '';
foreach ($meetings as $meeting) {
$meeting_types = $classes = '';
if (!empty($meeting['types'])) {
$classes = tsml_to_css_classes($meeting['types']);
$meeting_types = ' ' . tsml_format_types($meeting['types']) . '';
}
if (!empty($meeting['notes'])) {
$classes .= ' notes';
}
$meeting_location = '';
if (!empty($meeting['location'])) {
$meeting_location = $meeting['location'];
}
if ($meeting['attendance_option'] == 'online' || $meeting['attendance_option'] == 'inactive') {
$meeting_location = !empty($meeting['group']) ? $meeting['group'] : '';
}
$region = '';
if (!empty($meeting['sub_region'])) {
$region = $meeting['sub_region'];
} elseif (!empty($meeting['region'])) {
$region = $meeting['region'];
}
$rows .= '
| ' . tsml_format_time($meeting['time']) . ' |
' . @$meeting['name'] . '' . $meeting_types . ' |
' . $meeting_location . '
' . ($meeting['attendance_option'] != 'in_person' ? $tsml_meeting_attendance_options[$meeting['attendance_option']] : '') . '
|
' . $region . ' |
';
}
return '
| ' . __('Time', '12-step-meeting-list') . ' |
' . __('Meeting', '12-step-meeting-list') . ' |
' . __('Location', '12-step-meeting-list') . ' |
' . __('Region', '12-step-meeting-list') . ' |
' . $rows . '
';
}
add_shortcode('tsml_next_meetings', 'tsml_next_meetings');
// output a list of types with links for AA-DC
add_shortcode('tsml_types_list', function () {
global $tsml_types_in_use, $tsml_programs, $tsml_program, $tsml_user_interface;
$types = [];
foreach ($tsml_types_in_use as $type) {
if ($tsml_user_interface === 'tsml_ui') {
$filter_url = tsml_meetings_url([
'type' => str_replace(' ', '-', strtolower($tsml_programs[$tsml_program]['types'][$type]))
]);
} else {
$filter_url = tsml_meetings_url(['tsml-day' => 'any', 'tsml-type' => $type]);
}
$types[$tsml_programs[$tsml_program]['types'][$type]] = '' . $tsml_programs[$tsml_program]['types'][$type] . '';
}
ksort($types);
return 'Types
';
});
// output a react meeting finder widget https://github.com/code4recovery/tsml-ui
function tsml_ui($arguments = [])
{
global $tsml_nonce, $tsml_conference_providers, $tsml_language, $tsml_programs, $tsml_program, $tsml_ui_config,
$tsml_feedback_addresses, $tsml_cache, $tsml_cache_writable, $tsml_distance_units, $tsml_columns, $tsml_timezone,
$tsml_slug, $tsml_map;
$defaults = shortcode_atts([
'distance' => '',
'language' => '',
'mode' => '',
'region' => '',
'search' => '',
'time' => '',
'type' => '',
'view' => '',
'weekday' => '',
], $arguments, 'tsml_ui');
// sanitize arrays
foreach (['region', 'time', 'type', 'weekday'] as $key) {
$defaults[$key] = explode(',', $defaults[$key]);
$defaults[$key] = array_map('sanitize_title', $defaults[$key]);
$defaults[$key] = array_filter($defaults[$key]);
}
// sanitize language
$defaults['language'] = sanitize_text_field($defaults['language']);
// sanitize search
$defaults['search'] = sanitize_text_field($defaults['search']);
// view must either be table or map
if (!in_array($defaults['view'], ['table', 'map'])) {
$defaults['view'] = 'table';
}
// mode must either be search, location, or me
if (!in_array($defaults['mode'], ['search', 'location', 'me'])) {
$defaults['mode'] = 'search';
}
// distance must be an integer
$defaults['distance'] = intval($defaults['distance']);
$defaults['distance'] = in_array($defaults['distance'], [1, 2, 5, 10, 15, 25, 50, 100])
? strval($defaults['distance'])
: '';
if (empty($defaults['distance'])) {
unset($defaults['distance']);
}
// enqueue app script
$js = defined('TSML_UI_PATH') ? TSML_UI_PATH : 'https://tsml-ui.code4recovery.org/app.js';
wp_enqueue_script('tsml_ui', $js, [], TSML_VERSION, ['in_footer' => true, 'strategy' => 'async']);
// get program types and type descriptions
$types = !empty($tsml_programs[$tsml_program]['types'])
? $tsml_programs[$tsml_program]['types']
: [];
$type_descriptions = !empty($tsml_programs[$tsml_program]['type_descriptions'])
? $tsml_programs[$tsml_program]['type_descriptions']
: [];
// apply settings
wp_localize_script(
'tsml_ui',
'tsml_react_config',
array_replace_recursive(
[
'columns' => array_keys($tsml_columns),
'defaults' => $defaults,
'conference_providers' => $tsml_conference_providers,
'distance_unit' => $tsml_distance_units,
'feedback_emails' => array_values($tsml_feedback_addresses),
'flags' => $tsml_programs[$tsml_program]['flags'],
'language' => $defaults['language'],
'map' => $tsml_map,
'strings' => [
$tsml_language => array_replace_recursive(
$tsml_columns,
compact('types', 'type_descriptions'),
// Get any existing strings for this language if they exist
!empty($tsml_ui_config['strings'][$tsml_language]) ? $tsml_ui_config['strings'][$tsml_language] : []
),
],
],
$tsml_ui_config
)
);
// use meetings.json if it's writable, otherwise use the admin-ajax URL to the feed
$data = $tsml_cache_writable && file_exists(WP_CONTENT_DIR . $tsml_cache)
? content_url($tsml_cache) . '?' . filemtime(WP_CONTENT_DIR . $tsml_cache)
: admin_url('admin-ajax.php') . '?action=meetings&nonce=' . wp_create_nonce($tsml_nonce);
// remove URL domain to fix CORS issues caused by GoDaddy Managed WP
$url = parse_url($data);
$data = $url['path'] . '?' . $url['query'];
// pretty permalinks
$meeting_finder = parse_url(tsml_meetings_url());
$request_starts_with_meeting_finder_path = substr($_SERVER['REQUEST_URI'], 0, strlen($meeting_finder['path'])) === $meeting_finder['path'];
$tsml_path = empty($meeting_finder['query']) && $request_starts_with_meeting_finder_path ? $meeting_finder['path'] : '';
return "";
}
add_shortcode('tsml_react', 'tsml_ui');
add_shortcode('tsml_ui', 'tsml_ui');
// output a list of regions with links for AA-DC
add_shortcode('tsml_regions_list', function () {
// run function recursively
function get_regions($parent = 0)
{
global $tsml_user_interface;
$taxonomy = 'tsml_region';
// phpcs:ignore
$terms = get_terms(compact('taxonomy', 'parent'));
if (!count($terms)) {
return;
}
foreach ($terms as &$term) {
if ($tsml_user_interface === 'tsml_ui') {
$filter_url = tsml_meetings_url(['region' => $term->slug]);
} else {
$filter_url = tsml_meetings_url(
['tsml-day' => 'any', 'tsml-region' => $term->slug]
);
}
$term = '' . $term->name . '' . get_regions($term->term_id) . '';
}
return '';
}
return 'Regions
' . get_regions();
});