Просмотр исходного кода

Merge pull request #5197 from weseek/feat/page-redirect-crud

feat: Page redirect crud
Yuki Takei 4 лет назад
Родитель
Сommit
a7dbd0abb5
1 измененных файлов с 84 добавлено и 49 удалено
  1. 84 49
      packages/app/src/server/service/page.ts

+ 84 - 49
packages/app/src/server/service/page.ts

@@ -14,6 +14,7 @@ import {
 import { stringifySnapshot } from '~/models/serializers/in-app-notification-snapshot/page';
 import { stringifySnapshot } from '~/models/serializers/in-app-notification-snapshot/page';
 import ActivityDefine from '../util/activityDefine';
 import ActivityDefine from '../util/activityDefine';
 import { IPage } from '~/interfaces/page';
 import { IPage } from '~/interfaces/page';
+import { PageRedirectModel } from '../models/page-redirect';
 import { ObjectIdLike } from '../interfaces/mongoose-utils';
 import { ObjectIdLike } from '../interfaces/mongoose-utils';
 
 
 const debug = require('debug')('growi:services:page');
 const debug = require('debug')('growi:services:page');
@@ -322,11 +323,6 @@ class PageService {
     // update descendants first
     // update descendants first
     await this.renameDescendantsWithStream(page, newPagePath, user, options, shouldUseV4Process);
     await this.renameDescendantsWithStream(page, newPagePath, user, options, shouldUseV4Process);
 
 
-    /*
-     * TODO: https://redmine.weseek.co.jp/issues/86577
-     * bulkWrite PageRedirectDocument if createRedirectPage is true
-     */
-
     /*
     /*
      * update target
      * update target
      */
      */
@@ -372,11 +368,6 @@ class PageService {
     // update Rivisions
     // update Rivisions
     await Revision.updateRevisionListByPageId(renamedPage._id, { pageId: renamedPage._id });
     await Revision.updateRevisionListByPageId(renamedPage._id, { pageId: renamedPage._id });
 
 
-    /*
-     * TODO: https://redmine.weseek.co.jp/issues/86577
-     * bulkWrite PageRedirectDocument if createRedirectPage is true
-     */
-
     this.pageEvent.emit('rename', page, user);
     this.pageEvent.emit('rename', page, user);
 
 
     return renamedPage;
     return renamedPage;
@@ -389,27 +380,43 @@ class PageService {
       return this.renameDescendantsV4(pages, user, options, oldPagePathPrefix, newPagePathPrefix);
       return this.renameDescendantsV4(pages, user, options, oldPagePathPrefix, newPagePathPrefix);
     }
     }
 
 
-    const Page = this.crowi.model('Page');
+    const Page = mongoose.model('Page') as unknown as PageModel;
+    const PageRedirect = mongoose.model('PageRedirect') as unknown as PageRedirectModel;
 
 
-    const { updateMetadata } = options;
+    const { updateMetadata, createRedirectPage } = options;
 
 
     const updatePathOperations: any[] = [];
     const updatePathOperations: any[] = [];
+    const insertPageRedirectOperations: any[] = [];
 
 
     pages.forEach((page) => {
     pages.forEach((page) => {
       const newPagePath = page.path.replace(oldPagePathPrefix, newPagePathPrefix);
       const newPagePath = page.path.replace(oldPagePathPrefix, newPagePathPrefix);
 
 
       // increment updatePathOperations
       // increment updatePathOperations
       let update;
       let update;
-      if (updateMetadata && !page.isEmpty) {
+      if (!page.isEmpty && updateMetadata) {
         update = {
         update = {
           $set: { path: newPagePath, lastUpdateUser: user._id, updatedAt: new Date() },
           $set: { path: newPagePath, lastUpdateUser: user._id, updatedAt: new Date() },
         };
         };
+
       }
       }
       else {
       else {
         update = {
         update = {
           $set: { path: newPagePath },
           $set: { path: newPagePath },
         };
         };
       }
       }
+
+      if (!page.isEmpty && createRedirectPage) {
+        // insert PageRedirect
+        insertPageRedirectOperations.push({
+          insertOne: {
+            document: {
+              fromPath: page.path,
+              toPath: newPagePath,
+            },
+          },
+        });
+      }
+
       updatePathOperations.push({
       updatePathOperations.push({
         updateOne: {
         updateOne: {
           filter: {
           filter: {
@@ -429,14 +436,25 @@ class PageService {
       }
       }
     }
     }
 
 
+    try {
+      await PageRedirect.bulkWrite(insertPageRedirectOperations);
+    }
+    catch (err) {
+      if (err.code !== 11000) {
+        throw Error(`Failed to create PageRedirect documents: ${err}`);
+      }
+    }
+
     this.pageEvent.emit('updateMany', pages, user);
     this.pageEvent.emit('updateMany', pages, user);
   }
   }
 
 
   private async renameDescendantsV4(pages, user, options, oldPagePathPrefix, newPagePathPrefix) {
   private async renameDescendantsV4(pages, user, options, oldPagePathPrefix, newPagePathPrefix) {
+    const PageRedirect = mongoose.model('PageRedirect') as unknown as PageRedirectModel;
     const pageCollection = mongoose.connection.collection('pages');
     const pageCollection = mongoose.connection.collection('pages');
-    const { updateMetadata } = options;
+    const { updateMetadata, createRedirectPage } = options;
 
 
     const unorderedBulkOp = pageCollection.initializeUnorderedBulkOp();
     const unorderedBulkOp = pageCollection.initializeUnorderedBulkOp();
+    const insertPageRedirectOperations: any[] = [];
 
 
     pages.forEach((page) => {
     pages.forEach((page) => {
       const newPagePath = page.path.replace(oldPagePathPrefix, newPagePathPrefix);
       const newPagePath = page.path.replace(oldPagePathPrefix, newPagePathPrefix);
@@ -449,6 +467,17 @@ class PageService {
       else {
       else {
         unorderedBulkOp.find({ _id: page._id }).update({ $set: { path: newPagePath } });
         unorderedBulkOp.find({ _id: page._id }).update({ $set: { path: newPagePath } });
       }
       }
+      // insert PageRedirect
+      if (!page.isEmpty && createRedirectPage) {
+        insertPageRedirectOperations.push({
+          insertOne: {
+            document: {
+              fromPath: page.path,
+              toPath: newPagePath,
+            },
+          },
+        });
+      }
     });
     });
 
 
     try {
     try {
@@ -460,6 +489,15 @@ class PageService {
       }
       }
     }
     }
 
 
+    try {
+      await PageRedirect.bulkWrite(insertPageRedirectOperations);
+    }
+    catch (err) {
+      if (err.code !== 11000) {
+        throw Error(`Failed to create PageRedirect documents: ${err}`);
+      }
+    }
+
     this.pageEvent.emit('updateMany', pages, user);
     this.pageEvent.emit('updateMany', pages, user);
   }
   }
 
 
@@ -925,6 +963,7 @@ class PageService {
     const Page = mongoose.model('Page') as PageModel;
     const Page = mongoose.model('Page') as PageModel;
     const PageTagRelation = mongoose.model('PageTagRelation') as any; // TODO: Typescriptize model
     const PageTagRelation = mongoose.model('PageTagRelation') as any; // TODO: Typescriptize model
     const Revision = mongoose.model('Revision') as any; // TODO: Typescriptize model
     const Revision = mongoose.model('Revision') as any; // TODO: Typescriptize model
+    const PageRedirect = mongoose.model('PageRedirect') as unknown as PageRedirectModel;
 
 
     // v4 compatible process
     // v4 compatible process
     const shouldUseV4Process = this.shouldUseV4Process(page);
     const shouldUseV4Process = this.shouldUseV4Process(page);
@@ -974,12 +1013,7 @@ class PageService {
       }, { new: true });
       }, { new: true });
       await PageTagRelation.updateMany({ relatedPage: page._id }, { $set: { isPageTrashed: true } });
       await PageTagRelation.updateMany({ relatedPage: page._id }, { $set: { isPageTrashed: true } });
 
 
-      /*
-       * TODO: https://redmine.weseek.co.jp/issues/86577
-       * bulkWrite PageRedirect documents
-       */
-      // const body = `redirect ${newPath}`;
-      // await Page.create(page.path, body, user, { redirectTo: newPath });
+      await PageRedirect.create({ fromPath: page.path, toPath: newPath });
 
 
       this.pageEvent.emit('delete', page, user);
       this.pageEvent.emit('delete', page, user);
       this.pageEvent.emit('create', deletedPage, user);
       this.pageEvent.emit('create', deletedPage, user);
@@ -992,6 +1026,7 @@ class PageService {
     const Page = mongoose.model('Page') as PageModel;
     const Page = mongoose.model('Page') as PageModel;
     const PageTagRelation = mongoose.model('PageTagRelation') as any; // TODO: Typescriptize model
     const PageTagRelation = mongoose.model('PageTagRelation') as any; // TODO: Typescriptize model
     const Revision = mongoose.model('Revision') as any; // TODO: Typescriptize model
     const Revision = mongoose.model('Revision') as any; // TODO: Typescriptize model
+    const PageRedirect = mongoose.model('PageRedirect') as unknown as PageRedirectModel;
 
 
     const newPath = Page.getDeletedPageName(page.path);
     const newPath = Page.getDeletedPageName(page.path);
     const isTrashed = isTrashPage(page.path);
     const isTrashed = isTrashPage(page.path);
@@ -1017,12 +1052,7 @@ class PageService {
     }, { new: true });
     }, { new: true });
     await PageTagRelation.updateMany({ relatedPage: page._id }, { $set: { isPageTrashed: true } });
     await PageTagRelation.updateMany({ relatedPage: page._id }, { $set: { isPageTrashed: true } });
 
 
-    /*
-     * TODO: https://redmine.weseek.co.jp/issues/86577
-     * bulkWrite PageRedirect documents
-     */
-    // const body = `redirect ${newPath}`;
-    // await Page.create(page.path, body, user, { redirectTo: newPath });
+    await PageRedirect.create({ fromPath: page.path, toPath: newPath });
 
 
     this.pageEvent.emit('delete', page, user);
     this.pageEvent.emit('delete', page, user);
     this.pageEvent.emit('create', deletedPage, user);
     this.pageEvent.emit('create', deletedPage, user);
@@ -1031,9 +1061,11 @@ class PageService {
   }
   }
 
 
   private async deleteDescendants(pages, user) {
   private async deleteDescendants(pages, user) {
-    const Page = mongoose.model('Page') as PageModel;
+    const Page = mongoose.model('Page') as unknown as PageModel;
+    const PageRedirect = mongoose.model('PageRedirect') as unknown as PageRedirectModel;
 
 
     const deletePageOperations: any[] = [];
     const deletePageOperations: any[] = [];
+    const insertPageRedirectOperations: any[] = [];
 
 
     pages.forEach((page) => {
     pages.forEach((page) => {
       const newPath = Page.getDeletedPageName(page.path);
       const newPath = Page.getDeletedPageName(page.path);
@@ -1059,6 +1091,15 @@ class PageService {
             },
             },
           },
           },
         };
         };
+
+        insertPageRedirectOperations.push({
+          insertOne: {
+            document: {
+              fromPath: page.path,
+              toPath: newPath,
+            },
+          },
+        });
       }
       }
 
 
       deletePageOperations.push(operation);
       deletePageOperations.push(operation);
@@ -1075,6 +1116,15 @@ class PageService {
     finally {
     finally {
       this.pageEvent.emit('syncDescendantsDelete', pages, user);
       this.pageEvent.emit('syncDescendantsDelete', pages, user);
     }
     }
+
+    try {
+      await PageRedirect.bulkWrite(insertPageRedirectOperations);
+    }
+    catch (err) {
+      if (err.code !== 11000) {
+        throw Error(`Failed to create PageRedirect documents: ${err}`);
+      }
+    }
   }
   }
 
 
   /**
   /**
@@ -1128,25 +1178,11 @@ class PageService {
     const ShareLink = this.crowi.model('ShareLink');
     const ShareLink = this.crowi.model('ShareLink');
     const Revision = this.crowi.model('Revision');
     const Revision = this.crowi.model('Revision');
     const Attachment = this.crowi.model('Attachment');
     const Attachment = this.crowi.model('Attachment');
+    const PageRedirect = mongoose.model('PageRedirect') as unknown as PageRedirectModel;
 
 
     const { attachmentService } = this.crowi;
     const { attachmentService } = this.crowi;
     const attachments = await Attachment.find({ page: { $in: pageIds } });
     const attachments = await Attachment.find({ page: { $in: pageIds } });
 
 
-    /*
-     * TODO: https://redmine.weseek.co.jp/issues/86577
-     * deleteMany related PageRedirect documents
-     */
-    // const pages = await Page.find({ redirectTo: { $ne: null } });
-    // const redirectToPagePathMapping = {};
-    // pages.forEach((page) => {
-    //   redirectToPagePathMapping[page.redirectTo] = page.path;
-    // });
-
-    // const redirectedFromPagePaths: any[] = [];
-    // pagePaths.forEach((pagePath) => {
-    //   redirectedFromPagePaths.push(...this.prepareShoudDeletePagesByRedirectTo(pagePath, redirectToPagePathMapping));
-    // });
-
     return Promise.all([
     return Promise.all([
       Bookmark.deleteMany({ page: { $in: pageIds } }),
       Bookmark.deleteMany({ page: { $in: pageIds } }),
       Comment.deleteMany({ page: { $in: pageIds } }),
       Comment.deleteMany({ page: { $in: pageIds } }),
@@ -1154,8 +1190,7 @@ class PageService {
       ShareLink.deleteMany({ relatedPage: { $in: pageIds } }),
       ShareLink.deleteMany({ relatedPage: { $in: pageIds } }),
       Revision.deleteMany({ path: { $in: pagePaths } }),
       Revision.deleteMany({ path: { $in: pagePaths } }),
       Page.deleteMany({ $or: [{ path: { $in: pagePaths } }, { _id: { $in: pageIds } }] }),
       Page.deleteMany({ $or: [{ path: { $in: pagePaths } }, { _id: { $in: pageIds } }] }),
-      // TODO: https://redmine.weseek.co.jp/issues/86577
-      // Page.deleteMany({ $or: [{ path: { $in: pagePaths } }, { path: { $in: redirectedFromPagePaths } }, { _id: { $in: pageIds } }] }),
+      PageRedirect.deleteMany({ $or: [{ toPath: { $in: pagePaths } }] }),
       attachmentService.removeAllAttachments(attachments),
       attachmentService.removeAllAttachments(attachments),
     ]);
     ]);
   }
   }
@@ -1279,8 +1314,10 @@ class PageService {
   // use the same process in both v4 and v5
   // use the same process in both v4 and v5
   private async revertDeletedDescendants(pages, user) {
   private async revertDeletedDescendants(pages, user) {
     const Page = this.crowi.model('Page');
     const Page = this.crowi.model('Page');
+    const PageRedirect = mongoose.model('PageRedirect') as unknown as PageRedirectModel;
 
 
     const revertPageOperations: any[] = [];
     const revertPageOperations: any[] = [];
+    const fromPathsToDelete: string[] = [];
 
 
     pages.forEach((page) => {
     pages.forEach((page) => {
       // e.g. page.path = /trash/test, toPath = /test
       // e.g. page.path = /trash/test, toPath = /test
@@ -1295,15 +1332,13 @@ class PageService {
           },
           },
         },
         },
       });
       });
-    });
 
 
-    /*
-     * TODO: https://redmine.weseek.co.jp/issues/86577
-     * deleteMany PageRedirectDocument of paths as well
-     */
+      fromPathsToDelete.push(page.path);
+    });
 
 
     try {
     try {
       await Page.bulkWrite(revertPageOperations);
       await Page.bulkWrite(revertPageOperations);
+      await PageRedirect.deleteMany({ fromPath: { $in: fromPathsToDelete } });
     }
     }
     catch (err) {
     catch (err) {
       if (err.code !== 11000) {
       if (err.code !== 11000) {