Skip to content

Commit bd08c0f

Browse files
committed
バックアップ取得用クラスを追加
1 parent da141a2 commit bd08c0f

21 files changed

+670
-99
lines changed

composer.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"Takuya\\BacklogApiClient\\": "src/lib"
1010
},
1111
"files": [
12-
"src/helpers/domain_name_utils.php"
12+
"src/helpers/domain_name_utils.php",
13+
"src/helpers/StrTool.php"
1314
]
1415
},
1516
"autoload-dev": {
@@ -33,7 +34,8 @@
3334
"guzzlehttp/guzzle": ">=7.5",
3435
"ext-json": "*",
3536
"ext-gd": "*",
36-
"takuya/php-genetator-array-access": "^1.0"
37+
"takuya/php-genetator-array-access": "^1.0",
38+
"doctrine/inflector": "^2.0"
3739
},
3840
"require-dev": {
3941
"phpunit/phpunit": "^9.5",

src/helpers/StrTool.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace Takuya\BacklogApiClient\Utils;
4+
5+
use Doctrine\Inflector\Inflector;
6+
use Doctrine\Inflector\InflectorFactory;
7+
8+
class StrTool {
9+
protected static Inflector $inflector;
10+
11+
public static function inflector (): Inflector {
12+
return static::$inflector ??= InflectorFactory::createForLanguage( 'english' )->build();
13+
}
14+
15+
public static function singular ( string $str ) {
16+
return static::inflector()->singularize( $str );
17+
}
18+
19+
public static function plural ( string $str ) {
20+
return static::inflector()->pluralize( $str );
21+
}
22+
23+
public static function isSingular ( string $str ) {
24+
return $str == static::singular( $str );
25+
}
26+
27+
public static function isPlural ( string $str ) {
28+
return $str == static::plural( $str );
29+
}
30+
31+
public static function snake ( $value, $delimiter = '_' ) {
32+
$value = preg_replace( '/\s+/u', '', ucwords( $value ) );
33+
$value = preg_replace( '/(.)(?=[A-Z])/u', '$1'.$delimiter, $value );
34+
$value = mb_strtolower( $value, 'UTF-8' );
35+
return $value;
36+
}
37+
}
38+

src/lib/BacklogArchiver.php

Lines changed: 0 additions & 52 deletions
This file was deleted.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Takuya\BacklogApiClient\Backup\ArchiveService;
4+
5+
use Takuya\BacklogApiClient\Backup\Contracts\ArchiverContract;
6+
7+
class ArchiveDump implements ArchiverContract {
8+
public function __construct( public $file='php:/stdout'){
9+
10+
}
11+
public function saveBacklogModel ( string $name, array $arr ):bool {
12+
13+
$ret = var_export([$name,$arr],true);
14+
file_put_contents($this->file,$ret);
15+
return true;
16+
}
17+
18+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Takuya\BacklogApiClient\Backup\ArchiveService;
4+
5+
use Takuya\BacklogApiClient\Backup\Contracts\ArchiverContract;
6+
use Takuya\BacklogApiClient\Backup\BacklogArchiver;
7+
use Takuya\BacklogApiClient\Utils\StrTool;
8+
9+
class ArchiveEloquent implements ArchiverContract {
10+
public function saveBacklogModel ( string $name, array $arr ):bool {
11+
$arr = $this->snake_case_key( $arr );
12+
$app_model_class = 'App\\Models\\'.$name;
13+
return ( new $app_model_class( $arr ) )->save();
14+
}
15+
16+
protected function snake_case_key ( $arr ) {
17+
foreach ( $arr as $k => $v ) {
18+
unset( $arr[$k] );
19+
$arr[StrTool::snake( $k )] = $v;
20+
}
21+
22+
return $arr;
23+
}
24+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Takuya\BacklogApiClient\Backup\ArchiveService;
4+
5+
use Takuya\BacklogApiClient\Backup\Contracts\ArchiverContract;
6+
7+
class ArchiveJson implements ArchiverContract {
8+
public function saveBacklogModel ( string $name, array $arr ):bool {
9+
$str = json_encode($arr);
10+
$key = md5($str);
11+
return file_put_contents("$name.$key.json",$str );
12+
}
13+
14+
}

src/lib/Backup/BacklogArchiver.php

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<?php
2+
3+
namespace Takuya\BacklogApiClient\Backup;
4+
5+
use Takuya\BacklogApiClient\Backlog;
6+
use Takuya\BacklogApiClient\Backup\Traits\HasClassCheck;
7+
use Takuya\BacklogApiClient\Models\Interfaces\HasIcon;
8+
use Takuya\BacklogApiClient\Models\Interfaces\ProjectAttrs;
9+
use Takuya\BacklogApiClient\Models\Interfaces\HasFileContent;
10+
use Takuya\BacklogApiClient\Models\BaseModel;
11+
use Takuya\BacklogApiClient\Backup\Traits\ArchiveMethods;
12+
use Takuya\BacklogApiClient\Utils\StrTool;
13+
use Takuya\BacklogApiClient\Backup\Contracts\ArchiverContract;
14+
15+
class BacklogArchiver {
16+
17+
use HasClassCheck;
18+
use ArchiveMethods;
19+
20+
protected Backlog $cli;
21+
22+
public function __construct (protected ArchiverContract $archiverContract) {
23+
}
24+
25+
public function saveBacklogModel ( \Takuya\BacklogApiClient\Models\BaseModel $obj ): void {
26+
$arr = $this->storable($obj);
27+
$ref = new \ReflectionClass( $obj );
28+
$name = $ref->getShortName();
29+
$this->archiverContract->saveBacklogModel($name, $arr);
30+
}
31+
32+
public function storable ( BaseModel $obj ): array {
33+
$arr = $obj->toArray();
34+
$arr = $this->filterAttr( $arr, get_class( $obj ) );
35+
$arr = array_merge( $arr, $this->getTraitRelation( $obj ), $this->getInterfaceAttrs( $obj ) );
36+
return $arr;
37+
}
38+
39+
protected function filterAttrUser ( $arr, $class ) {
40+
$map = $class::attribute_mapping_list();
41+
$userAttrNames = array_map( fn( $e ) => $e[0], array_filter( $map, fn( $e ) => str_ends_with( $e[1], 'User' ) ) );
42+
$userArrayAttrNames = array_filter( $userAttrNames, fn( $str ) => $str == StrTool::plural( $str ) );
43+
$userAttrNames = array_filter( $userAttrNames, fn( $str ) => $str == StrTool::singular( $str ) );
44+
foreach ( $arr as $k => $v ) {
45+
if ( $k == 'nulabAccount' ) {
46+
$arr[$k] = $v['nulabId'] ?? null;
47+
}
48+
if ( in_array( $k, $userArrayAttrNames ) ) {
49+
$arr[$k] = array_map( fn( $e ) => $e["userId"], $v );
50+
}
51+
if ( in_array( $k, $userAttrNames ) ) {
52+
$arr[$k] = $v["userId"] ?? null;
53+
}
54+
}
55+
56+
return $arr;
57+
}
58+
protected function filterAttribnutes($arr,$class,$attrName){
59+
if ( !empty( $arr[$attrName] ) ) {
60+
$attr = $arr[$attrName];
61+
if ( is_array( $attr ) && array_key_exists( 0, $attr ) ) {
62+
$values = array_map( fn( $e ) => $e['id'], $attr );
63+
$arr[$attrName] = $values;
64+
}
65+
if ( is_array( $attr ) && array_key_exists( 'id', $attr ) ) {
66+
$arr[$attrName] = $attr['id'];
67+
}
68+
}
69+
return $arr;
70+
}
71+
protected function filterAttr( $arr, $class ) {
72+
$arr = $this->filterAttrUser($arr, $class);
73+
$arr = $this->filterAttribnutes($arr,$class, 'attachments');
74+
$arr = $this->filterAttribnutes($arr,$class, 'stars');
75+
$arr = $this->filterAttribnutes($arr,$class, 'sharedFiles');
76+
$arr = $this->filterAttribnutes($arr,$class, 'category');
77+
$arr = $this->filterAttribnutes($arr,$class, 'customFields');
78+
$arr = $this->filterAttribnutes($arr,$class, 'status');
79+
$arr = $this->filterAttribnutes($arr,$class, 'issueType');
80+
$arr = $this->filterAttribnutes($arr,$class, 'tags');
81+
return $arr;
82+
}
83+
84+
protected function getTraitRelation( $obj ) {
85+
$traits = $this->findRelationTraits($obj);
86+
$cols = [];
87+
foreach ($traits as $trait) {
88+
if( str_ends_with(strtolower($trait->getName()), 'space') ) {
89+
$cols['spaceKey'] = $obj->getSpaceKey();
90+
}
91+
if( str_ends_with(strtolower($trait->getName()), 'project') ) {
92+
$cols['projectId'] = $obj->getProjectId();
93+
}
94+
if( str_ends_with(strtolower($trait->getName()), 'issue') ) {
95+
$cols['issueId'] = $obj->getIssueId();
96+
}
97+
if( str_ends_with(strtolower($trait->getName()), 'comment') ) {
98+
$cols['commentId'] = $obj->getCommentId();
99+
}
100+
if( str_ends_with(strtolower($trait->getName()), 'wikipage') ) {
101+
$cols['wikiId'] = $obj->getWikiPageId();
102+
}
103+
}
104+
return $cols;
105+
}
106+
107+
protected function getInterfaceAttrs( $obj ) {
108+
$cols = [];
109+
if( $this->hasInterface($obj, HasIcon::class) ) {
110+
$cols['icon'] = $obj->icon();
111+
}
112+
if( $this->hasInterface($obj, HasFileContent::class) ) {
113+
$mem_max = ini_get('memory_limit');// ファイル取得が必要なのでメモリ上限を引き上げる。
114+
ini_set( 'memory_limit', '-1' );
115+
/** @var HasFileContent $obj */
116+
if($this->isClass($obj,\Takuya\BacklogApiClient\Models\SharedFile::class)){
117+
/** @var \Takuya\BacklogApiClient\Models\SharedFile $obj */
118+
$cols['content'] = $obj->isFile() ? $obj->getContent() : null;
119+
}else{
120+
$cols['content'] = $obj->getContent();
121+
}
122+
// ini_set('memory_limit',$mem_max);
123+
}
124+
if( $this->hasInterface($obj, ProjectAttrs::class) ) {
125+
/** @var ProjectAttrs $obj */
126+
$cols['teams'] = array_map(fn( $e ) => $e->id, $obj->teams());
127+
$cols['users'] = array_map(fn( $e ) => $e->userId, $obj->users());
128+
}
129+
130+
return $cols;
131+
}
132+
133+
134+
135+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Takuya\BacklogApiClient\Backup\Contracts;
4+
5+
interface ArchiverContract {
6+
public function saveBacklogModel ( string $name , array $arr ):bool;
7+
8+
}

0 commit comments

Comments
 (0)