root/HTTP/WikiDateNavigation.lua

Revision 1368 (checked in by rsz, 6 months ago)

cleanup

Line 
1 --------------------------------------------------------------------------------
2 -- Title:               WikiDateNavigation.lua
3 -- Description:         Like a square peg in a round hole
4 -- Author:              Raphaël Szwarc http://alt.textdrive.com/lua/
5 -- Creation Date:       January 30, 2007
6 -- Legal:               Copyright (C) 2007 Raphaël Szwarc
7 --                      Under the terms of the MIT License
8 --                      http://www.opensource.org/licenses/mit-license.html
9 --------------------------------------------------------------------------------
10
11 -- import dependencies
12 local HTTPService = require( 'HTTPService' )
13 local Template = require( 'Template' )
14 local WikiDate = require( 'WikiDate' )
15 local WikiDateService = require( 'WikiDateService' )
16 local WikiService = require( 'WikiService' )
17
18 local FormatDate = WikiService.FormatDate
19
20 local os = require( 'os' )
21
22 local getmetatable = getmetatable
23 local ipairs = ipairs
24 local mod = math.mod
25 local setmetatable = setmetatable
26 local tostring = tostring
27
28 --------------------------------------------------------------------------------
29 -- WikiDateNavigation
30 --------------------------------------------------------------------------------
31
32 module( 'WikiDateNavigation' )
33 _VERSION = '1.0'
34
35 local self = setmetatable( _M, {} )
36 local meta = getmetatable( self )
37
38 --------------------------------------------------------------------------------
39 -- Utilities
40 --------------------------------------------------------------------------------
41
42 local lengths = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
43
44 local function IsLeap( aYear )
45     return ( ( mod( aYear, 4 ) == 0 ) and ( mod( aYear, 100 ) ~= 0 ) ) or ( mod( aYear, 400 ) == 0 )
46 end
47
48 local function MonthLength( aDate )
49     local aLength = lengths[ aDate.month ]
50    
51     if aDate.month == 2 and IsLeap( aDate.year ) then
52         aLength = aLength + 1
53     end
54    
55     return aLength
56 end
57
58 local function Years()
59     local thisYear = os.date( '!*t' ).year
60     local aList = {}
61
62     for aYear = thisYear - 11, thisYear do
63         aList[ #aList + 1 ] = aYear
64     end
65    
66     return aList
67 end
68
69 local function Values()
70     return
71     {
72         Years(),
73         { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 },
74         { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 },
75         { 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 },
76         { 25, 26, 27, 28, 29, 30, 31, 0, 0, 0, 0, 0 }
77     }
78 end
79
80 local function HasValue( anIterator, aValue )
81     for aLocalValue in anIterator do
82         if aLocalValue == aValue then
83             return true
84         end
85     end
86    
87     return false
88 end
89
90 local function FormatYear( aDate, aValue )
91     local aLocalDate = { year = aValue, month = 1, day = 1 }
92     local aFormat = os.date( '!\'%y', os.time( aLocalDate ) )
93     local isCurrent = aDate.year == aValue
94     local firstYear = WikiDate()() or 0
95    
96     if HasValue( WikiDate(), aValue ) then
97         aLocalDate.month = nil
98         aLocalDate.day = nil
99     else
100         aLocalDate = nil
101     end
102    
103     if aValue < firstYear then
104         aFormat = nil
105     end
106    
107     return aFormat, aLocalDate, isCurrent
108 end
109
110 local function FormatMonth( aDate, aValue )
111     local aLocalDate = { year = aDate.year, month = aValue, day = 1 }
112     local aFormat = os.date( '!%b', os.time( aLocalDate ) )
113     local isCurrent = aDate.month == aValue
114
115     if HasValue( WikiDate( { year = aDate.year } ), aValue ) then
116         aLocalDate.day = nil
117     else
118         aLocalDate = nil
119     end
120
121     return aFormat, aLocalDate, isCurrent
122 end
123
124 local function FormatDay( aDate, aValue )
125     local aLocalDate = { year = aDate.year, month = aDate.month or 1, day = aValue }
126     local aLength = MonthLength( aLocalDate )
127     local isCurrent = aDate.day == aValue
128    
129     if aValue < 1 or aValue > aLength then
130         aValue = nil
131         aLocalDate = nil
132         isCurrent = false
133     end
134    
135     if not HasValue( WikiDate( { year = aDate.year, month = aDate.month or 1 } ), aValue ) then
136         aLocalDate = nil
137     end
138    
139     return aValue, aLocalDate, isCurrent
140 end
141
142 local types = { 'year', 'month', 'day', 'day', 'day' }
143 local formats = { year = FormatYear, month = FormatMonth, day =  FormatDay }
144
145 local function Title( aYear, aMonth, aDay )
146     local aTime = os.time( { year = aYear or 1, month = aMonth or 1, day = aDay or 1 } )
147     local aFormat = nil
148    
149     if aDay then
150         return FormatDate( aTime )
151     elseif aMonth then
152         aFormat = '!%B %Y'
153     else
154         aFormat = '!%Y'
155     end
156    
157     return os.date( aFormat, aTime )
158 end
159
160 local function FormatValue( aType, aDate, aValue )
161     local aValue, aDate, isCurrent = formats[ aType ]( aDate, aValue )
162
163     if aValue and isCurrent then
164         aValue = ( '<b>%s</b>' ):format( aValue )
165     end
166    
167     if aValue and aDate then
168         local aService = WikiDateService( aDate.year, aDate.month, aDate.day )
169         local anURL = HTTPService[ aService ]
170         local aPath = tostring( anURL.path )
171         local aTitle = Title( aDate.year, aDate.month, aDate.day )
172
173         aValue = ( '<a href=\'%s\' title=\'%s\'>%s</a>' ):format( aPath, aTitle, aValue )
174     end
175        
176     return aValue or '&nbsp;'
177 end
178
179 --------------------------------------------------------------------------------
180 -- Metamethods
181 --------------------------------------------------------------------------------
182
183 function meta:__call( aDate )
184     local aNavigation = { date = aDate }
185
186     setmetatable( aNavigation, self )
187
188     return aNavigation
189 end
190
191 function meta:__concat( aValue )
192     return tostring( self ) .. tostring( aValue )
193 end
194
195 function meta:__tostring()
196     return ( '%s/%s' ):format( self._NAME, self._VERSION )
197 end
198
199 function self:__concat( aValue )
200     return tostring( self ) .. tostring( aValue )
201 end
202
203 function self:__tostring()
204     local aTemplate = Template[ 'WikiNavigation.txt' ]
205     local someValues = Values()
206     local aDate = self.date
207    
208     for aRowIndex, aRowValue in ipairs( someValues ) do
209         local aRowTemplate = aTemplate[ 'rows' ]
210         local aRowType = types[ aRowIndex ]
211        
212         for aColumnIndex, aColumnValue in ipairs( aRowValue ) do
213             local aColumnTemplate = aRowTemplate[ 'columns' ]
214            
215             aColumnTemplate[ 'value' ] = FormatValue( aRowType, aDate, aColumnValue )
216            
217             aRowTemplate[ 'columns' ] = aColumnTemplate
218         end
219
220         aTemplate[ 'rows' ] = aRowTemplate
221     end
222
223     return tostring( aTemplate )
224 end
225
226
Note: See TracBrowser for help on using the browser.