workofstan/mycms

MyCMS - 一个用于交互式网站(包括通用管理)的MVC框架。

v0.4.10 2024-08-03 21:45 UTC

README

Total Downloads Latest Stable Version Lint Code Base PHP Composer + PHPUnit + PHPStan

MyCMS是一个用于交互式网站(包括通用管理)的MVC框架。此框架允许您通过简单的配置创建应用程序,并通过composer保持框架的更新,同时尽可能多地使用纯PHP。它作为一个开发栈,您先安装它,然后编写您项目特定的类。样板项目在dist文件夹中准备好,可根据需要进行调整,并使用此WorkOfStan\MyCMS库。

MyCMS设计用于与以下技术一起使用

安装

期望Apache模块mod_alias(用于隐藏非公开文件)和mod_rewrite(用于友好URL功能)。

一旦安装了composer,请在项目根目录中执行以下命令以安装此库

composer require workofstan/mycms:^0.4.10

大多数库的类使用前缀My。为了开发您的项目,请在./classes/目录中创建自己的类,作为MyCMS类的子类,并不要在名称中使用初始的My

$MyCMS = new \WorkOfStan\MyCMS\MyCMS(
    [
        // compulsory
        'logger' => $logger, // object \Psr\Log\LoggerInterface
        //optional
    ]
);

//Finish with Latte initialization & Mark-up output
$MyCMS->renderLatte(DIR_TEMPLATE_CACHE, "\\vendor\\ProjectName\\Latte\\CustomFilters::common", $params);

文件process.phpadmin-process.php必须存在,因为它们处理表单。

注意:$MyCMS名称被ProjectSpecific extends ProjectCommon类期望(@todo用参数处理替换全局$MyCMS)

部署

/dist

文件夹/dist包含使用MyCMS的新项目的初始分发文件,因此将其复制到您的新项目文件夹中,以便轻松开始。将字符串MYCMSPROJECTNAMESPACE替换为您项目的命名空间。(TODO:rector...)将字符串MYCMSPROJECTSPECIFIC替换为其他网站特定信息(品牌、Twitter地址、电话号码、phinx.yml中的数据库表前缀等)。如果您想使用自己的表名前缀,请在首次运行./build.sh之前更改与数据库相关的字符串。

要调整内容和结构,请在首次运行构建之前调整迁移content_tablecontent_example,或者构建后调整数据库内容,或者运行构建,看看它如何工作,然后调整迁移、删除表并再次运行构建。

包含用户和散列密码的表命名为TAB_PREFIX . 'admin'

建议根据注释中的建议,将 Contoller.php、FriendlyUrl.php 和 ProjectSpecific.php 类适配到您的需求。关于部署,请查看 dist/README.md 中的《部署》章节和《语言管理》章节。

MyCMS 仅作为库使用,因此使用它的项目应该实现 RedirectMatch 404 vendor\/ 语句,如 dist/.htaccess 中准备的那样,以将库隐藏于网络访问之外。

管理员界面

管理员界面由 MyAdmin::outputAdmin 在以下结构中显示

元素概览

导航

  • 特殊 Admin::outputSpecialMenuLinks
  • 默认:媒体+用户+设置 MyAdmin::outputNavigation

搜索

  • 管理员类变量 $searchColumns 定义了一个数组,格式为数据库表 => [id,要搜索的字段列表],例如:
    protected $searchColumns = [
        'product' => ['id', 'name_#', 'content_#'], // "#" will be replaced by current language
    ];

议程

  • MyAdmin::outputAgendas
  • 在 admin.php 的 $AGENDAS 中定义

主要

  • 消息
  • 工作区:以下之一
    • $_GET['search'] => MyAdmin::outputSearchResults
    • $_GET['table'] => MyAdmin::outputTable -- $_GET['where'] 是数组 => Admin::outputTableBeforeEdit . MyAdmin::tableAdmin->outputForm . Admin::outputTableAfterEdit -- $_POST['edit-selected'] => MyAdmin::outputTableEditSelected(false) -- $_POST['clone-selected'] => MyAdmin::outputTableEditSelected(true) -- 否则 => Admin::outputTableBeforeListing . MyAdmin::tableAdmin->view . Admin::outputTableAfterListing
    • $_GET['media'] => MyAdmin::outputMedia 媒体上传等。
    • $_GET['user'] => MyAdmin::outputUser 用户操作(注销,更改密码,创建用户,删除用户)
    • Admin::projectSpecificSectionsCondition => Admin::projectSpecificSection 特定管理员部分
  • 仪表板:表单列表 MyAdmin::outputDashboard

管理员备注

数据库

管理员界面中显示的表列可以使用注释中设置的多种功能

TODO:active=0/1 显示为开关按钮

TODO:更好的解释。

clientSideResources

