mirror of
https://git.yylx.win/https://github.com/osoobe/freescout-api-extender.git
synced 2025-10-03 18:21:38 +08:00
Initial commit
This commit is contained in:
commit
952ca5e52a
19 changed files with 440 additions and 0 deletions
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
ApiExtender*.zip
|
||||
/vendor/
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# Laravel 4 specific
|
||||
bootstrap/compiled.php
|
||||
app/storage/
|
||||
|
||||
# Laravel 5 & Lumen specific
|
||||
public/storage
|
||||
public/hot
|
||||
|
||||
# Laravel 5 & Lumen specific with changed public path
|
||||
public_html/storage
|
||||
public_html/hot
|
||||
|
||||
storage/*.key
|
||||
.env
|
||||
Homestead.yaml
|
||||
Homestead.json
|
||||
/.vagrant
|
||||
.phpunit.result.cache
|
0
Http/Controllers/.gitkeep
Normal file
0
Http/Controllers/.gitkeep
Normal file
96
Http/Controllers/KnowledgeBaseApiController.php
Normal file
96
Http/Controllers/KnowledgeBaseApiController.php
Normal file
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace Modules\ApiExtender\Http\Controllers;
|
||||
|
||||
use App\Conversation;
|
||||
use App\Mailbox;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\KnowledgeBase\Entities\KbCategory;
|
||||
use Modules\KnowledgeBase\Entities\KbArticle;
|
||||
use Modules\KnowledgeBase\Entities\KbArticleKbCategory;
|
||||
|
||||
class KnowledgeBaseApiController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function get(Request $request, $mailboxId)
|
||||
{
|
||||
$mailbox = Mailbox::findOrFail($mailboxId);
|
||||
if ($mailbox === null) {
|
||||
return Response::json([], 404);
|
||||
}
|
||||
$categories = \KbCategory::getTree($mailbox->id, [], 0, true);
|
||||
|
||||
$locale = $request->input('locale') ?? \Kb::defaultLocale($mailbox);
|
||||
|
||||
$items = [];
|
||||
|
||||
foreach ($categories as $c) {
|
||||
if (!$c->checkVisibility()) {
|
||||
continue;
|
||||
}
|
||||
$items[] = (object)[
|
||||
'id' => $c->id,
|
||||
'name' => $c->getAttributeInLocale('name', $locale),
|
||||
'description' => $c->getAttributeInLocale('description', $locale)
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
return Response::json([
|
||||
'mailbox_id' => $mailbox->id,
|
||||
'name' => $mailbox->name,
|
||||
'categories' => $items,
|
||||
], 200);
|
||||
|
||||
}
|
||||
|
||||
public function category(Request $request, $mailboxId, $categoryId)
|
||||
{
|
||||
$mailbox = Mailbox::findOrFail($mailboxId);
|
||||
if ($mailbox === null) {
|
||||
return Response::json([], 404);
|
||||
}
|
||||
|
||||
$category = KbCategory::findOrFail($categoryId);
|
||||
if (!$category->checkVisibility()) {
|
||||
$category = null;
|
||||
}
|
||||
if ($category === null) {
|
||||
return Response::json([], 404);
|
||||
}
|
||||
$articles = [];
|
||||
if ($category) {
|
||||
$sortedArticles = $category->getArticlesSorted(true);
|
||||
}
|
||||
|
||||
$locale = $request->input('locale') ?? \Kb::defaultLocale($mailbox);
|
||||
|
||||
foreach ($sortedArticles as $a) {
|
||||
$a->setLocale($locale);
|
||||
$articles[] = (object)['id' => $a->id, 'title' => $a->getAttributeInLocale('title', $locale), 'text' => $a->getAttributeInLocale('text', $locale)];
|
||||
}
|
||||
|
||||
return Response::json([
|
||||
'id' => 0,
|
||||
'mailbox_id' => $mailbox->id,
|
||||
'name' => $mailbox->name,
|
||||
'category' => (object)[
|
||||
'id'=>$category->id,
|
||||
'name'=>$category->getAttributeInLocale('name', $locale),
|
||||
'description'=>$category->getAttributeInLocale('description', $locale),
|
||||
],
|
||||
'articles' => $articles,
|
||||
], 200);
|
||||
}
|
||||
|
||||
}
|
96
Http/Controllers/ReportApiController.php
Normal file
96
Http/Controllers/ReportApiController.php
Normal file
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace Modules\ApiExtender\Http\Controllers;
|
||||
|
||||
use App\Conversation;
|
||||
use App\Mailbox;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\KnowledgeBase\Entities\KbCategory;
|
||||
use Modules\KnowledgeBase\Entities\KbArticle;
|
||||
use Modules\KnowledgeBase\Entities\KbArticleKbCategory;
|
||||
|
||||
class ReportApiController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function get(Request $request, $mailboxId)
|
||||
{
|
||||
$mailbox = Mailbox::findOrFail($mailboxId);
|
||||
if ($mailbox === null) {
|
||||
return Response::json([], 404);
|
||||
}
|
||||
$categories = \KbCategory::getTree($mailbox->id, [], 0, true);
|
||||
|
||||
$locale = $request->input('locale') ?? \Kb::defaultLocale($mailbox);
|
||||
|
||||
$items = [];
|
||||
|
||||
foreach ($categories as $c) {
|
||||
if (!$c->checkVisibility()) {
|
||||
continue;
|
||||
}
|
||||
$items[] = (object)[
|
||||
'id' => $c->id,
|
||||
'name' => $c->getAttributeInLocale('name', $locale),
|
||||
'description' => $c->getAttributeInLocale('description', $locale)
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
return Response::json([
|
||||
'mailbox_id' => $mailbox->id,
|
||||
'name' => $mailbox->name,
|
||||
'categories' => $items,
|
||||
], 200);
|
||||
|
||||
}
|
||||
|
||||
public function category(Request $request, $mailboxId, $categoryId)
|
||||
{
|
||||
$mailbox = Mailbox::findOrFail($mailboxId);
|
||||
if ($mailbox === null) {
|
||||
return Response::json([], 404);
|
||||
}
|
||||
|
||||
$category = KbCategory::findOrFail($categoryId);
|
||||
if (!$category->checkVisibility()) {
|
||||
$category = null;
|
||||
}
|
||||
if ($category === null) {
|
||||
return Response::json([], 404);
|
||||
}
|
||||
$articles = [];
|
||||
if ($category) {
|
||||
$sortedArticles = $category->getArticlesSorted(true);
|
||||
}
|
||||
|
||||
$locale = $request->input('locale') ?? \Kb::defaultLocale($mailbox);
|
||||
|
||||
foreach ($sortedArticles as $a) {
|
||||
$a->setLocale($locale);
|
||||
$articles[] = (object)['id' => $a->id, 'title' => $a->getAttributeInLocale('title', $locale), 'text' => $a->getAttributeInLocale('text', $locale)];
|
||||
}
|
||||
|
||||
return Response::json([
|
||||
'id' => 0,
|
||||
'mailbox_id' => $mailbox->id,
|
||||
'name' => $mailbox->name,
|
||||
'category' => (object)[
|
||||
'id'=>$category->id,
|
||||
'name'=>$category->getAttributeInLocale('name', $locale),
|
||||
'description'=>$category->getAttributeInLocale('description', $locale),
|
||||
],
|
||||
'articles' => $articles,
|
||||
], 200);
|
||||
}
|
||||
|
||||
}
|
5
Http/routes.php
Normal file
5
Http/routes.php
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
Route::group(['prefix' => \Helper::getSubdirectory(), 'namespace' => 'Modules\ApiExtender\Http\Controllers'], function () {
|
||||
Route::get('/api/knowledgebase/{mailboxId}/categories', ['uses' => 'KnowledgeBaseApiController@get', 'laroute' => false])->name('knowledgebase.index');
|
||||
Route::get('/api/knowledgebase/{mailboxId}/categories/{categoryId}', ['uses' => 'KnowledgeBaseApiController@category', 'laroute' => false])->name('knowledgebase.category');
|
||||
});
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 @jtorvald
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
0
Providers/.gitkeep
Normal file
0
Providers/.gitkeep
Normal file
43
Providers/ApiExtenderServiceProvider.php
Normal file
43
Providers/ApiExtenderServiceProvider.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Modules\ApiExtender\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class ApiExtenderServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Indicates if loading of the provider is deferred.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $defer = false;
|
||||
|
||||
/**
|
||||
* Boot the application events.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Module hooks.
|
||||
*/
|
||||
public function hooks()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the services provided by the provider.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function provides()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
0
Public/.gitkeep
Normal file
0
Public/.gitkeep
Normal file
38
Public/images/module.svg
Normal file
38
Public/images/module.svg
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="256px" height="256px" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>module</title>
|
||||
<defs>
|
||||
<path d="M62,3.00122599 C62,1.35349407 60.6354067,0 58.9741627,0 L11.6435407,0 C5.14688995,0 0,5.10502656 0,11.4017164 C0,11.4017164 0,62.8197793 0,62.8492031 C0,67.9542297 4.22727273,72 9.37416268,72 L58.8258373,72 C60.0421053,72 61.2435407,71.2496935 61.7033493,70.0433183 C62.1631579,68.8369432 61.8516746,67.498161 60.7985646,66.7478545 C58.1138756,65.0559869 57.9507177,61.3485901 60.338756,59.7008582 C60.8430622,59.2006539 61.9851675,58.1708214 61.8961722,56.6996322 C61.9703349,56.4642419 62,3.00122599 62,3.00122599 Z M6.05167464,62.8492031 C6.05167464,61.0543523 7.5645933,59.7008582 9.37416268,59.7008582 L52.9373206,59.7008582 C51.6023923,61.907642 51.8842105,64.496935 52.9373206,65.997548 L9.37416268,65.997548 C7.5645933,65.997548 6.05167464,64.6587658 6.05167464,62.8492031 Z M55.9631579,53.6984062 L9.38899522,53.6984062 C8.21722488,53.6984062 7.10478469,53.9190846 6.06650718,54.3163057 L6.06650718,11.4017164 C6.06650718,8.4004904 8.63253589,6.00245198 11.6583732,6.00245198 L55.9779904,6.00245198 L55.9779904,53.6984062 L55.9631579,53.6984062 Z" id="path-1"></path>
|
||||
<filter x="-26.6%" y="-18.8%" width="153.2%" height="145.8%" filterUnits="objectBoundingBox" id="filter-2">
|
||||
<feOffset dx="0" dy="3" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||
<feGaussianBlur stdDeviation="5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
|
||||
</filter>
|
||||
<polygon id="path-3" points="27.0340136 0 0 26.7240312 10.0272109 26.7240312 2.31972789 47 30 20.2742777 19.9710884 20.2742777"></polygon>
|
||||
<filter x="-21.7%" y="-9.6%" width="150.0%" height="131.9%" filterUnits="objectBoundingBox" id="filter-4">
|
||||
<feOffset dx="1" dy="3" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||
<feGaussianBlur stdDeviation="2" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
|
||||
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
|
||||
</filter>
|
||||
</defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="module">
|
||||
<rect id="Rectangle" stroke="#979797" fill="#BA3434" x="0.5" y="0.5" width="255" height="255"></rect>
|
||||
<circle id="Oval" fill="#E95252" cx="128" cy="85" r="57"></circle>
|
||||
<g id="book-svgrepo-com" transform="translate(97.000000, 49.000000)" fill-rule="nonzero">
|
||||
<g id="Shape">
|
||||
<use fill="black" fill-opacity="1" filter="url(#filter-2)" xlink:href="#path-1"></use>
|
||||
<use fill="#FFFFFF" xlink:href="#path-1"></use>
|
||||
</g>
|
||||
<g id="Path" transform="translate(16.000000, 6.000000)">
|
||||
<use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-3"></use>
|
||||
<use fill="#FFBC00" xlink:href="#path-3"></use>
|
||||
</g>
|
||||
</g>
|
||||
<text id="Knowledge-Base-API" font-family="Helvetica" font-size="30" font-weight="normal" fill="#FFFFFF">
|
||||
<tspan x="53.2763672" y="189">Knowledge</tspan>
|
||||
<tspan x="65.7861328" y="225">Base API</tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
0
Resources/assets/.gitkeep
Normal file
0
Resources/assets/.gitkeep
Normal file
0
Resources/lang/.gitkeep
Normal file
0
Resources/lang/.gitkeep
Normal file
0
Resources/views/.gitkeep
Normal file
0
Resources/views/.gitkeep
Normal file
24
composer.json
Normal file
24
composer.json
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "freescout/apiextender",
|
||||
"description": "",
|
||||
"authors": [
|
||||
{
|
||||
"name": "jtorvald",
|
||||
"email": ""
|
||||
}
|
||||
],
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Modules\\ApiExtender\\Providers\\ApiExtenderServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Modules\\ApiExtender\\": ""
|
||||
}
|
||||
}
|
||||
}
|
BIN
logo.sketch
Normal file
BIN
logo.sketch
Normal file
Binary file not shown.
26
module.json
Normal file
26
module.json
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"name": "Api Extender",
|
||||
"alias": "apiextender",
|
||||
"description": "This module adds the a public API for categories and articles from the Knowledge base, report and other modules",
|
||||
"version": "1.0.0",
|
||||
"detailsUrl": "https://github.com/osoobe/freescout-api-extender",
|
||||
"author": "osoobe",
|
||||
"authorUrl": "https://github.com/osoobe",
|
||||
"requiredAppVersion": "1.8.7",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"knowledge",
|
||||
"api"
|
||||
],
|
||||
"img": "/modules/apiextender/images/module.svg",
|
||||
"active": 0,
|
||||
"order": 0,
|
||||
"providers": [
|
||||
"Modules\\ApiExtender\\Providers\\ApiExtenderServiceProvider"
|
||||
],
|
||||
"aliases": {},
|
||||
"files": [
|
||||
"start.php"
|
||||
],
|
||||
"requires": []
|
||||
}
|
47
readme.md
Normal file
47
readme.md
Normal file
|
@ -0,0 +1,47 @@
|
|||
# Knowledge base API module for FreeScout
|
||||
This module adds the option to add a public API for the [FreeScout](https://freescout.net) knowledge base (module).
|
||||
|
||||
## Requirements
|
||||
- [FreeScout](https://freescout.net) installed
|
||||
- FreeScout [Knowledge base module](https://freescout.net/module/knowledge-base/)
|
||||
|
||||
## Installation
|
||||
|
||||
1. Download the latest module zip file via the releases card on the right.
|
||||
2. Transfer the zip file to the server in the Modules folder of FreeScout.
|
||||
3. Unpack the zip file.
|
||||
4. Remove the zip file.
|
||||
5. Activate the module via the Modules page in FreeScout.
|
||||
|
||||
## Update instructions
|
||||
|
||||
1. Download the latest module zip file via the releases card on the right.
|
||||
2. Transfer the zip file to the server in the Modules folder of FreeScout.
|
||||
3. Remove the folder ApiExtender
|
||||
4. Unpack the zip file.
|
||||
5. Remove the zip file.
|
||||
|
||||
## Contributing
|
||||
|
||||
Feel free to add your own features by sending a pull request.
|
||||
|
||||
## Get knowledge base categories in a mailbox
|
||||
|
||||
```
|
||||
curl "https://example.com/api/knowledgebase/1/categories?locale=en" \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Content-Type: application/json; charset=utf-8' \
|
||||
-d $'{}'
|
||||
```
|
||||
|
||||
## Get articles in a category
|
||||
|
||||
```
|
||||
curl "https://example.com/api/knowledgebase/1/categories/1?locale=en" \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Content-Type: application/json; charset=utf-8' \
|
||||
-d $'{}'
|
||||
```
|
||||
## LICENSE
|
||||
|
||||
MIT
|
3
release.sh
Normal file
3
release.sh
Normal file
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env sh
|
||||
# rm ApiExtender-*.zip
|
||||
# zip -r ApiExtender-1.0.1.zip ApiExtender -x "*.DS_Store" -x ".git*" -x ".idea*" -x "*.gitkeep"
|
17
start.php
Normal file
17
start.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register Namespaces And Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When a module starting, this file will execute automatically. This helps
|
||||
| to register some namespaces like translator or view. Also, this file
|
||||
| will load the routes file for each module. You may also modify
|
||||
| this file as you want.
|
||||
|
|
||||
*/
|
||||
|
||||
if (!app()->routesAreCached()) {
|
||||
require __DIR__ . '/Http/routes.php';
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue