MetCPT WP self-updates
MetCPT is a corporate content hub plugin for WordPress that manages Events, Tenders, and Careers with structured listings and elegant single-page templates. Built for enterprise and institutional websites, originally developed for IIUM Holdings.
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/ismetdev/metcpt/archive/refs/heads/main.zipShips its own WordPress updater (Plugin Update Checker), so new versions show up under Dashboard → Updates.
MetCPT — Corporate Content Hub for WordPress
A WordPress plugin built for IIUM Holdings Sdn Bhd to manage corporate events, procurement tenders, career vacancies, and news content across multiple subsidiary companies — with structured admin entry, styled public listings, and full single-page templates.
Table of Contents
- Overview
- Features
- Requirements
- Installation
- Updates
- Configuration
- Shortcodes
- Recommended Page Setup
- Archive Display
- Server Cron Setup
- File Structure
- Custom Post Types
- Data & Storage
- Security
- Performance
- Changelog
- Support
- License
Overview
MetCPT registers four custom post types (Events, Tenders, Careers, Companies) and exposes a set of shortcodes that render structured, styled listings on ordinary WordPress pages. It is designed to sit alongside a page builder such as Elementor: listings are placed on pages via shortcodes, while the plugin owns the single-post templates for each content type.
Features
Events
- Custom post type with an 8-section meta box (schedule, VIPs, itinerary, attendance, FAQs, guidelines, call-to-action, contact)
- Automatic status detection (Upcoming / Today / Past)
- VIP attendee list with configurable role badges
- Itinerary builder (time / activity / person-in-charge)
- Single event page with Google Calendar integration and WhatsApp sharing
[events_list]shortcode with month dividers and filtering
Tenders
- Custom post type for procurement opportunities
- Two display templates — A (searchable table) and B (editorial layout), switchable globally or per-shortcode
- Automatic status calculation (Open / Closing Soon / Closed) from the closing date
- Daily email notifications for tenders nearing their closing date, with de-duplication
[tenders_list]and[tenders_preview]shortcodes
Careers
- Custom post type for job vacancies
- Relational company system via the
metcpt_companyCPT - Controlled Department dropdown (managed in Settings) and fixed Job Type options
- Application tracking with closing dates; "Apply" hidden automatically once closed
[careers_list]and[careers_preview]shortcodes
News Grid
- Editorial news layout for standard WordPress posts
- Uniform responsive grid (
repeat(3, 1fr), minimum 6 cards) - Optional category filtering
[news_grid]and[category_posts]shortcodes
Admin
- Settings page — tabbed configuration for General, Events, Tenders, Careers, Posts, plus an Error Log and How-To reference
- Dashboard widget — content-health overview (counts, closing-soon alerts, missing-field detection), transient-cached for 5 minutes
- Error Log — captures PHP errors, warnings, notices, uncaught exceptions, and fatals originating from MetCPT's own files, stored in a dedicated table with a filterable UI, detail modal, per-entry resolve, and 30-day auto-purge of resolved entries
- Dummy data tools — one-click seed/clear of sample content for local testing (behind a toggle; idempotent seeding)
Requirements
| Minimum | |
|---|---|
| WordPress | 6.0 |
| PHP | 7.4 |
| MySQL | 5.7 |
Installation
Via WordPress admin (recommended)
- Download
metcpt.zipfrom the latest release. - Go to Plugins → Add New → Upload Plugin, choose the zip, and click Install Now.
- Click Activate.
Manual
- Extract
metcpt.zipinto/wp-content/plugins/metcpt/. - Activate MetCPT from the Plugins screen.
After activating, go to Settings → Permalinks and click Save Changes once to flush rewrite rules.
Updates
MetCPT self-updates from its GitHub releases via the bundled Plugin Update Checker. When a new version is released, WordPress shows an update on the Plugins / Dashboard → Updates screen; an administrator clicks Update to install it. Updates are always deliberate and admin-initiated — there is no silent or push-based deployment.
Configuration
Open MetCPT Settings and configure, at minimum:
- Tenders → Page URL and Careers → Page URL — used by the "Back" buttons on single pages and the "View all" links in previews
- Events → Archive URL — used by the "Back to Events" button
- Tenders → Notification Recipient and Closing Soon Threshold (days)
- Tenders → Categories and Careers → Departments — the dropdown options shown when editing content
- Posts → News Grid — header label, headline, view-all link, and default category
Then create your first Company, and start adding Events, Tenders, and Careers.
Shortcodes
Events
[events_list]
[events_list filter="upcoming"]
[events_list filter="past" order="DESC"]
[events_list posts_per_page="5" show_excerpt="no"]
| Attribute | Values | Default |
|---|---|---|
filter |
all / upcoming / past | all |
category |
category slug | — |
posts_per_page |
integer (-1 = all) |
-1 |
order |
ASC / DESC | ASC |
show_excerpt |
yes / no | yes |
show_date |
yes / no | yes |
Tenders
[tenders_list]
[tenders_list template="a"]
[tenders_preview]
[tenders_preview template="b" posts_per_page="6"]
template="a" (table) or template="b" (editorial) overrides the global Active Template setting for that shortcode. Specify it explicitly on any page where the layout matters.
| Attribute | Values | Default |
|---|---|---|
template |
a / b | global setting |
posts_per_page |
integer | 5 (preview) |
view_all_url |
URL | Tenders Page URL |
Careers
[careers_list]
[careers_list filter="open"]
[careers_list company="iium-holdings" department="ICT" type="Full Time"]
[careers_preview posts_per_page="3"]
| Attribute | Values | Default |
|---|---|---|
filter |
all / open / closed | all |
company |
company post slug | — |
department |
exact department name | — |
type |
Full Time / Part Time / Contract / Internship | — |
posts_per_page |
integer (-1 = all) |
-1 |
order |
ASC / DESC | ASC |
view_all_url |
URL | Careers Page URL |
News
[news_grid]
[news_grid category="csr"]
[news_grid label="Our Stories" headline="Latest from" headline_italic="the group."]
[category_posts category_slug="news" posts_per_page="5"]
[news_grid] attributes fall back to the Posts settings tab when omitted (label, headline, headline_italic, view_all_text, view_all_url, category, posts_per_page, show_excerpt, order, orderby). [category_posts] requires category_slug and accepts posts_per_page, order, orderby, show_excerpt, and show_date.
Recommended Page Setup
| Page | Shortcode |
|---|---|
| Homepage | [news_grid], [tenders_preview], [careers_preview] |
| Events | [events_list filter="upcoming"] |
| Tenders | [tenders_list template="a"] |
| Careers | [careers_list filter="open"] |
| Company-specific Careers | [careers_list company="company-slug"] |
| CSR / News | [category_posts category_slug="csr"] |
Archive Display
Listings are served by WordPress pages containing shortcodes, not by CPT archives. Create a page for each module (slugs events, tenders, careers) holding the relevant list shortcode. These pages use the theme's page template — keeping header, footer, and navigation — and avoid conflicts with page builders that intercept CPT template loading. The archive-URL settings point the single-page "Back" buttons at these pages.
Each module also ships a template-archive.php fallback that styles a raw CPT archive URL (e.g. ?post_type=metcpt_event) if one is reached directly. These are an active fallback, not dead code.
Server Cron Setup (Recommended)
WordPress wp_cron runs on page traffic, which can delay tender notifications. For reliable timing:
- Disable the pseudo-cron in
wp-config.php:define( 'DISABLE_WP_CRON', true ); - Add a real daily cron job (e.g. 8:00 AM):
wget -q -O /dev/null "https://yoursite.com/wp-cron.php?doing_wp_cron"
File Structure
metcpt/
├── metcpt.php # Plugin entry point + auto-updater bootstrap
├── uninstall.php # Cleanup on deletion (preserve-by-default)
├── readme.txt # WordPress-format readme
├── LICENSE # GPL-2.0-or-later
├── libs/plugin-update-checker/ # GitHub release update library (YahnisElsts)
├── includes/
│ ├── core/
│ │ ├── class-metcpt.php # Main loader class
│ │ ├── post-types.php # CPT registration
│ │ ├── helpers.php # Shared standalone helpers
│ │ └── migrate-from-haraka.php # One-time Haraka → MetCPT data migration
│ ├── admin/
│ │ ├── settings-page.php # Settings UI + registration
│ │ ├── settings-fields.php # Field renderers
│ │ ├── cron.php # Daily tender-closing email task
│ │ ├── dashboard-widget.php # Admin content-health widget
│ │ ├── error-log.php # Error capture, DB, AJAX, purge cron
│ │ ├── error-log-page.php # Error Log tab UI
│ │ ├── docs-page.php # How-To tab UI
│ │ └── dummy-data.php # Seed / clear sample content
│ ├── events/ (meta-boxes, shortcode-list, templates.php — registers templates/events/*)
│ ├── tenders/ (meta-boxes, shortcode-list, shortcode-preview, shortcode-template-b, templates.php — registers templates/tenders/*)
│ ├── careers/ (meta-boxes-company, meta-boxes-career, shortcode-list, shortcode-preview, templates.php — registers templates/careers/*)
│ └── posts/ (shortcode-general, shortcode-news-grid)
├── templates/ # Single and archive-fallback markup per module
│ ├── events/ (single.php, archive.php)
│ ├── tenders/ (single.php, archive.php)
│ └── careers/ (single.php, archive.php)
└── assets/css/ # Per-module CSS (tokens, general, events, tenders, careers, posts, admin, settings, docs)
Custom Post Types
| CPT | Slug | Purpose |
|---|---|---|
| Events | metcpt_event |
Corporate events |
| Tenders | metcpt_tender |
Procurement opportunities |
| Careers | metcpt_career |
Job vacancies |
| Companies | metcpt_company |
Subsidiary company profiles |
Data & Storage
MetCPT stores content in native WordPress tables (wp_posts, wp_postmeta, wp_options) and creates one custom table, wp_metcpt_error_log, for the error-logging feature. On deletion the plugin preserves all data by default; a full-cleanup block in uninstall.php can be enabled to remove posts, meta, options, and the log table.
Security
- Nonce verification on every meta-box save and AJAX action
- Capability checks (
edit_postfor content,manage_optionsfor admin actions) - Input sanitized on save (
sanitize_text_field,sanitize_textarea_field,esc_url_raw,absint) - Output escaped (
esc_html,esc_attr,esc_url,esc_textarea,wp_kses_post) - All database access parameterized via
$wpdb->prepare()
Performance
- Dashboard widget cached via transient (5-minute expiry), invalidated on post save/delete
- Asset cache-busting keyed to file modification time
- Lean shortcode queries with optional category narrowing
Changelog
1.2.1 (2026-07-10)
- Rewrite rules now flush automatically once after each plugin update (version-gated, on
admin_init), so the manual Settings → Permalinks → Save step is no longer needed following an update. Fresh installs already flushed on activation.
1.2.0 (2026-07-10)
- Removed six settings that were registered and rendered but never read: accent colour, organisation name, events default order, events show-excerpt, default submission address, and default tender fee.
- Removed the redundant News-Grid live preview from the Posts settings tab (the same preview remains in the How-To tab).
- Fixed an undefined-array-key warning in the manual cron trigger's nonce check.
- Made the dummy-data seeder idempotent — it now refuses to seed on top of existing dummy content instead of stacking duplicates.
- Completed and corrected the
uninstall.phpoption-cleanup list (fixed two mismatched option names and added all currently registered options).
1.1.0 (2026-07-10)
- Rebranded from "Haraka" to "MetCPT" with a one-time automatic data migration for post types, options, post meta, the error-log table, and scheduled cron hooks.
- Switched updates to public-repo GitHub releases (no authentication token required).
- Redesigned the settings page and refreshed the newsroom and tenders-preview layouts onto shared design tokens.
1.0.0 (2026-06-14)
- Initial production release: Events, Tenders, and Careers modules;
[news_grid]; dashboard widget; closing-tender email notifications; styled archive fallbacks; safe uninstall handler.
Support
- Internal: IIUM Holdings Web Development Team
- Issues: github.com/ismetdev/metcpt/issues
License
Proprietary — for internal use by IIUM Holdings Sdn Bhd and its subsidiaries.
Developed for IIUM Holdings Sdn Bhd · v1.2.1 · July 2026