Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: CI

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

jobs:
test:
name: PHP ${{ matrix.php }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: ['8.2', '8.3', '8.4', '8.5']
env:
ICMS_CORE_PATH: ${{ github.workspace }}/core/htdocs
steps:
- name: Checkout module
uses: actions/checkout@v4

- name: Checkout ImpressCMS core (signatures for PHPStan)
uses: actions/checkout@v4
with:
repository: fiammybe/impresscms
ref: main
path: core

- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
tools: composer:v2

- name: Install dev dependencies
run: composer install --no-interaction --no-progress --prefer-dist

- name: Lint
run: composer lint

- name: Static analysis
run: composer analyse -- --no-progress --memory-limit=1G

- name: Unit tests
run: composer test
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/vendor/
/composer.lock
/.phpunit.cache/
/.phpunit.result.cache
/.phpstan/
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Changelog

## 1.0.0 Alpha (unreleased)

- Phase 0: module skeleton for ImpressCMS 2.0 in IPF mode, install and update routines, English and Dutch language files, CI on PHP 8.2 to 8.5.
39 changes: 38 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,39 @@
# imforum
ImpressCMS forum based on IPF

Community forum module for ImpressCMS 2.0, built on the ImpressCMS Persistable Framework (IPF). imforum is the successor of iForum: same features, new code, and an importer that takes over the data of a running iForum installation.

Status: phase 0 (foundation). The module installs and updates, but has no forum functions yet.

## Requirements

- ImpressCMS 2.0
- PHP 8.2 to 8.5
- MySQL 5.5.3 or newer (utf8mb4); any storage engine, imforum does not rely on transactions or foreign keys

## Installation

Copy `src/` to `modules/imforum` in your ImpressCMS installation and install the module from System → Modules. The directory must be called `imforum`: IPF derives the table and class names from it, so the module cannot be cloned under another name.

## Development

```sh
composer install
composer lint # php -l on every file
composer test # PHPUnit
ICMS_CORE_PATH=/path/to/impresscms/htdocs composer analyse # PHPStan, needs a core checkout
```

PHPStan reads the core classes from `ICMS_CORE_PATH`. Without that variable it stops with an error about a missing scan directory.

For a local test site, copy `src/` to `modules/imforum`. A symlink or Windows junction does not work: PHP resolves `__DIR__` to the real folder, and the module takes its name from that folder.

Conventions:

- Classes are named `mod_imforum_<Item>` and `mod_imforum_<Item>Handler` and live in `src/class/<Item>.php` and `src/class/<Item>Handler.php`; the core autoloads them once `object_items` is set.
- Form labels come from `_CO_IMFORUM_<ITEM>_<FIELD>` in `language/*/common.php`.
- English and Dutch ship with the module; other languages go through Crowdin.
- Never rename or remove an object var in one release. The core drops columns that are no longer declared before the upgrade functions run, so add the new var and copy the data first, and remove the old var one release later.

## License

MIT, see [LICENSE](LICENSE).
26 changes: 26 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "iforummodule/imforum",
"description": "Community forum module for ImpressCMS 2.0, built on the ImpressCMS Persistable Framework",
"type": "project",
"license": "MIT",
"require": {
"php": ">=8.2"
},
"require-dev": {
"phpunit/phpunit": "^11.5",
"phpstan/phpstan": "^2.1"
},
"autoload-dev": {
"psr-4": {
"Imforum\\Tests\\": "tests/"
}
},
"scripts": {
"lint": "find src tests -name '*.php' -print0 | xargs -0 -n1 php -l",
"analyse": "phpstan analyse",
"test": "phpunit"
},
"config": {
"sort-packages": true
}
}
15 changes: 15 additions & 0 deletions crowdin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
files:
- source: /src/language/english/*.php
translation: /src/language/%two_letters_code%/%original_file_name%
languages_mapping:
two_letters_code:
nl: nederlands
fr: francais
it: italiano
de: german
es: spanish
pt-BR: portuguesebr
ru: russian
fa: persian
ja: ja_utf8
zh-CN: schinese
16 changes: 16 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
parameters:
level: 6
paths:
- src
excludePaths:
- src/language/*
bootstrapFiles:
- tests/phpstan-bootstrap.php
# The ImpressCMS core is checked out next to the module in CI (see .github/workflows/ci.yml)
# and only scanned for class and function signatures, never analysed.
scanDirectories:
- %env.ICMS_CORE_PATH%/libraries/icms
scanFiles:
- %env.ICMS_CORE_PATH%/include/functions.php
- %env.ICMS_CORE_PATH%/include/cp_functions.php
- %env.ICMS_CORE_PATH%/libraries/icms.php
19 changes: 19 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="tests/bootstrap.php"
colors="true"
failOnWarning="true"
failOnDeprecation="true"
failOnNotice="true">
<testsuites>
<testsuite name="unit">
<directory>tests/Unit</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory>src</directory>
</include>
</source>
</phpunit>
23 changes: 23 additions & 0 deletions src/admin/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php
/**
* Administration index
*
* @copyright The iForum project
* @license MIT, see LICENSE
* @package imforum
* @since 1.0
*/

include_once dirname(__DIR__, 3) . '/include/cp_header.php';
include_once dirname(__DIR__) . '/include/common.php';

icms_cp_header();
/** icms_cp_header() creates the admin template engine as a global */
global $icmsAdminTpl;
icms::$module->displayAdminMenu(0, _AM_IMFORUM_INDEX);