class/Admin.php 中,您可以重新定义 clientSideResources 变量,以加载到管理员中的资源。其默认值是

    protected $clientSideResources = [
        'js' => [
            'scripts/jquery.js',
            'scripts/popper.js',
            'scripts/bootstrap.js',
            'scripts/admin.js?v=' . PAGE_RESOURCE_VERSION,
        ],
        'css-pre-admin' => [
            'styles/bootstrap.css',
        ],
        'css' => [
            'styles/font-awesome.css',
            'styles/ie10-viewport-bug-workaround.css',
            'styles/bootstrap-datetimepicker.css',
            'styles/summernote.css',
            'styles/admin.css?v=' . PAGE_RESOURCE_VERSION,
        ]
    ];

admin.css 可继承到子项目中,然而,由于供应商文件夹应该被浏览器拒绝访问,因此该标准 admin.css 的内容必须通过方法 MyAdmin::getAdminCss 获取。

测试

从命令行运行

./vendor/bin/phpunit

注意,dist 文件夹包含基于 MyCMS 的项目部署和测试运行,因此,为了开发,必须设置 dist 的环境。

注意:从根目录运行 vendor/bin/phpunit 将导致使用根目录的 MyCMS 类,即使是从 mycms/dist/Test 中。而从 dist 运行 vendor/bin/phpunit 将导致使用 dist/vendor/workofstan/mycms/classes 中的 MyCMS 类。

GitHub Actions 的 PHPUnit 版本使用配置文件 phpunit-github-actions.xml,该文件忽略了 Distribution Test Suite,因为 MySQLi 环境尚未准备好,并且 CLI 环境中无法工作。

重用工作流

由于 dist/.github/workflows 通过 workflow_call 重用了某些 .github/workflows,因此,绝对不能在那里引入任何破坏性更改。重用的工作流可以通过分支、标签或提交引用,并且不支持 语义版本控制

    # Working examples
    uses: WorkOfStan/MyCMS/.github/workflows/phpcbf.yml@main # ok, but all encompassing
    uses: WorkOfStan/MyCMS/.github/workflows/phpcbf.yml@v0.4.10 # it works

    # Failing examples
    uses: WorkOfStan/MyCMS/.github/workflows/phpcbf.yml@v0.4
    uses: WorkOfStan/MyCMS/.github/workflows/phpcbf.yml@^v0.4
    uses: WorkOfStan/MyCMS/.github/workflows/phpcbf.yml@^0.4
    uses: WorkOfStan/MyCMS/.github/workflows/phpcbf.yml@v0    

因此,如果必须引入破坏性更改,请创建另一个用于重用的工作流,而不是更改现有工作流!

PHPStan

由于支持 PHP<7.1,因此 phpstan/phpstan-webmozart-assertrector/rector 不能在 composer.json 中作为 required-dev 依赖项。因此,为了正确考虑 PHPStan(对于 level>6 相关)的 Assert 语句,请执行临时操作(即不将其提交到存储库)

composer require --dev phpstan/phpstan-webmozart-assert --prefer-dist --no-progress
composer require --dev rector/rector --prefer-dist --no-progress

并使用 conf/phpstan.webmozart-assert.neon 允许执行 phpstan --configuration=conf/phpstan.webmozart-assert.neon analyse . --memory-limit 300M

预置脚本 ./phpstan.sh./phpstan-remove.sh 可用于启动(或删除)静态分析。(待办:从根目录调用分发脚本以实现DRY。)

控制器内如何实现友好URL

包括在 dist 文件夹中语言管理的SEO设置详情

