Skip to content

Commit

Permalink
Merge pull request #25 from wp-blocks/v0.0.4
Browse files Browse the repository at this point in the history
V0.0.4
  • Loading branch information
erikyo committed Dec 11, 2023
2 parents 2b76108 + 0999c8a commit 9e32c7e
Show file tree
Hide file tree
Showing 34 changed files with 3,043 additions and 880 deletions.
17 changes: 0 additions & 17 deletions .eslintrc.js

This file was deleted.

19 changes: 19 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"env": {
"browser": true,
"node": true,
"es2021": true,
"jest": true
},
"extends": "eslint:recommended",
"overrides": [
],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"rules": {
"semi": ["error", "always"],
"max-len": ["error", { "code": 200 }]
}
}
5 changes: 5 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npm run lint
npm test
127 changes: 127 additions & 0 deletions lib/Database.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
const mysql = require('mysql2/promise');
const mysqldump = require('mysqldump').default;
const {getConnectionSettings} = require("./utils/data");
const path = require("path");
const fs = require('fs');

/**
* Constructor for the Database class.
*
* @class Database
*/
class Database {
/**
* A description of the entire function.
*
* @param {import('./constants').WPMMconfig} config - The configuration object.
*/
constructor (config) {
// Load configuration from wp-package.json
this.config = config;
}

/**
* Generates a unique filename for the database dump.
*
* @returns {string} - The generated filename.
*/
dbDumpFilename = () => {
const date = new Date().toDateString().replace(" ", "-");
return `${this.config.wordpress.WP_config.DB_NAME}-${date}.sql.gz`;
};

/**
* Uploads a database by executing SQL queries from a specified file.
*
* @async
* @param {string} sqlFilePath - The path to the SQL file.
* @return {Promise<void | Error>} - A Promise that resolves to a MySQL Connection object or throws an Error.
*/
async uploadDatabase (sqlFilePath) {
try {
console.log('Uploading database...');

if (!fs.existsSync(sqlFilePath)) {
return new Error('SQL file not found');
}

if (!this.config) {
return new Error('Database configuration not found');
}

/**
* the connection settings for the database
* @type {mysql.ConnectionOptions} databaseConnectionConfig - The connection settings for the database.
*/
const databaseConnectionConfig = getConnectionSettings(this.config.wordpress.WP_config);

/**
* @type {import('mysql2/promise').Connection} connection - The MySQL connection object.
*/
const connection = await mysql.createConnection(databaseConnectionConfig);

const sqlFileContent = fs.readFileSync(sqlFilePath, 'utf8');
const queries = sqlFileContent.split(';');

for (const query of queries) {
if (query.trim() !== '') {
await connection.query(query);
}
}

console.log('Database uploaded successfully');
connection.end().then(() => {
console.log('👍 Database connection closed');
}).catch(error => {
console.error('🫠 Error closing database connection:', error.message);
});
} catch (/** @type {any} */ error) {
console.error('🔴 Error uploading database:', error.message);
}
}

/**
* Asynchronously dumps the database to the specified output file.
*
* @param {string} basePath - The base path of the WordPress installation.
* @async
* @return {Promise<void | Error>} - A promise that resolves if the database is dumped successfully, or rejects with an error message if an error occurs.
*/
async dumpDatabase (basePath) {
const dumpPath = path.join( basePath, 'backups', 'db');
const dumpFile = path.join( dumpPath, this.dbDumpFilename());

// Check if the directory exists and create it if it doesn't
if (!fs.existsSync(dumpPath)) {
fs.mkdirSync( dumpPath, { recursive: true });
console.log(`ℹ️ Directory created: ${dumpPath}`);
}

console.log(`✳️ Dumping database to ${dumpFile}...`);

if (!this.config.wordpress.WP_config) {
return new Error('🔴 Database configuration not found');
}

/**
* the connection settings for the database
*
* @type {mysqldump.ConnectionOptions} databaseConnectionConfig - The connection settings for the database.
*/
const databaseConnectionConfig = getConnectionSettings(this.config.wordpress.WP_config);

if (databaseConnectionConfig.host === 'localhost') {
console.log('⚠️ Warning: You are using localhost as your database host. This may not work correctly.');
}

mysqldump({
connection: databaseConnectionConfig,
dumpToFile: dumpFile,
compressFile: true
}).catch(error => {
console.error('🔴 Error dumping database:', error.message);
});
}
}

