@@ -70,7 +70,7 @@ public function startingImport($propertyId, $accountId, $viewId, $idSite, $extra
7070 'import_end_time ' => null ,
7171 'last_job_start_time ' => $ now ,
7272 'last_day_archived ' => null ,
73- 'import_range_start ' => null ,
73+ 'import_range_start ' => $ this -> getDefaultImportRangeStart ( $ idSite ) ,
7474 'import_range_end ' => null ,
7575 'extra_custom_dimensions ' => $ extraCustomDimensions ,
7676 'days_finished_since_rate_limit ' => 0 ,
@@ -81,6 +81,28 @@ public function startingImport($propertyId, $accountId, $viewId, $idSite, $extra
8181 $ this ->saveStatus ($ status );
8282 return $ status ;
8383 }
84+ /**
85+ * The oldest date there is data to import, used as the start of the import range.
86+ *
87+ * Imports run backwards, from the end date towards this one. Both finishing an import and switching over
88+ * to importing recent days compare progress against the recorded range start, so an import that never
89+ * records one can reach the oldest date and then neither finish nor move forward - it just stops making
90+ * progress. Both importers create the Matomo site from the GA property's create time immediately before
91+ * starting the import, so the site creation date is the property's first day.
92+ *
93+ * @param int $idSite
94+ * @return string|null The date as YYYY-MM-DD, or null if no creation date could be read.
95+ */
96+ private function getDefaultImportRangeStart ($ idSite )
97+ {
98+ try {
99+ return Date::factory (Site::getCreationDateFor ($ idSite ))->toString ();
100+ } catch (\Exception $ ex ) {
101+ // Best effort only - starting an import must not fail over an unreadable creation date. The import
102+ // command makes the same lookup as its own fallback, so it still knows where to stop.
103+ return null ;
104+ }
105+ }
84106 public function getImportedDateRange ($ idSite )
85107 {
86108 $ optionName = self ::IMPORTED_DATE_RANGE_PREFIX . $ idSite ;
@@ -115,7 +137,12 @@ public function dayImportFinished($idSite, Date $date, $isMainImport = \true, $s
115137 public function setImportDateRange ($ idSite , Date $ startDate = null , Date $ endDate = null )
116138 {
117139 $ status = $ this ->getImportStatus ($ idSite );
118- $ status ['import_range_start ' ] = $ startDate ? $ startDate ->toString () : '' ;
140+ // Callers that pass no start date mean "leave it as it is", not "clear it" - Controller::startImportGA4()
141+ // calls this whenever either date is given, so blanking here would drop the range start set when the
142+ // import began.
143+ if ($ startDate !== null ) {
144+ $ status ['import_range_start ' ] = $ startDate ->toString ();
145+ }
119146 $ status ['import_range_end ' ] = $ endDate ? $ endDate ->toString () : '' ;
120147 if (!empty ($ status ['import_range_start ' ]) && !empty ($ status ['import_range_end ' ]) && Date::factory ($ status ['import_range_start ' ])->isLater (Date::factory ($ status ['import_range_end ' ]))) {
121148 throw new \Exception ("The start date cannot be past the end date. " );
0 commit comments