1717use App \Http \Resources \Models \ThumbAlbumResource ;
1818use Carbon \Carbon ;
1919use Illuminate \Support \Collection ;
20+ use Safe \Exceptions \PcreException ;
21+ use function Safe \preg_match ;
2022use Spatie \LaravelData \Data ;
2123use Spatie \TypeScriptTransformer \Attributes \TypeScript ;
2224
@@ -55,6 +57,38 @@ public static function fromPhoto(PhotoResource $photo, TimelinePhotoGranularity
5557 return new TimelineData (time_date: $ time_date , format: $ format );
5658 }
5759
60+ /**
61+ * Attempts to parse a date from a title string.
62+ *
63+ * @param string $title The title string to parse
64+ *
65+ * @return ?Carbon The parsed Carbon date object or null if parsing fails
66+ */
67+ private static function parseDateFromTitle (string $ title ): ?Carbon
68+ {
69+ // A title is expected to be in one of the following formats:
70+ // "YYYY something"
71+ // "YYYY-MM something"
72+ // "YYYY-MM-DD something"
73+ // We match the first part that looks like a date.
74+ // Then use Carbon to create a date object from the matched components.
75+ $ pattern = '/^(\d{4})(?:-(\d{2}))?(?:-(\d{2}))?/ ' ;
76+ try {
77+ if (preg_match ($ pattern , $ title , $ matches ) === 1 ) {
78+ $ year = intval ($ matches [1 ]);
79+ $ month = intval ($ matches [2 ] ?? 1 );
80+ $ day = intval ($ matches [3 ] ?? 1 );
81+
82+ return Carbon::createFromDate ($ year , $ month , $ day );
83+ }
84+
85+ return null ;
86+ } catch (PcreException $ e ) {
87+ // fail silently.
88+ return null ;
89+ }
90+ }
91+
5892 private static function fromAlbum (ThumbAlbumResource $ album , ColumnSortingType $ column_sorting , TimelineAlbumGranularity $ granularity ): ?self
5993 {
6094 $ timeline_date_format_year = request ()->configs ()->getValueAsString ('timeline_album_date_format_year ' );
@@ -64,6 +98,8 @@ private static function fromAlbum(ThumbAlbumResource $album, ColumnSortingType $
6498 ColumnSortingType::CREATED_AT => $ album ->created_at_carbon (),
6599 ColumnSortingType::MAX_TAKEN_AT => $ album ->max_taken_at_carbon (),
66100 ColumnSortingType::MIN_TAKEN_AT => $ album ->min_taken_at_carbon (),
101+ // Parse the title as date (e.g. "2020 something" or "2020-03 something" or "2020-03-25 something")
102+ ColumnSortingType::TITLE => self ::parseDateFromTitle ($ album ->title ),
67103 default => null ,
68104 };
69105
0 commit comments