Here’s a tiny, drop-in PHP “SDK” you can include in a theme or plugin to consume the Artemis Herbal Remedies Database. It:
- Wraps the REST calls (works inside or outside WordPress)
- Handles query params & taxonomy filters (arrays or strings)
- Supports pagination helpers
- Adds optional caching (uses WP transients when available)
- Returns decoded arrays with headers when useful
1) Client Class (single file)
Create class-artemis-herbs-client.php with:
<?php
/**
* Minimal client for the Artemis Herbal Remedies Database (WordPress REST API)
* Base URL: https://herbs.artemis-temple.com/wp-json
*/
class Artemis_Herbs_Client {
protected $base;
protected $timeout;
protected $user_agent;
protected $cache_ttl; // seconds
public function __construct(array $opts = []) {
$this->base = rtrim($opts['base'] ?? 'https://herbs.artemis-temple.com/wp-json', '/');
$this->timeout = (int)($opts['timeout'] ?? 12);
$this->user_agent = $opts['user_agent'] ?? 'ArtemisHerbsClient/1.0';
$this->cache_ttl = isset($opts['cache_ttl']) ? (int)$opts['cache_ttl'] : 600; // 10 min
}
/** ---------- Public endpoints ---------- */
/** GET /wp/v2/artm_monograph (list) */
public function list_monographs(array $args = [], bool $with_headers = false) {
$path = '/wp/v2/artm_monograph';
$args = $this->normalize_args($args);
return $this->get($path, $args, $with_headers);
}
/** Generator over all pages */
public function iterate_monographs(array $args = []) : \Generator {
$page = 1;
$args = $this->normalize_args($args);
$args['per_page'] = $args['per_page'] ?? 100;
do {
$args['page'] = $page;
[$items, $headers] = $this->get('/wp/v2/artm_monograph', $args, true);
foreach ($items as $row) { yield $row; }
$total_pages = isset($headers['x-wp-totalpages'][0]) ? (int)$headers['x-wp-totalpages'][0] : 0;
$page++;
} while ($total_pages && $page <= $total_pages);
}
/** GET /wp/v2/artm_monograph/{id} */
public function get_monograph($id, array $args = []) {
$path = '/wp/v2/artm_monograph/' . rawurlencode($id);
$args = $this->normalize_args($args);
return $this->get($path, $args);
}
/** GET /wp/v2/{taxonomy} (list terms) */
public function list_terms(string $taxonomy, array $args = [], bool $with_headers = false) {
$path = '/wp/v2/' . $taxonomy;
$args = $this->normalize_args($args);
return $this->get($path, $args, $with_headers);
}
/** GET /wp/v2/{taxonomy}/{id} */
public function get_term(string $taxonomy, $id, array $args = []) {
$path = '/wp/v2/' . $taxonomy . '/' . rawurlencode($id);
$args = $this->normalize_args($args);
return $this->get($path, $args);
}
/** Convenience: search monographs by keyword */
public function search_monographs(string $q, array $args = []) {
$args['search'] = $q;
return $this->list_monographs($args);
}
/** ---------- Internals ---------- */
/** Normalize filters: allow array values for tax filters and _fields */
protected function normalize_args(array $args) : array {
// Support arrays for taxonomy filters and _fields; http_build_query handles [].
// Add safe defaults:
if (!isset($args['_fields'])) {
// small default response
$args['_fields'] = ['id','slug','link','title','meta'];
}
// Many consumers want embed sometimes
if (!empty($args['_embed']) && $args['_embed'] !== 'false') {
$args['_embed'] = '1';
} else {
unset($args['_embed']);
}
return $args;
}
/** GET helper with optional caching; returns [body, headers] when $with_headers */
protected function get(string $path, array $params = [], bool $with_headers = false) {
$url = $this->base . $path;
if (!empty($params)) {
$url .= (strpos($url, '?') === false ? '?' : '&') . http_build_query($params);
}
// Cache key
$ckey = 'ahc_' . md5($url);
if ($this->cache_ttl > 0 && function_exists('get_transient')) {
$cached = get_transient($ckey);
if ($cached) {
return $with_headers ? [$cached['body'], $cached['headers']] : $cached['body'];
}
}
// Prefer WP HTTP API if available
if (function_exists('wp_remote_get')) {
$res = wp_remote_get($url, [
'timeout' => $this->timeout,
'user-agent' => $this->user_agent,
]);
if (is_wp_error($res)) {
throw new \RuntimeException('HTTP error: ' . $res->get_error_message());
}
$code = (int) wp_remote_retrieve_response_code($res);
$raw = wp_remote_retrieve_body($res);
$hdrs = wp_remote_retrieve_headers($res)->getAll();
} else {
// Fallback to cURL
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_USERAGENT => $this->user_agent,
CURLOPT_HEADER => true,
]);
$resp = curl_exec($ch);
if ($resp === false) {
throw new \RuntimeException('cURL error: ' . curl_error($ch));
}
$code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers_raw = substr($resp, 0, $header_size);
$raw = substr($resp, $header_size);
curl_close($ch);
$hdrs = $this->parse_headers($headers_raw);
}
if ($code < 200 || $code >= 300) {
throw new \RuntimeException("HTTP $code: $raw");
}
$data = json_decode($raw, true);
if (!is_array($data) && !is_null($data)) {
throw new \RuntimeException('Invalid JSON response');
}
if ($this->cache_ttl > 0 && function_exists('set_transient')) {
set_transient($ckey, ['body' => $data, 'headers' => $hdrs], $this->cache_ttl);
}
return $with_headers ? [$data, $hdrs] : $data;
}
protected function parse_headers(string $raw) : array {
$headers = [];
foreach (explode("\r\n", $raw) as $line) {
if (strpos($line, ':') !== false) {
[$k, $v] = explode(':', $line, 2);
$k = strtolower(trim($k));
$v = trim($v);
$headers[$k][] = $v;
}
}
return $headers;
}
}
2) Usage Examples
A) In a theme template (list monographs)
require_once get_stylesheet_directory() . '/inc/class-artemis-herbs-client.php';
$api = new Artemis_Herbs_Client([
'cache_ttl' => 900, // 15 minutes
]);
$rows = $api->list_monographs([
'per_page' => 20,
'_fields' => ['id','slug','title','link'],
'orderby' => 'title',
'order' => 'asc',
]);
echo '<ul class="herb-list">';
foreach ($rows as $r) {
printf('<li><a href="%s">%s</a></li>',
esc_url($r['link']),
esc_html($r['title']['rendered'] ?? $r['slug'])
);
}
echo '</ul>';
B) Filter by multiple taxonomy terms (arrays supported)
$rows = $api->list_monographs([
'artm_system' => 'nervous',
'artm_action' => ['nervine','anxiolytic','adaptogen'],
'_fields' => ['id','slug','title','link'],
]);
C) Iterate all pages (generator)
echo '<ul>';
foreach ($api->iterate_monographs([
'_fields' => ['id','slug','title','link'],
'orderby' => 'title',
'order' => 'asc',
]) as $row) {
echo '<li>' . esc_html($row['title']['rendered']) . '</li>';
}
echo '</ul>';
D) Get one monograph with embedded terms
$item = $api->get_monograph(1234, ['_embed' => 1]);
// Access taxonomy terms under $item['_embedded']['wp:term']
E) List terms of a taxonomy (e.g., artm_action)
$terms = $api->list_terms('artm_action', [
'per_page' => 100,
'orderby' => 'name',
'order' => 'asc',
]);
// $terms[] => [ id, name, slug, count, ... ]
3) Quick Shortcode (optional)
Drop this into a plugin or theme to expose a simple list via shortcode:
add_shortcode('artemis_herbs', function($atts){
$a = shortcode_atts([
'system' => '', // e.g. digestive
'action' => '', // e.g. carminative (comma-separated allowed)
'limit' => 20,
], $atts);
require_once __DIR__ . '/class-artemis-herbs-client.php';
$api = new Artemis_Herbs_Client(['cache_ttl' => 600]);
$args = [
'per_page' => (int)$a['limit'],
'_fields' => ['id','slug','title','link'],
'orderby' => 'title',
'order' => 'asc',
];
if ($a['system']) $args['artm_system'] = trim($a['system']);
if ($a['action']) $args['artm_action'] = array_map('trim', explode(',', $a['action']));
try {
$rows = $api->list_monographs($args);
} catch (\Throwable $e) {
return '<p>Error: ' . esc_html($e->getMessage()) . '</p>';
}
if (!$rows) return '<p>No results.</p>';
$out = '<ul class="artemis-herbs">';
foreach ($rows as $r) {
$out .= sprintf('<li><a href="%s">%s</a></li>',
esc_url($r['link']),
esc_html($r['title']['rendered'] ?? $r['slug'])
);
}
$out .= '</ul>';
return $out;
});
Usage:
[artemis_herbs system="digestive" action="carminative,nervine" limit="30"]
4) Notes & Tips
- Taxonomy filters: Use either slugs (
artm_action=carminative) or arrays (artm_action[]=carminative&artm_action[]=nervine). The client builds both viahttp_build_query. - Fields: Use
_fieldsto keep payloads small. For full monographs, omit_fieldsor pass what you need. - Embedding: Add
['_embed' => 1]when you need related resources (terms/media) inline. - Caching: Inside WordPress, the client uses transients. Adjust
cache_ttlor set to0to disable.
