nextcloud 应用开发
nextcloud app文件夹目录结构
+---appinfo
+---css
+---js
+---l10n
+---lib
| +---AppInfo (必须)
| +---Command
| +---Controller (必须)
| +---Cron
| +---Db
| +---Exceptions
| +---Listeners
| +---Migration
| +---Model
| +---Plugins
| +---Service
| +---Storage
| \---Tools
| +---Db
| +---Exceptions
| +---Traits
+---screenshots
+---vendor
目录结构解析
* appinfo * info.xml 信息说明文件 ``` <?xml version="1.0"?> <info xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd"> <id>ai_test</id> // id <name>AI测试</name> // 名称 <summary>对接AI测试</summary> // 摘要 <description>对接AI测试</description> // 描述 <version>1.0</version> // 版本 <licence>agpl</licence> // 开源许可 <author>Eason</author> // 作者 <namespace>AiTest</namespace> // 代码命名空间 <types> // 类型 <filesystem/> </types> <documentation> // 文档地址 <admin>https://github.com/nextcloud/files_lock/blob/master/README.md</admin> </documentation> <category>tools</category> // 分类 <category>files</category> // 分类 <website>https://github.com/nextcloud/files_lock</website> // web站点 <bugs>https://github.com/nextcloud/files_lock/issues</bugs> // bug提交地址 <repository>https://github.com/nextcloud/files_lock.git</repository> // 代码仓库 <screenshot>https://raw.githubusercontent.com/nextcloud/files_lock/master/screenshots/0.7.0.png</screenshot> // 预览图 <dependencies> <nextcloud min-version="21" max-version="23"/> // 兼容nc的版本 </dependencies> </info> ``` * routes.php 路由文件 ```
declare(strict_types=1); return [ 'routes' => [ ['name' => 'AiTest#doRun', 'url' => '/{ownerId}/{fileId}', 'verb' => 'PUT'], ] ]; ``` * css 样式文件 * js javascript脚本 * main.js ``` /** AI测试 **/ (function() { _.extend(OC.Files.Client, { PROPERTY_AI_TEST: '{' + OC.Files.Client.NS_NEXTCLOUD + '}test', }); var AIPlugin = { /** 文件列表渲染时 **/ attach: function(fileList) { var self = this; /** 增加 webdav属性 **/ var oldGetWebdavProperties = fileList._getWebdavProperties; fileList._getWebdavProperties = function() { var props = oldGetWebdavProperties.apply(this, arguments); props.push(OC.Files.Client.PROPERTY_AI_TEST); return props }; /** 注册右边三个点中的菜单选择 **/ fileList.fileActions.registerAction({ name: 'test', displayName: function(context) { if (context && context.$file) { return "AI测试" } return ''; }, mime: 'all', order: -999, iconClass: 'icon-details', permissions: OC.PERMISSION_UPDATE, actionHandler: function (filename,context) { var fileId = context.$file.data("id"); var fileOwnerId = typeof context.$file.data("shareOwnerId") == 'undefined' ? OC.getCurrentUser().uid : context.$file.data("shareOwnerId"); $.ajax({ method: 'PUT', url: OC.generateUrl('/apps/ai_test/' + fileOwnerId + '/' + fileId) }).done(function(res) { console.log(res); }).fail(function(res) { OCP.Toast.warning(res.responseJSON.message) }); } }) }, }; /** 向全局的插件对象注册该插件 **/ OC.Plugins.register('OCA.Files.FileList', AIPlugin) })(); ``` * l10n 语言文件 * lib * AppInfo * Application.php ```
declare(strict_types=1); namespace OCA\AiTest\AppInfo; use OCA\DAV\Connector\Sabre\Node as SabreNode; use OCA\Files\Event\LoadAdditionalScriptsEvent; use OCA\AiTest\Listeners\LoadAdditionalScripts; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\IServerContainer; use OCP\SabrePluginEvent; use Sabre\DAV\INode; use Sabre\DAV\PropFind; use Throwable; use Closure class Application extends App implements IBootstrap { const APP_ID = 'ai_test'; //向文件 webdav中添加属性的固定格式:{http://nextcloud.org/ns} = nc 在系统中定义好了的 const AI_TEST = '{http://nextcloud.org/ns}test'; /** * @param array $params */ public function __construct(array $params = array()) { parent::__construct(self::APP_ID, $params); } /** * @param IRegistrationContext $context * 注册事件监听 * event OCA\Files\Event\LoadAdditionalScriptsEvent::class 访问 /apps/files*路由 会触发 * handle 事件处理 在此处 将app的css、js等静态文件加载进去 */ public function register(IRegistrationContext $context): void { $context->registerEventListener( LoadAdditionalScriptsEvent::class, LoadAdditionalScripts::class ); } /** * @param IBootContext $context * 在服务启动后,会触发方法 * @throws Throwable */ public function boot(IBootContext $context): void { $context->injectFn(Closure::fromCallable([$this, 'registerHooks'])); } /** * @param IServerContainer $container 服务器容器,可以通过类获取相应的对象 */ public function registerHooks(IServerContainer $container) { $eventDispatcher = \OC::$server->getEventDispatcher(); $eventDispatcher->addListener( 'OCA\DAV\Connector\Sabre::addPlugin', function (SabrePluginEvent $e) { $server = $e->getServer(); //注册文件的webdav属性 $server->on('propFind', function(PropFind $propFind, INode $node){ if (!$node instanceof SabreNode) { return; } $nodeId = $node->getId(); //注册webdav属性的处理方法 $propFind->handle( Application::AI_TEST, function () use ($nodeId) { return $nodeId; } ); }); } ); } } ``` * Command cli命令 * Controller 控制器 * Cron 后台任务 * Db * Exceptions 异常处理 * Listeners 事件处理 * Migration 数据迁移 * Model * Plugins * Service * Storage * Tools * screenshots 预览图 * vendor 第三方库
未完待续...