module.exports = Database;
153 changes: 153 additions & 0 deletions lib/Dump.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
const fs = require('fs');
const path = require('path');
const {getCurrentWpInfo} = require("./utils/wordpress.js");
const {getWpConfigContent} = require("./utils/wordpress.js");
const {parseWpConfig} = require("./utils/parsers.js");

/**
* Represents a Dump class for WordPress configuration.
*
* @class Dump
*/
class Dump {
/**
* Constructor for the class.
*
* Initializes the class with the necessary folders for WordPress.
* @param {import("./constants").WPMMpaths} paths - The object containing the paths for the WordPress installation.
*/
constructor (paths) {
this.baseFolder = paths.baseFolder;
this.themeFolder = paths.themeFolder;
this.pluginsFolder = paths.pluginsFolder;
}

/**
* Initializes the function by logging the `baseFolder` and `themeFolder` properties,
* scanning the theme and plugins directories, retrieving the website name from the
* `baseFolder` path, getting the WordPress version from `wp-includes/version.php`,
* determining the language using `Intl.DateTimeFormat().resolvedOptions().locale`,
* and saving the result to a JSON file.
*
* @return {Promise<import('./constants').WPMMconfig|{}>} - The configuration object.
*/
async init() {
const themes = this.scanDirectory(this.themeFolder);
const plugins = this.scanDirectory(this.pluginsFolder);

// the website name
const name = path.basename(this.baseFolder);

console.log(`🔍️ Scanning ${this.baseFolder}`);
/**
* @type {{locale: string|null, version: string|null}}
*/
const wpInfo = getCurrentWpInfo(this.baseFolder);

const wpConfigData = parseWpConfig(
getWpConfigContent(this.baseFolder)
);

const version = wpInfo.version || 'latest';
const language = wpInfo.locale || 'en_US';

const result = {
wordpress: {
name,
version,
language,
WP_config: {
...wpConfigData?.constants,
...wpConfigData?.variables
}
},
themes,
plugins
};

const outputPath = path.join(process.cwd(), 'wp-package.json');

fs.writeFileSync(outputPath, JSON.stringify(result, null, 2));
console.log(`🆗 Wordpress configuration Dump completed. Configuration saved to ${outputPath}`);

return result;
}

/**
* Scans a directory and returns an array of objects containing the name and version of each item found.
*
* @param {string} directory - The path of the directory to scan.
* @return {import('./constants').WPMMconfigPkg[]|null} - An array of objects with the name and version of each item found.
*/
scanDirectory (directory) {
// Check if the directory exists
if (! fs.existsSync(directory)) {
console.log(`⚠️ The directory ${directory} does not exist.`);
return [];
}

const items = fs.readdirSync(directory);
/**
* The array of parsed items
*
* @type {import('./constants').WPMMconfigPkg[]} result
*/
let result= [];

for (const item of items) {
const fullPath = path.join(directory, item);
console.log(`🔍️ Scanning ${fullPath}`);
const isDirectory = fs.statSync(fullPath).isDirectory();

if (isDirectory) {
const stylePath = path.join(fullPath, 'style.css');
const themeFile = path.join(fullPath, `${item}.php`);
const pluginFile = `${item}.php`; // ie: 'hello-dolly.php'

if (fs.existsSync(stylePath)) {
const version = this.extractVersionFromStyleFile(stylePath);
if (version) {
console.log(`ℹ️ Found ${item} version ${version}`);
result.push({ name: item, version });
}
}

if (fs.existsSync(themeFile) || fs.existsSync(pluginFile)) {
const version = this.extractVersionFromPHPFile(themeFile) || this.extractVersionFromPHPFile(pluginFile);
if (version) {
console.log(`ℹ️ Found ${item} version ${version}`);
result.push({ name: item, version });
}
}
}
}

return result.length ? result : null;
}

/**
* Extracts the version number from a style file.
*
* @param {string} filePath - The path to the style file.
* @return {string|null} The version number extracted from the style file, or null if no match was found.
*/
extractVersionFromStyleFile (filePath) {
const content = fs.readFileSync(filePath, 'utf8');
const match = /Version:\s*([\d.]+)/i.exec(content);
return match ? match[1] : null;
}

/**
* Extracts the version number from a PHP file.
*
* @param {string} filePath - The path to the PHP file.
* @return {string|null} The version number extracted from the file, or null if no version is found.
*/
extractVersionFromPHPFile (filePath) {
const content = fs.readFileSync(filePath, 'utf8');
const match = /Version:\s*([\d.]+)/i.exec(content);
return match ? match[1] : null;
}
}

module.exports = Dump;
Loading

0 comments on commit 9e32c7e

Please sign in to comment.