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+ }
0 commit comments