new Controller(['requestUri' => $_SERVER['REQUEST_URI']])
│   // request URI is set in multiple places
│   ->requestUri
│   ->projectSpecific->requestUri
│   ->friendlyUrl->requestUri
│   ->friendlyUrl->projectSpecific->requestUri
│   ->result['template'] = TEMPLATE_DEFAULT
│
└───run()
│   └── $controller->MyCMS->template = $this->result['template'];
│   │
│   └───$controller->friendlyUrl
│       └── ->determineTemplate(['REQUEST_URI' => $this->requestUri]) // returns mixed string with name of the template when template determined, array with redir field when redirect, bool when default template SHOULD be used
│            ├── ->friendlyIdentifyRedirect(['REQUEST_URI' => $this->requestUri]) // returns mixed 1) bool (true) or 2) array with redir string field or 3) array with token string field and matches array field (see above)
│            │   ├──if $token === self::PAGE_NOT_FOUND
│            │   │    └──$this->MyCMS->template = self::TEMPLATE_NOT_FOUND
│             <──────── @return true
│                 ├──FORCE_301
│                 │    ├── ->friendlyfyUrl(URL query) // returns string query key of parse_url, e.g  var1=12&var2=b
│                 │    │   └── ->switchParametric(`type`, `value`) // project specific request to database returns mixed null (do not change the output) or string (URL - friendly or parametric)
│                 │    │        └──If something new calculated, then
│             <────────────── @return redirWrapper(URL - friendly or parametric)
│                 │    └── if !isset($matches[1]) && ($this->language != DEFAULT_LANGUAGE) // no language subpatern and the language isn't default
│             <─────────── @return 302 redirWrapper(languageFolder . interestingPath) // interestingPath is part of PATH beyond applicationDir
│                 ├──REDIRECTOR_ENABLED
│                 │    └──if old_url == interestingPath (=part of PATH beyond applicationDir)
│             <─────────── @return redirWrapper(new_path)
│                 └──If there are more (non language) folders, the base of relative URLs would be incorrect, therefore
│             <──────── @return **redirect** either to a base URL with query parameters or to a 404 Page not found
│             <──── @return [token, matches]
│         <──── @return array with redir field when redirect || bool when default template SHOULD be used
│            │
│            ├──[token, matches]
│            ├──loop through $myCmsConf['templateAssignementParametricRules'] and if $this->get[`type`] found:
│         <────── @return template || `TEMPLATE_NOT_FOUND` (if invalid `value`)
│            │
│            └── ->pureFriendlyUrl(['REQUEST_URI' => $this->requestUri], $token, $matches); //FRIENDLY URL & Redirect calculation where $token, $matches are expected from above
│                       ├──default scripts and language directories all result into the default template
│             <─────────── @return self::TEMPLATE_DEFAULT
│         <──── @return self::TEMPLATE_DEFAULT
│                       │
│                       └── ->findFriendlyUrlToken(token) // project specific request to database @return mixed null on empty result, false on database failure or one-dimensional array [id, type] on success
│                            │                              If there is a pure friendly URL, i.e. the token exactly matches a record in content database, decode it internally to type=id
│                            │                              SQL statement searching for $token in url_LL column of table(s) with content pieces addressed by FriendlyURL tokens
│                            │                              Overide the method if the default UNION on tables, where relevant types are stored, isn't sufficient
│                            │   spoof $this->get[$found['type']] = $this->get['id'] = $found['id']
│             <────────────── @return $this->determineTemplate(['REQUEST_URI' => $this->requestUri]) RECURSION
│             <─────────── @return null
│         <──── null => @return self::TEMPLATE_NOT_FOUND
│   <──── redir or continue with calculated $controller->MyCMS->template

待办

待办管理

  • 200314:在 F/classes/Admin::outputSpecialMenuLinks() 和 ::sectionUrls() 中进行 FriendlyURL 管理,将其通用化并启用,如果 FRIENDLY_URL == true
  • 200314:在 Admin.php 中添加相应的 FriendlyURL 编辑部分(根据 F 项目),如果可以通用化
  • 200526:如果使用 Texy(仅在 MyTableAdmin 中可见 ($comment['display'] == 'html' ? ' richtext' : '') . ($comment['display'] == 'texyla' ? ' texyla' : '')),则描述它。否则从 composer.json、Latte\CustomFilters、ProjectCommon、dist\index.php 中删除。

待办治理

  • 190705:在 classes\LogMysqli.php 中进行日志记录 'log/sql' . date("Y-m-d") . '.log.sql'); 到当前调用脚本的目录 - 这对API来说并不有利。如何从 APP_ROOT 中获取?
  • 200526:描述 jQuery 依赖项;以及其他 JS 库(可能在 dist 中?)
  • 200529:现在需要 PHP 7.2 或更高版本:最新 PHPUnit + Phinx https://github.com/cakephp/phinx/releases .. 计划在 0.5.0 版本中发布
  • 200608:将所有 array( 替换为 [
  • 200819:将 FORCE_301、FRIENDLY_URL 和 REDIRECTOR_ENABLED 转换为变量,以便可以对所有场景进行 PHPUnit 测试
  • 200819:考虑 REQUEST_URI 查询与 _GET 的区别 - 是否应该只使用一个真理来源?
  • 200921:对于 PHP/7.1.0+ 版本,在 MyCommon、MyFriendlyUrl、MyAdminProcess.php 中使用 protected 进行 const

待办 UI

  • 220716:Admin Translations 和 Urls 模块应通过核心显示标签页(而不是应用程序)
  • 230309:‘使用门户规则’:‘条款和条件’,‘使用门户规则’:‘Terms & Bedingungen’不应显示为 & - 要么在 inc-footer.latte 中没有 noescape 过滤器,要么更改 L10n::translate return Tools::h($text);

待办 安全性

  • 190723:如果同一域名下有两个不同的 MyCMS 实例,那么即使用户不存在,通过登录到 admin.php 也会登录到所有实例
  • 220513,Latte::2.11.3 警告:Engine::addFilter(null, ...) 已弃用,从 ^2.10.8 开始使用 addFilterLoader(),它需要 php: >=7.1 <8.2(停止限制 "latte/latte": ">=2.4.6 <2.11.3")