$icmsAdminTpl->assign('imforum_version', icms::$module->getVar('version'));
$icmsAdminTpl->assign('imforum_dbversion', icms::$module->getDBVersion());
$icmsAdminTpl->display('db:imforum_admin_index.html');

icms_cp_footer();
27 changes: 27 additions & 0 deletions src/admin/menu.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php
/**
* Administration menu
*
* @copyright The iForum project
* @license MIT, see LICENSE
* @package imforum
* @since 1.0
*/

defined('ICMS_ROOT_PATH') || die('ImpressCMS root path not defined');

$adminmenu = [];
$adminmenu[] = [
'title' => _MI_IMFORUM_MENU_INDEX,
'link' => 'admin/index.php',
'icon' => 'images/imforum_iconbig.png',
'small' => 'images/imforum_iconsmall.png',
];

// icms_module_Object::displayAdminMenu() counts the header menu without an
// isset check, so it must always be an array.
$headermenu = [];
$headermenu[] = [
'title' => _MI_IMFORUM_NAME,
'link' => ICMS_URL . '/modules/' . basename(dirname(__DIR__)) . '/',
];
1 change: 1 addition & 0 deletions src/assets/css/imforum.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* Forum-specific additions on top of the ImpressCMS 2.0 default theme. */
1 change: 1 addition & 0 deletions src/assets/css/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<script>history.go(-1);</script>
1 change: 1 addition & 0 deletions src/assets/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<script>history.go(-1);</script>
1 change: 1 addition & 0 deletions src/assets/js/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<script>history.go(-1);</script>
1 change: 1 addition & 0 deletions src/blocks/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<script>history.go(-1);</script>
1 change: 1 addition & 0 deletions src/class/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<script>history.go(-1);</script>
67 changes: 67 additions & 0 deletions src/icms_version.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
/**
* imforum module definition
*
* imforum is the IPF-based successor of iForum. As soon as `object_items` is an
* array, the core flags the module as IPF (ipf = 1), registers class/ under the
* namespace mod_imforum and builds the tables from the object definitions.
*
* @copyright The iForum project
* @license MIT, see LICENSE
* @package imforum
* @since 1.0
*/

defined('ICMS_ROOT_PATH') || die('ImpressCMS root path not defined');

include_once __DIR__ . '/include/common.php';

$modversion = [
'name' => _MI_IMFORUM_NAME,
'version' => '1.0.0',
'status' => 'Alpha',
'status_version' => '1.0.0 Alpha',
'date' => '25 October 2026',
'description' => _MI_IMFORUM_DESC,
'author' => 'fiammybe',
'author_realname' => 'David Janssens',
'credits' => 'Based on the ideas of iForum, CBB and newbb',
'license' => 'MIT, see LICENSE',
'official' => false,
'dirname' => basename(__DIR__),
'modname' => IMFORUM_DIRNAME,

'iconsmall' => 'images/imforum_iconsmall.png',
'iconbig' => 'images/imforum_iconbig.png',
'image' => 'images/imforum_icon.png',

'support_site_url' => 'https://github.com/iForumModule/imforum',
'support_site_name' => 'imforum on GitHub',
'submit_bug' => 'https://github.com/iForumModule/imforum/issues',
'submit_feature' => 'https://github.com/iForumModule/imforum/issues',

// IPF objects, filled in phase 1. An empty array already enables IPF mode
// (autoloading), but the core only runs the table sync and the
// imforum_db_upgrade_<n>() steps once the array is not empty.
'object_items' => [],

'onInstall' => 'include/onupdate.php',
'onUpdate' => 'include/onupdate.php',

'hasAdmin' => 1,
'adminindex' => 'admin/index.php',
'adminmenu' => 'admin/menu.php',

'hasMain' => 1,
'hasSearch' => 0,
'hasComments' => 0,
'hasNotification' => 0,

'templates' => [
['file' => 'imforum_index.html', 'description' => 'Forum index'],
['file' => 'imforum_admin_index.html', 'description' => 'Administration index'],
],

'blocks' => [],
'config' => [],
];
Binary file added src/images/imforum_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/imforum_iconbig.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/images/imforum_iconsmall.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/images/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<script>history.go(-1);</script>
26 changes: 26 additions & 0 deletions src/include/common.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php
/**
* Constants shared by every imforum entry point
*
* The core reads IMFORUM_DB_VERSION through constant() without a defined()
* check (icms_db_legacy_updater_Handler::moduleUpgrade), so this file must be
* loaded before every install or update.
*
* @copyright The iForum project
* @license MIT, see LICENSE
* @package imforum
* @since 1.0
*/

defined('ICMS_ROOT_PATH') || die('ImpressCMS root path not defined');

if (!defined('IMFORUM_DIRNAME')) {
/** The directory and module name; IPF derives table and class names from it */
define('IMFORUM_DIRNAME', basename(dirname(__DIR__)));
define('IMFORUM_ROOT_PATH', ICMS_ROOT_PATH . '/modules/' . IMFORUM_DIRNAME . '/');
define('IMFORUM_URL', ICMS_URL . '/modules/' . IMFORUM_DIRNAME . '/');
define('IMFORUM_UPLOAD_PATH', ICMS_UPLOAD_PATH . '/' . IMFORUM_DIRNAME . '/');

/** Raise by one for every release that needs an imforum_db_upgrade_<n>() step */
define('IMFORUM_DB_VERSION', 1);
}
1 change: 1 addition & 0 deletions src/include/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<script>history.go(-1);</script>
Loading
Loading