From 2cd50d47af20a0580de426c85bfb90a0797019e2 Mon Sep 17 00:00:00 2001 From: "Fabien \"egg\" O'Carroll" Date: Wed, 2 Aug 2023 14:14:54 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=90=9B=20Fixed=20superfluous=20DB=20q?= =?UTF-8?q?ueries=20on=20Collection=20save?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a global hook for the bookshelf-relations plugin which updates the sort_order for pivot tables when saving the parent model. This hook requires that we fetch each row in the pivot table related to the model and then run an update on each one. Since we have a "latest" Collection this means at least N update queries where N is the number of Posts for a site. For large sites this was crippling the database. We only need the sort_order to be updated for Collections with a type of "manual". We currently don't have a way to disable the update based on model attributes, so instead we have disabled the update for all Collections - this is okay because 1. Collections is not released and 2. we don't have full support for manual Collections yet anyway. --- .../core/core/server/models/base/bookshelf.js | 2 +- .../models/model_collections.test.js | 53 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 ghost/core/test/regression/models/model_collections.test.js diff --git a/ghost/core/core/server/models/base/bookshelf.js b/ghost/core/core/server/models/base/bookshelf.js index 4d2bcb5c3c..64e2a96945 100644 --- a/ghost/core/core/server/models/base/bookshelf.js +++ b/ghost/core/core/server/models/base/bookshelf.js @@ -80,7 +80,7 @@ ghostBookshelf.plugin('bookshelf-relations', { }; // CASE: disable after hook for specific relations - if (['permissions_roles', 'members_newsletters'].indexOf(existing.relatedData.joinTableName) !== -1) { + if (['permissions_roles', 'members_newsletters', 'collections_posts'].indexOf(existing.relatedData.joinTableName) !== -1) { return Promise.resolve(); } diff --git a/ghost/core/test/regression/models/model_collections.test.js b/ghost/core/test/regression/models/model_collections.test.js new file mode 100644 index 0000000000..4fd9d8fad8 --- /dev/null +++ b/ghost/core/test/regression/models/model_collections.test.js @@ -0,0 +1,53 @@ +const assert = require('assert/strict'); +const testUtils = require('../../utils'); +const models = require('../../../core/server/models'); +const db = require('../../../core/server/data/db'); + +describe('Collection Model', function () { + before(testUtils.teardownDb); + before(testUtils.stopGhost); + after(testUtils.teardownDb); + + // This is required for the models to be initialised ??? + // @TODO remove this once we have a better way of initialising models + before(testUtils.setup('users:roles', 'posts')); + + describe('add', function () { + it('does not update the sort_order of the collections_posts table', async function () { + if (db?.knex?.client?.config?.client !== 'sqlite3') { + return this.skip(); + } + /** @type {import('sqlite3').Database} */ + const database = db.knex.client; + + let didUpdateCollectionPosts = false; + + function handler(/** @type {{sql: string}} */ query) { + if (query.sql.toLowerCase().includes('update `collections_posts` set `sort_order`')) { + didUpdateCollectionPosts = true; + } + } + + const posts = await models.Post.findAll(); + + database.on('query', handler); + + await models.Collection.add({ + title: 'Test Collection', + slug: 'test-collection', + description: 'Test description', + type: 'manual', + filter: null, + posts: posts.toJSON().map(post => ({id: post.id})), + feature_image: null + }); + + database.off('query', handler); + + const actual = didUpdateCollectionPosts; + const expected = false; + + assert.equal(actual, expected, 'collections_posts should not have been updated'); + }); + }); +}); From 6936007052b49ffb8bd795e73e3ff682cdcfd332 Mon Sep 17 00:00:00 2001 From: Steve Larson <9larsons@gmail.com> Date: Wed, 2 Aug 2023 09:56:40 -0500 Subject: [PATCH 2/3] :bug: Updated gscan error handling for page errors (#17575) refs https://github.com/TryGhost/Product/issues/3676 - add filter for sidebar display of theme errors (angry red box) - filter specific to each page feature, will need to add each one by this approach --- .../test/utils/responses/themes.json | 4 +- .../app/components/gh-nav-menu/footer.js | 13 +++- ghost/core/package.json | 2 +- .../utils/fixtures/themes/casper/package.json | 2 +- .../utils/fixtures/themes/test-theme/page.hbs | 47 +++++++++++++++ .../test/utils/fixtures/themes/warnings.zip | Bin 309706 -> 309768 bytes yarn.lock | 56 ++++++++++++++++-- 7 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 ghost/core/test/utils/fixtures/themes/test-theme/page.hbs diff --git a/apps/admin-x-settings/test/utils/responses/themes.json b/apps/admin-x-settings/test/utils/responses/themes.json index 3dfb92f029..cd4a1d4b09 100644 --- a/apps/admin-x-settings/test/utils/responses/themes.json +++ b/apps/admin-x-settings/test/utils/responses/themes.json @@ -53,7 +53,7 @@ "autoprefixer": "10.4.7", "beeper": "2.1.0", "cssnano": "5.1.12", - "gscan": "4.37.4", + "gscan": "4.37.5", "gulp": "4.0.2", "gulp-concat": "2.6.1", "gulp-livereload": "4.0.2", @@ -315,7 +315,7 @@ "autoprefixer": "10.4.14", "beeper": "2.1.0", "cssnano": "6.0.1", - "gscan": "4.37.4", + "gscan": "4.37.5", "gulp": "4.0.2", "gulp-concat": "2.6.1", "gulp-livereload": "4.0.2", diff --git a/ghost/admin/app/components/gh-nav-menu/footer.js b/ghost/admin/app/components/gh-nav-menu/footer.js index eb7207a44a..eb9e9eba1f 100644 --- a/ghost/admin/app/components/gh-nav-menu/footer.js +++ b/ghost/admin/app/components/gh-nav-menu/footer.js @@ -36,7 +36,18 @@ export default class Footer extends Component { } get hasThemeErrors() { - return this.themeManagement.activeTheme && this.themeManagement.activeTheme.gscanErrors.length; + const errors = this.themeManagement.activeTheme && this.themeManagement.activeTheme.gscanErrors; + if (!errors) { + return false; + } + // filter errors that have other UI to display to users that the functionality is not working + const filteredErrors = errors?.filter((error) => { + if (error.code === 'GS110-NO-MISSING-PAGE-BUILDER-USAGE' && error?.failures?.[0].message.includes(`show_title_and_feature_image`)) { + return false; + } + return true; + }); + return filteredErrors && filteredErrors.length; } // equivalent to "left: auto; right: -20px" diff --git a/ghost/core/package.json b/ghost/core/package.json index 8b9c864611..4642ca509a 100644 --- a/ghost/core/package.json +++ b/ghost/core/package.json @@ -187,7 +187,7 @@ "ghost-storage-base": "1.0.0", "glob": "8.1.0", "got": "11.8.6", - "gscan": "4.37.4", + "gscan": "4.37.5", "human-number": "2.0.1", "image-size": "1.0.2", "intl": "1.2.5", diff --git a/ghost/core/test/utils/fixtures/themes/casper/package.json b/ghost/core/test/utils/fixtures/themes/casper/package.json index f570d70319..3298a16ebe 100644 --- a/ghost/core/test/utils/fixtures/themes/casper/package.json +++ b/ghost/core/test/utils/fixtures/themes/casper/package.json @@ -49,7 +49,7 @@ "autoprefixer": "10.2.5", "beeper": "2.1.0", "cssnano": "4.1.10", - "gscan": "4.37.4", + "gscan": "4.37.5", "gulp": "4.0.2", "gulp-concat": "2.6.1", "gulp-livereload": "4.0.2", diff --git a/ghost/core/test/utils/fixtures/themes/test-theme/page.hbs b/ghost/core/test/utils/fixtures/themes/test-theme/page.hbs new file mode 100644 index 0000000000..f74f63f64b --- /dev/null +++ b/ghost/core/test/utils/fixtures/themes/test-theme/page.hbs @@ -0,0 +1,47 @@ +{{!< default}} + +{{!-- The tag above means: insert everything in this file +into the {body} tag of the default.hbs template --}} + + +{{#post}} +{{!-- Everything inside the #post block pulls data from the page --}} + +
+
+ + {{#match @page.show_title_and_feature_image}} +
+ +

{{title}}

+ + {{#if feature_image}} +
+ {{!-- This is a responsive image, it loads different sizes depending on device + https://medium.freecodecamp.org/a-guide-to-responsive-images-with-ready-to-use-templates-c400bd65c433 --}} + {{#if feature_image_alt}}{{feature_image_alt}}{{else}}{{title}}{{/if}} + {{#if feature_image_caption}} +
{{feature_image_caption}}
+ {{/if}} +
+ {{/if}} + +
+ {{/match}} + +
+ {{content}} +
+ +
+
+ +{{/post}} \ No newline at end of file diff --git a/ghost/core/test/utils/fixtures/themes/warnings.zip b/ghost/core/test/utils/fixtures/themes/warnings.zip index 6abc471101877adca7b066547e0efc3704128363..a8d963eb803c9b3b33b88824d5e57b2560c0c646 100644 GIT binary patch delta 3715 zcma)9dpwls9)I8Wc|WTu_vFd}PKn@Z`h7FmlAYdB>)8QVI!Y%0{} ziS}}mHtUvKCZ}3zJFL-us^cgJrCQgCu46fJInT?I%R4@qk3Z)5{=UE4^LxI}GtyVf zlI6=(y*vP95%iznP-?oWx#j>#5Kseue}mZY(>-lw1GIq(fq@e?>i_YV2F31Y6D0hD zTY4`|mpYW1xmWLfzIt>#CSxX4Lm z1IoVi|>AjsZV! zN@YUY^(IToUj4nfjYvwgq$G)!0A`VnD5VYsLB6=WoiKu{(V9QTG5pDNgOn@aH zOM}$#|E%dGh$3&#$kuh7tKBGr=b_6{r+B^>DU z+jA~E!@^Nti*@evGddwX$q)Cr{=~6v*SKTz$g1F5rKH$`DrdLGn$3y+y92?X+vpSB z2WBbi2DLT9l`oWA{KD87yd{DVSx;nKoXgG6gt4Yo?uF5(4sWCWEDF2zZmXb{cRsQ9 z?6duHF+ZyF4ws{GiTEP#W;So@wOfuCD^5Ce2p!TKB7^)^?>m@Om0#~JsF4S0MyK3Y z5^#4lm}y@5ujqi0!?_}>ZEJRx4e;YR&b9di0Y-&`(+t5te7aUdOs$>ja3nlv|vaQ?q2H@{UolfE)OA8t2#bs(Qa~dAL1QT6LFi zz2mI+!K)TrmjEM{pTwi_FnLyfL&4GK%|f4;(>D&JN?!}Bul_dlVQ580K*H-LSrm^Q^Uqty5@dvY zXt5)gDB3ChK0&T~<|*ZEBlbM==yXR|k&Y}mrs5XCklXHD#8X zexGX=n0fcOyzC#>T33&SYmAHEsHig^E$;x9S_}ee~;TrX8H^2Y;dE8d35Yrfzb8ur5860|tectQi1( zBo^?cgMdl-whsbd66;3k5Lm|`J1>VoEJ;H2=`gTofJ=tKEfU907-58e83F&IMd|1` z*0lMWcYPe3m=JUy709G{M^qqR343o)g=-k-W2%rv(cNIFG1B>Juse&!P4c1L@)-j` zQmeq^ZEV9wqI|e%E;x1XqS}1usy&A}3DU!4Q~=!-QWFc{7RA)A0w_?7Iv2t%a~)47 zoLdOFbHT}+@LfDms3_rXe79^Xg3ioQ>G>}%QpBZ;M06mx;XE>tP3($cXe8NTMC6LSPSA<(}umtj$(L{{iE`j#UD4mmjsiLs= z0g5bz8x>QlOXrW`^m5RmO%pp`r4gy<$8I%8Eq_t1!Yioy?Y11 z*L8GEXh68gYP+`*0mdw%d>0_n6}~QmE6F2hc{wy-u7#c#uX1eEgu=_AnPQ`2Yy@6* z0(7SntT4vW*}!cVWAr!YidBIf523Xc&|I~fZkh# zr|UAih&f?0fVRlqnv+U%eER_6_JLJz8RrSjInobMSU*^eOe>)(a~<@C2rF^5wsI6! z2`!i>9v_F|N~jB#4FL2)4pt!L5~#{-ibsPb!KO}w0IePbdPWNk#pJf&!Ttqx^o0ZCPJiH^Elsgj zB8X5dZi{DCkfH*Kj|5IGo&w8=pox>DZuaZ$1?n)S3t91MSLY~hK@RSS@+^O&s*s2Y z2ti~Ce8-NlqjWynC$oZ@vj_s2QFHR)siE{LsG~oFs)XO?1o1BZe6y4wcI4xj#Qy;q Cll{~H delta 3772 zcmai02~bp57XAO<2Q*-V#EpGN0}Ra~Ae##+CZG_?0%Md20=5uvbVMUMVF*YfDi{&v z1*0>O!j@gIfd)+=8XXJ+!I3D8La7wcfS^fi#06yDZv<)ht=-kXy570x+uD8t`L5tvN~JciHnTtHEB`i9_wWjOEuOeF09$TO^(ww#Acz@sw~>J#Z_nP zR1fda0Pd@6vsZIy~f?)qjMND$&E*}lL}+tjFF7CpROxeDWlcQ z7`5N9{~Tt5Dk0QWDkK=(s?Tt-bPbsGJQm++!3dPZQenZk>I6(pL^5o_M98H#TQe>k z_&IAP6S2}>0%p157vRzbQ4K!9RScd_~&|heXl1yeA|a`u3oBf)1ve^`)G~YCSF!z#ZP`N=DV)v?gat=GflUgn%0Hb zF8WIZ{CQOmZrXU5SFOE;)q`dQI1c_1qF>rNnEXkK^Vzk98?3gU@fND3yPV3nl~+qi z9CV!nHEu2US?2uvkqTY|wSRlsr?Y(Oou{crng*Oje#544Z zFNSH|rdq1+_f=o_TowDLNAlBioh9jEqoK1}1Up4`=TozK?*Av3pLFKc55vZ?=9P5= zrYid4-$#wz{y9JYrl~t_)M_pl%skX4PAJx~4$at?csM@cX=R(n8VzZ(ga6e(A13r1 z8mc&1+RXF1U!xrxzq(R-^0GS}Vb6Tz`%A$$>k7SZiy!b+?VkR+ICqKVH>KUOYfzB3 z=#}5&5dOL>+vjPyYj5V1|LbU1Ncm#d6W1aizWlZ0s}I_DhmEwR{H-y|_tLg@*Y44L zXS>rq|4mFSu1!4Eef9gI$9onxNJ8t4J4AaL)?KbTYgD`>%QAiI%~8YKmuhDW7YM^` z8vhi5EuaZ5>PFU+Ia z)%dhv1TGwK<`8V8$ryP23>-LMhv%@Hrem?_1#pZx$)gw0L=)dN!I%$ebfGFD<0OuzT_0Oiub2Gm$i##kUk7mwA)Qfo6}Yio;j#kcH5D8`L@_Evt8}L@$3V7}!V8hFQtFjLsP_z#T=% zV=6cn6FFEH7Ap%_N)C#QVzh$WD_i~jO1W&ZekIen6ZaE*wgkB;4N6w>wyjuq9{F+y z#k!T8N2|GokL6*#QsmAJKFq<g>;!W5 z?%Wl*WY*gmHlw*(f*aCq_`-1z5Wq z^l+UR@trv{Bwp72{@AHOe4QpgeFcH09>6xeVDt`wIZ>Bho+9LUazR%Vu Date: Wed, 2 Aug 2023 15:12:35 +0000 Subject: [PATCH 3/3] v5.57.2 --- ghost/admin/package.json | 2 +- ghost/core/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ghost/admin/package.json b/ghost/admin/package.json index 99142de42f..2df604c1ed 100644 --- a/ghost/admin/package.json +++ b/ghost/admin/package.json @@ -1,6 +1,6 @@ { "name": "ghost-admin", - "version": "5.57.1", + "version": "5.57.2", "description": "Ember.js admin client for Ghost", "author": "Ghost Foundation", "homepage": "http://ghost.org", diff --git a/ghost/core/package.json b/ghost/core/package.json index 4642ca509a..603e905c60 100644 --- a/ghost/core/package.json +++ b/ghost/core/package.json @@ -1,6 +1,6 @@ { "name": "ghost", - "version": "5.57.1", + "version": "5.57.2", "description": "The professional publishing platform", "author": "Ghost Foundation", "homepage": "https://ghost.org",