Skip to content

Commit

Permalink
api utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
spelkey-ucd committed May 9, 2023
1 parent 44f3a1d commit 615ef2a
Show file tree
Hide file tree
Showing 11 changed files with 941 additions and 7 deletions.
38 changes: 38 additions & 0 deletions wp-api-etl/cli/ucdlib-wp-find.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Command, Option } from 'commander';
import {JSDOM} from "jsdom";

import Config from "../lib/config.js";
import WpApi from "../lib/wp-api.js";

const program = new Command();

program
.command('post-by-element')
.description('Find posts that contain a specified DOM element')
.argument('<query>', 'Args to pass to QuerySelector')
.option('-t, --type <type...>', 'Post type to search', ['page'])
.action(async (query, options) => {
const foundPosts = [];
const config = new Config();
const api = new WpApi(config);

for (const postType of options.type) {
const posts = await api.getPostsByTypeAll(postType);
for (const post of posts) {
const dom = new JSDOM(post.content.rendered);
const elements = dom.window.document.querySelectorAll(query);
if (elements.length > 0) {
foundPosts.push(post);
}
}
}

console.log(`Found ${foundPosts.length} posts.`);
for (const post of foundPosts) {
console.log(post.link);
}

}
);

program.parse(process.argv);
10 changes: 10 additions & 0 deletions wp-api-etl/cli/ucdlib-wp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#! /usr/bin/env node
import { Command } from 'commander';

const program = new Command();
program
.name('ucdlib-wp-main')
.version('0.0.1')
.command('find', 'Query for posts')

program.parse(process.argv);
14 changes: 14 additions & 0 deletions wp-api-etl/lib/config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import dotenv from "dotenv";
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import { existsSync } from 'fs';

/**
* @class Config
* @description Configuration class for the WP API ETL. Sets defaults and reads from .env file if present.
* @param {String} envPath - Path to the .env file
*/
class Config {
constructor(envPath) {
if (envPath) {
dotenv.config({ path: envPath });
} else {
const __dirname = dirname(fileURLToPath(import.meta.url));
const envFile = join(__dirname, '../.env');
if (existsSync(envFile)) {
dotenv.config({ path: envFile });
}
}
const env = process.env;

Expand Down
27 changes: 27 additions & 0 deletions wp-api-etl/lib/http-cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { fileURLToPath } from 'url';
import path from 'path';
import crypto from 'crypto';

/**
* @class HTTPCache
* @description Simple HTTP cache for the WP API ETL. Stores cached responses in .http-cache directory.
*/
class HTTPCache {

constructor() {
Expand All @@ -15,6 +19,11 @@ class HTTPCache {
this.cache = {};
}

/**
* @description Get a cached response by URL
* @param {String} url - URL to retrieve
* @returns - Cached response or null if not found
*/
get(url) {
url = this.hash(url);
if( this.cache[url] ) {
Expand All @@ -30,20 +39,38 @@ class HTTPCache {
return null;
}

/**
* @description Set a cached response by URL
* @param {String} url - URL to set
* @param {*} response - Response to cache
*/
set(url, response) {
let hash = this.hash(url);
this.cache[hash] = {url, response};
fs.writeFileSync(this.getCacheFile(hash), JSON.stringify(this.cache[hash]));
}

/**
* @description Get the path to a cache file by hash
* @param {String} hash - Hash of the URL
* @returns {String}
*/
getCacheFile(hash) {
return path.join(this.localCacheDir, hash+'.json');
}

/**
* @description Hash a URL
* @param {String} url - URL to hash
* @returns - Hashed URL
*/
hash(url) {
return crypto.createHash('md5').update(url).digest('hex');
}

/**
* @description Clear the whole cache
*/
clearCache(){
fs.rmdirSync(this.localCacheDir, { recursive: true });
fs.mkdirSync(this.localCacheDir);
Expand Down
35 changes: 34 additions & 1 deletion wp-api-etl/lib/wp-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import fetch from "node-fetch";
import Config from "./config.js";
import cache from '../lib/http-cache.js';

/**
* @class WpApi
* @description Wrapper for the WP API
* @param {Config} config - Instantiated config object from wp-api-etl/lib/config.js
*/
class WpApi {
constructor(config) {
if ( config ) {
Expand Down Expand Up @@ -43,6 +48,18 @@ class WpApi {
return type;
}

/**
* @description Retrieve list of posts of a given type
* @param {String} postType - A registered post type - ie 'page', 'exhibit', 'post', etc.
* @param {Object} params - Params object with the following properties:
* - query: Object - URL Query params to pass to the API
* - host: String - Hostname to use for the API (defaults to class config value)
* - apiPath: String - Path of the API (defaults to class config value)
* - useCache: Boolean - Whether to use the cache (defaults to class config value)
* - writeToCache: Boolean - Whether to write to the cache (defaults to class config value)
*
* @returns {Array}
*/
async getPostsByType(postType, params = {}) {
postType = this.getTypeName(postType);
const queryParams = this.toSearchParamsObject(params.query);
Expand All @@ -69,7 +86,6 @@ class WpApi {

const q = queryParams.toString();
let url = `${host}${apiPath}/${postType}${q ? '?' + q : ''}`;
console.log(`Fetching ${url}`);

if ( useCache ){
const cached = cache.get(url);
Expand All @@ -92,6 +108,17 @@ class WpApi {

}

/**
* @description Retrieve all posts of a given type
* @param {String} postType - A registered post type - ie 'page', 'exhibit', 'post', etc.
* @param {Object} params - Params object with the following properties:
* - query: Object - URL Query params to pass to the API
* - host: String - Hostname to use for the API (defaults to class config value)
* - apiPath: String - Path of the API (defaults to class config value)
* - useCache: Boolean - Whether to use the cache (defaults to class config value)
* - writeToCache: Boolean - Whether to write to the cache (defaults to class config value)
* @returns {Array}
*/
async getPostsByTypeAll(postType, params = {}) {
const out = [];
let page = 1;
Expand All @@ -107,8 +134,14 @@ class WpApi {
}
page++;
}
return out;
}

/**
* @description Convert an object to a URLSearchParams object and sort it
* @param {Object} params
* @returns
*/
toSearchParamsObject(params) {
params = new URLSearchParams(params);
params.sort();
Expand Down
32 changes: 27 additions & 5 deletions wp-api-etl/lightbox/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import Config from "../lib/config.js";
import {JSDOM} from "jsdom";
import { dirname, join } from 'path';
import { fileURLToPath, URLSearchParams } from 'url';
import { existsSync, mkdirSync } from 'fs';
import { fileURLToPath } from 'url';
import { existsSync } from 'fs';

import Config from "../lib/config.js";
import WpApi from "../lib/wp-api.js";

class LightBoxImageCheck {
Expand All @@ -21,15 +23,35 @@ class LightBoxImageCheck {
}

async run(){
this.findPostsWithMissingImageIds();
const posts = await this.findPostsWithMissingImageIds();
console.log(posts);
}

async findPostsWithMissingImageIds(postTypes = ['pages', 'exhibit']){
if ( !Array.isArray(postTypes) ) {
postTypes = [postTypes];
}
const out = {};
const p = await this.api.getPostsByTypeAll('exhibits');
for( let postType of postTypes ) {
const posts = await this.api.getPostsByTypeAll(postType);
for( let post of posts ) {
let imgCt = 0;
const dom = new JSDOM(post.content.rendered);
const galleries = dom.window.document.querySelectorAll('.wp-block-gallery');
for( let gallery of galleries ) {
const images = gallery.querySelectorAll('img');
for( let image of images ) {
if ( !image.hasAttribute('data-id') ) {
imgCt++;
}
}
}
if ( imgCt > 0 ) {
out[post.id] = {imgCt, post};
}
}
}
return out;
}
}

Expand Down
2 changes: 2 additions & 0 deletions wp-api-etl/lightbox/readme.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Image Correction for Lightbox Plugin.

The WP Gallery block has functionality that allows a user to bulk set the "link to" property on all image blocks. However, in some cases, [this does not work on our site](https://github.com/UCDavisLibrary/main-wp-website/issues/85#issuecomment-1535287882). The issue seems to be that when the gallery was originally imported, the images were uploaded, but the `data-id` attribute was not set.

Luckily, it only affects 5 exhibits, which will just be manually fixed.
Loading

0 comments on commit 615ef2a

Please sign in to comment.