HuasoFoundries /
jpgraph
| 1 | <?php |
||||||
| 2 | |||||||
| 3 | /** |
||||||
| 4 | * JPGraph v4.0.3 |
||||||
| 5 | */ |
||||||
| 6 | |||||||
| 7 | namespace Amenadiel\JpGraph\Graph; |
||||||
| 8 | |||||||
| 9 | use Amenadiel\JpGraph\Text; |
||||||
| 10 | use Amenadiel\JpGraph\Util; |
||||||
| 11 | |||||||
| 12 | /** |
||||||
| 13 | * @class GanttScale |
||||||
| 14 | * // Description: Responsible for calculating and showing |
||||||
| 15 | * // the scale in a gantt chart. This includes providing methods for |
||||||
| 16 | * // converting dates to position in the chart as well as stroking the |
||||||
| 17 | * // date headers (days, week, etc). |
||||||
| 18 | */ |
||||||
| 19 | class GanttScale |
||||||
| 20 | { |
||||||
| 21 | public $minute; |
||||||
| 22 | public $hour; |
||||||
| 23 | public $day; |
||||||
| 24 | public $week; |
||||||
| 25 | public $month; |
||||||
| 26 | public $year; |
||||||
| 27 | public $divider; |
||||||
| 28 | public $dividerh; |
||||||
| 29 | public $tableTitle; |
||||||
| 30 | public $iStartDate = -1; |
||||||
| 31 | public $iEndDate = -1; |
||||||
| 32 | // Number of gantt bar position (n.b not necessariliy the same as the number of bars) |
||||||
| 33 | // we could have on bar in position 1, and one bar in position 5 then there are two |
||||||
| 34 | // bars but the number of bar positions is 5 |
||||||
| 35 | public $actinfo; |
||||||
| 36 | public $iTopPlotMargin = 10; |
||||||
| 37 | public $iBottomPlotMargin = 15; |
||||||
| 38 | public $iVertLines = -1; |
||||||
| 39 | public $iVertHeaderSize = -1; |
||||||
| 40 | // The width of the labels (defaults to the widest of all labels) |
||||||
| 41 | private $iLabelWidth; |
||||||
| 42 | // Out image to stroke the scale to |
||||||
| 43 | private $iImg; |
||||||
| 44 | private $iTableHeaderBackgroundColor = 'white'; |
||||||
| 45 | private $iTableHeaderFrameColor = 'black'; |
||||||
| 46 | private $iTableHeaderFrameWeight = 1; |
||||||
| 47 | private $iAvailableHeight = -1; |
||||||
| 48 | private $iVertSpacing = -1; |
||||||
| 49 | private $iDateLocale; |
||||||
| 50 | private $iVertLayout = GANTT_EVEN; |
||||||
| 51 | private $iUsePlotWeekendBackground = true; |
||||||
| 52 | private $iWeekStart = 1; // Default to have weekends start on Monday |
||||||
| 53 | |||||||
| 54 | /** |
||||||
| 55 | * CONSTRUCTOR. |
||||||
| 56 | * |
||||||
| 57 | * @param mixed $aImg |
||||||
| 58 | */ |
||||||
| 59 | public function __construct($aImg) |
||||||
| 60 | { |
||||||
| 61 | $this->iImg = $aImg; |
||||||
| 62 | $this->iDateLocale = new Util\DateLocale(); |
||||||
| 63 | |||||||
| 64 | $this->minute = new HeaderProperty(); |
||||||
| 65 | $this->minute->SetIntervall(15); |
||||||
| 66 | $this->minute->SetLabelFormatString('i'); |
||||||
| 67 | $this->minute->SetFont(FF_FONT0); |
||||||
| 68 | $this->minute->grid->SetColor('gray'); |
||||||
| 69 | |||||||
| 70 | $this->hour = new HeaderProperty(); |
||||||
| 71 | $this->hour->SetFont(FF_FONT0); |
||||||
| 72 | $this->hour->SetIntervall(6); |
||||||
| 73 | $this->hour->SetStyle(HOURSTYLE_HM24); |
||||||
| 74 | $this->hour->SetLabelFormatString('H:i'); |
||||||
| 75 | $this->hour->grid->SetColor('gray'); |
||||||
| 76 | |||||||
| 77 | $this->day = new HeaderProperty(); |
||||||
| 78 | $this->day->grid->SetColor('gray'); |
||||||
| 79 | $this->day->SetLabelFormatString('l'); |
||||||
| 80 | |||||||
| 81 | $this->week = new HeaderProperty(); |
||||||
| 82 | $this->week->SetLabelFormatString('w%d'); |
||||||
| 83 | $this->week->SetFont(FF_FONT1); |
||||||
| 84 | |||||||
| 85 | $this->month = new HeaderProperty(); |
||||||
| 86 | $this->month->SetFont(FF_FONT1, FS_BOLD); |
||||||
| 87 | |||||||
| 88 | $this->year = new HeaderProperty(); |
||||||
| 89 | $this->year->SetFont(FF_FONT1, FS_BOLD); |
||||||
| 90 | |||||||
| 91 | $this->divider = new LineProperty(); |
||||||
| 92 | $this->dividerh = new LineProperty(); |
||||||
| 93 | $this->dividerh->SetWeight(2); |
||||||
| 94 | $this->divider->SetWeight(6); |
||||||
| 95 | $this->divider->SetColor('gray'); |
||||||
| 96 | $this->divider->SetStyle('fancy'); |
||||||
| 97 | |||||||
| 98 | $this->tableTitle = new Text\TextProperty(); |
||||||
| 99 | $this->tableTitle->Show(false); |
||||||
| 100 | $this->actinfo = new GanttActivityInfo(); |
||||||
| 101 | } |
||||||
| 102 | |||||||
| 103 | /** |
||||||
| 104 | * PUBLIC METHODS |
||||||
| 105 | * // Specify what headers should be visible. |
||||||
| 106 | * |
||||||
| 107 | * @param mixed $aFlg |
||||||
| 108 | */ |
||||||
| 109 | public function ShowHeaders($aFlg) |
||||||
| 110 | { |
||||||
| 111 | $this->day->Show($aFlg & GANTT_HDAY); |
||||||
| 112 | $this->week->Show($aFlg & GANTT_HWEEK); |
||||||
| 113 | $this->month->Show($aFlg & GANTT_HMONTH); |
||||||
| 114 | $this->year->Show($aFlg & GANTT_HYEAR); |
||||||
| 115 | $this->hour->Show($aFlg & GANTT_HHOUR); |
||||||
| 116 | $this->minute->Show($aFlg & GANTT_HMIN); |
||||||
| 117 | |||||||
| 118 | // Make some default settings of gridlines whihc makes sense |
||||||
| 119 | if ($aFlg & GANTT_HWEEK) { |
||||||
| 120 | $this->month->grid->Show(false); |
||||||
| 121 | $this->year->grid->Show(false); |
||||||
| 122 | } |
||||||
| 123 | if ($aFlg & GANTT_HHOUR) { |
||||||
| 124 | $this->day->grid->SetColor('black'); |
||||||
| 125 | } |
||||||
| 126 | } |
||||||
| 127 | |||||||
| 128 | // Should the weekend background stretch all the way down in the plotarea |
||||||
| 129 | public function UseWeekendBackground($aShow) |
||||||
| 130 | { |
||||||
| 131 | $this->iUsePlotWeekendBackground = $aShow; |
||||||
| 132 | } |
||||||
| 133 | |||||||
| 134 | // Have a range been specified? |
||||||
| 135 | public function IsRangeSet() |
||||||
| 136 | { |
||||||
| 137 | return $this->iStartDate != -1 && $this->iEndDate != -1; |
||||||
| 138 | } |
||||||
| 139 | |||||||
| 140 | // Should the layout be from top or even? |
||||||
| 141 | public function SetVertLayout($aLayout) |
||||||
| 142 | { |
||||||
| 143 | $this->iVertLayout = $aLayout; |
||||||
| 144 | } |
||||||
| 145 | |||||||
| 146 | // Which locale should be used? |
||||||
| 147 | public function SetDateLocale($aLocale) |
||||||
| 148 | { |
||||||
| 149 | $this->iDateLocale->Set($aLocale); |
||||||
| 150 | } |
||||||
| 151 | |||||||
| 152 | // Number of days we are showing |
||||||
| 153 | public function GetNumberOfDays() |
||||||
| 154 | { |
||||||
| 155 | return round(($this->iEndDate - $this->iStartDate) / SECPERDAY); |
||||||
| 156 | } |
||||||
| 157 | |||||||
| 158 | // The width of the actual plot area |
||||||
| 159 | public function GetPlotWidth() |
||||||
| 160 | { |
||||||
| 161 | $img = $this->iImg; |
||||||
| 162 | |||||||
| 163 | return $img->width - $img->left_margin - $img->right_margin; |
||||||
| 164 | } |
||||||
| 165 | |||||||
| 166 | // Specify the width of the titles(labels) for the activities |
||||||
| 167 | // (This is by default set to the minimum width enought for the |
||||||
| 168 | // widest title) |
||||||
| 169 | public function SetLabelWidth($aLabelWidth) |
||||||
| 170 | { |
||||||
| 171 | $this->iLabelWidth = $aLabelWidth; |
||||||
| 172 | } |
||||||
| 173 | |||||||
| 174 | // Which day should the week start? |
||||||
| 175 | // 0==Sun, 1==Monday, 2==Tuesday etc |
||||||
| 176 | public function SetWeekStart($aStartDay) |
||||||
| 177 | { |
||||||
| 178 | $this->iWeekStart = $aStartDay % 7; |
||||||
| 179 | |||||||
| 180 | //Recalculate the startday since this will change the week start |
||||||
| 181 | $this->SetRange($this->iStartDate, $this->iEndDate); |
||||||
| 182 | } |
||||||
| 183 | |||||||
| 184 | // Do we show min scale? |
||||||
| 185 | public function IsDisplayMinute() |
||||||
| 186 | { |
||||||
| 187 | return $this->minute->iShowLabels; |
||||||
| 188 | } |
||||||
| 189 | |||||||
| 190 | // Do we show day scale? |
||||||
| 191 | public function IsDisplayHour() |
||||||
| 192 | { |
||||||
| 193 | return $this->hour->iShowLabels; |
||||||
| 194 | } |
||||||
| 195 | |||||||
| 196 | // Do we show day scale? |
||||||
| 197 | public function IsDisplayDay() |
||||||
| 198 | { |
||||||
| 199 | return $this->day->iShowLabels; |
||||||
| 200 | } |
||||||
| 201 | |||||||
| 202 | // Do we show week scale? |
||||||
| 203 | public function IsDisplayWeek() |
||||||
| 204 | { |
||||||
| 205 | return $this->week->iShowLabels; |
||||||
| 206 | } |
||||||
| 207 | |||||||
| 208 | // Do we show month scale? |
||||||
| 209 | public function IsDisplayMonth() |
||||||
| 210 | { |
||||||
| 211 | return $this->month->iShowLabels; |
||||||
| 212 | } |
||||||
| 213 | |||||||
| 214 | // Do we show year scale? |
||||||
| 215 | public function IsDisplayYear() |
||||||
| 216 | { |
||||||
| 217 | return $this->year->iShowLabels; |
||||||
| 218 | } |
||||||
| 219 | |||||||
| 220 | // Specify spacing (in percent of bar height) between activity bars |
||||||
| 221 | public function SetVertSpacing($aSpacing) |
||||||
| 222 | { |
||||||
| 223 | $this->iVertSpacing = $aSpacing; |
||||||
| 224 | } |
||||||
| 225 | |||||||
| 226 | // Specify scale min and max date either as timestamp or as date strings |
||||||
| 227 | // Always round to the nearest week boundary |
||||||
| 228 | public function SetRange($aMin, $aMax) |
||||||
| 229 | { |
||||||
| 230 | $this->iStartDate = $this->NormalizeDate($aMin); |
||||||
| 231 | $this->iEndDate = $this->NormalizeDate($aMax); |
||||||
| 232 | } |
||||||
| 233 | |||||||
| 234 | // Adjust the start and end date so they fit to beginning/ending |
||||||
| 235 | // of the week taking the specified week start day into account. |
||||||
| 236 | public function AdjustStartEndDay() |
||||||
| 237 | { |
||||||
| 238 | if (!($this->IsDisplayYear() || $this->IsDisplayMonth() || $this->IsDisplayWeek())) { |
||||||
| 239 | // Don't adjust |
||||||
| 240 | return; |
||||||
| 241 | } |
||||||
| 242 | |||||||
| 243 | // Get day in week for start and ending date (Sun==0) |
||||||
| 244 | $ds = strftime('%w', $this->iStartDate); |
||||||
| 245 | $de = strftime('%w', $this->iEndDate); |
||||||
| 246 | |||||||
| 247 | // We want to start on iWeekStart day. But first we subtract a week |
||||||
| 248 | // if the startdate is "behind" the day the week start at. |
||||||
| 249 | // This way we ensure that the given start date is always included |
||||||
| 250 | // in the range. If we don't do this the nearest correct weekday in the week |
||||||
| 251 | // to start at might be later than the start date. |
||||||
| 252 | if ($ds < $this->iWeekStart) { |
||||||
| 253 | $d = strtotime('-7 day', $this->iStartDate); |
||||||
| 254 | } else { |
||||||
| 255 | $d = $this->iStartDate; |
||||||
| 256 | } |
||||||
| 257 | |||||||
| 258 | $adjdate = strtotime(($this->iWeekStart - $ds) . ' day', $d/*$this->iStartDate*/); |
||||||
| 259 | $this->iStartDate = $adjdate; |
||||||
| 260 | |||||||
| 261 | // We want to end on the last day of the week |
||||||
| 262 | $preferredEndDay = ($this->iWeekStart + 6) % 7; |
||||||
| 263 | if ($preferredEndDay != $de) { |
||||||
| 264 | // Solve equivalence eq: $de + x ~ $preferredDay (mod 7) |
||||||
| 265 | $adj = (7 + ($preferredEndDay - $de)) % 7; |
||||||
| 266 | $adjdate = strtotime("+${adj} day", $this->iEndDate); |
||||||
| 267 | $this->iEndDate = $adjdate; |
||||||
| 268 | } |
||||||
| 269 | } |
||||||
| 270 | |||||||
| 271 | // Specify background for the table title area (upper left corner of the table) |
||||||
| 272 | public function SetTableTitleBackground($aColor) |
||||||
| 273 | { |
||||||
| 274 | $this->iTableHeaderBackgroundColor = $aColor; |
||||||
| 275 | } |
||||||
| 276 | |||||||
| 277 | /////////////////////////////////////// |
||||||
| 278 | // PRIVATE Methods |
||||||
| 279 | |||||||
| 280 | // Determine the height of all the scale headers combined |
||||||
| 281 | public function GetHeaderHeight() |
||||||
| 282 | { |
||||||
| 283 | $img = $this->iImg; |
||||||
| 284 | $height = 1; |
||||||
| 285 | if ($this->minute->iShowLabels) { |
||||||
| 286 | $height += $this->minute->GetFontHeight($img); |
||||||
| 287 | $height += $this->minute->iTitleVertMargin; |
||||||
| 288 | } |
||||||
| 289 | if ($this->hour->iShowLabels) { |
||||||
| 290 | $height += $this->hour->GetFontHeight($img); |
||||||
| 291 | $height += $this->hour->iTitleVertMargin; |
||||||
| 292 | } |
||||||
| 293 | if ($this->day->iShowLabels) { |
||||||
| 294 | $height += $this->day->GetFontHeight($img); |
||||||
| 295 | $height += $this->day->iTitleVertMargin; |
||||||
| 296 | } |
||||||
| 297 | if ($this->week->iShowLabels) { |
||||||
| 298 | $height += $this->week->GetFontHeight($img); |
||||||
| 299 | $height += $this->week->iTitleVertMargin; |
||||||
| 300 | } |
||||||
| 301 | if ($this->month->iShowLabels) { |
||||||
| 302 | $height += $this->month->GetFontHeight($img); |
||||||
| 303 | $height += $this->month->iTitleVertMargin; |
||||||
| 304 | } |
||||||
| 305 | if ($this->year->iShowLabels) { |
||||||
| 306 | $height += $this->year->GetFontHeight($img); |
||||||
| 307 | $height += $this->year->iTitleVertMargin; |
||||||
| 308 | } |
||||||
| 309 | |||||||
| 310 | return $height; |
||||||
| 311 | } |
||||||
| 312 | |||||||
| 313 | // Get width (in pixels) for a single day |
||||||
| 314 | public function GetDayWidth() |
||||||
| 315 | { |
||||||
| 316 | return ($this->GetPlotWidth() - $this->iLabelWidth + 1) / $this->GetNumberOfDays(); |
||||||
| 317 | } |
||||||
| 318 | |||||||
| 319 | // Get width (in pixels) for a single hour |
||||||
| 320 | public function GetHourWidth() |
||||||
| 321 | { |
||||||
| 322 | return $this->GetDayWidth() / 24; |
||||||
| 323 | } |
||||||
| 324 | |||||||
| 325 | public function GetMinuteWidth() |
||||||
| 326 | { |
||||||
| 327 | return $this->GetHourWidth() / 60; |
||||||
| 328 | } |
||||||
| 329 | |||||||
| 330 | // Nuber of days in a year |
||||||
| 331 | public function GetNumDaysInYear($aYear) |
||||||
| 332 | { |
||||||
| 333 | if ($this->IsLeap($aYear)) { |
||||||
| 334 | return 366; |
||||||
| 335 | } |
||||||
| 336 | |||||||
| 337 | return 365; |
||||||
| 338 | } |
||||||
| 339 | |||||||
| 340 | // Get week number |
||||||
| 341 | public function GetWeekNbr($aDate, $aSunStart = true) |
||||||
| 342 | { |
||||||
| 343 | // We can't use the internal strftime() since it gets the weeknumber |
||||||
| 344 | // wrong since it doesn't follow ISO on all systems since this is |
||||||
| 345 | // system linrary dependent. |
||||||
| 346 | // Even worse is that this works differently if we are on a Windows |
||||||
| 347 | // or UNIX box (it even differs between UNIX boxes how strftime() |
||||||
| 348 | // is natively implemented) |
||||||
| 349 | // |
||||||
| 350 | // Credit to Nicolas Hoizey <[email protected]> for this elegant |
||||||
| 351 | // version of Week Nbr calculation. |
||||||
| 352 | |||||||
| 353 | $day = $this->NormalizeDate($aDate); |
||||||
| 354 | if ($aSunStart) { |
||||||
| 355 | $day += 60 * 60 * 24; |
||||||
| 356 | } |
||||||
| 357 | |||||||
| 358 | /** |
||||||
| 359 | * According to ISO-8601 : |
||||||
| 360 | * "Week 01 of a year is per definition the first week that has the Thursday in this year, |
||||||
| 361 | * which is equivalent to the week that contains the fourth day of January. |
||||||
| 362 | * In other words, the first week of a new year is the week that has the majority of its |
||||||
| 363 | * days in the new year.". |
||||||
| 364 | * |
||||||
| 365 | * Be carefull, with PHP, -3 % 7 = -3, instead of 4 !!! |
||||||
| 366 | * |
||||||
| 367 | * day of year = date("z", $day) + 1 |
||||||
| 368 | * offset to thursday = 3 - (date("w", $day) + 6) % 7 |
||||||
| 369 | * first thursday of year = 1 + (11 - date("w", mktime(0, 0, 0, 1, 1, date("Y", $day)))) % 7 |
||||||
| 370 | * week number = (thursday's day of year - first thursday's day of year) / 7 + 1 |
||||||
| 371 | * ---------------------------------------------------------------------------*/ |
||||||
| 372 | $thursday = $day + 60 * 60 * 24 * (3 - (date('w', $day) + 6) % 7); // take week's thursday |
||||||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||||
| 373 | $week = 1 + (date('z', $thursday) - (11 - date('w', mktime(0, 0, 0, 1, 1, date('Y', $thursday)))) % 7) / 7; |
||||||
|
0 ignored issues
–
show
date('Y', $thursday) of type string is incompatible with the type integer expected by parameter $year of mktime().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
$thursday of type double is incompatible with the type integer|null expected by parameter $timestamp of date().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 374 | |||||||
| 375 | return $week; |
||||||
| 376 | } |
||||||
| 377 | |||||||
| 378 | // Is year a leap year? |
||||||
| 379 | public function IsLeap($aYear) |
||||||
| 380 | { |
||||||
| 381 | // Is the year a leap year? |
||||||
| 382 | //$year = 0+date("Y",$aDate); |
||||||
| 383 | if ($aYear % 4 == 0) { |
||||||
| 384 | if (!($aYear % 100 == 0) || ($aYear % 400 == 0)) { |
||||||
| 385 | return true; |
||||||
| 386 | } |
||||||
| 387 | } |
||||||
| 388 | |||||||
| 389 | return false; |
||||||
| 390 | } |
||||||
| 391 | |||||||
| 392 | // Get current year |
||||||
| 393 | public function GetYear($aDate) |
||||||
| 394 | { |
||||||
| 395 | return 0 + date('Y', $aDate); |
||||||
| 396 | } |
||||||
| 397 | |||||||
| 398 | // Return number of days in a year |
||||||
| 399 | public function GetNumDaysInMonth($aMonth, $aYear) |
||||||
| 400 | { |
||||||
| 401 | $days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; |
||||||
| 402 | $daysl = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; |
||||||
| 403 | if ($this->IsLeap($aYear)) { |
||||||
| 404 | return $daysl[$aMonth]; |
||||||
| 405 | } |
||||||
| 406 | |||||||
| 407 | return $days[$aMonth]; |
||||||
| 408 | } |
||||||
| 409 | |||||||
| 410 | // Get day in month |
||||||
| 411 | public function GetMonthDayNbr($aDate) |
||||||
| 412 | { |
||||||
| 413 | return 0 + strftime('%d', $aDate); |
||||||
| 414 | } |
||||||
| 415 | |||||||
| 416 | // Get day in year |
||||||
| 417 | public function GetYearDayNbr($aDate) |
||||||
| 418 | { |
||||||
| 419 | return 0 + strftime('%j', $aDate); |
||||||
| 420 | } |
||||||
| 421 | |||||||
| 422 | // Get month number |
||||||
| 423 | public function GetMonthNbr($aDate) |
||||||
| 424 | { |
||||||
| 425 | return 0 + strftime('%m', $aDate); |
||||||
| 426 | } |
||||||
| 427 | |||||||
| 428 | // Translate a date to screen coordinates (horizontal scale) |
||||||
| 429 | public function TranslateDate($aDate) |
||||||
| 430 | { |
||||||
| 431 | // |
||||||
| 432 | // In order to handle the problem with Daylight savings time |
||||||
| 433 | // the scale written with equal number of seconds per day beginning |
||||||
| 434 | // with the start date. This means that we "cement" the state of |
||||||
| 435 | // DST as it is in the start date. If later the scale includes the |
||||||
| 436 | // switchover date (depends on the locale) we need to adjust back |
||||||
| 437 | // if the date we try to translate has a different DST status since |
||||||
| 438 | // we would otherwise be off by one hour. |
||||||
| 439 | $aDate = $this->NormalizeDate($aDate); |
||||||
| 440 | $tmp = localtime($aDate); |
||||||
|
0 ignored issues
–
show
It seems like
$aDate can also be of type double and false; however, parameter $timestamp of localtime() does only seem to accept integer|null, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 441 | $cloc = $tmp[8]; |
||||||
| 442 | $tmp = localtime($this->iStartDate); |
||||||
| 443 | $sloc = $tmp[8]; |
||||||
| 444 | $offset = 0; |
||||||
| 445 | if ($sloc != $cloc) { |
||||||
| 446 | if ($sloc) { |
||||||
| 447 | $offset = 3600; |
||||||
| 448 | } else { |
||||||
| 449 | $offset = -3600; |
||||||
| 450 | } |
||||||
| 451 | } |
||||||
| 452 | $img = $this->iImg; |
||||||
| 453 | |||||||
| 454 | return ($aDate - $this->iStartDate - $offset) / SECPERDAY * $this->GetDayWidth() + $img->left_margin + $this->iLabelWidth; |
||||||
| 455 | } |
||||||
| 456 | |||||||
| 457 | // Get screen coordinatesz for the vertical position for a bar |
||||||
| 458 | public function TranslateVertPos($aPos, $atTop = false) |
||||||
| 459 | { |
||||||
| 460 | $img = $this->iImg; |
||||||
| 461 | if ($aPos > $this->iVertLines) { |
||||||
| 462 | Util\JpGraphError::RaiseL(6015, $aPos); |
||||||
| 463 | } |
||||||
| 464 | |||||||
| 465 | // 'Illegal vertical position %d' |
||||||
| 466 | if ($this->iVertLayout == GANTT_EVEN) { |
||||||
| 467 | // Position the top bar at 1 vert spacing from the scale |
||||||
| 468 | $pos = round($img->top_margin + $this->iVertHeaderSize + ($aPos + 1) * $this->iVertSpacing); |
||||||
| 469 | } else { |
||||||
| 470 | // position the top bar at 1/2 a vert spacing from the scale |
||||||
| 471 | $pos = round($img->top_margin + $this->iVertHeaderSize + $this->iTopPlotMargin + ($aPos + 1) * $this->iVertSpacing); |
||||||
| 472 | } |
||||||
| 473 | |||||||
| 474 | if ($atTop) { |
||||||
| 475 | $pos -= $this->iVertSpacing; |
||||||
| 476 | } |
||||||
| 477 | |||||||
| 478 | return $pos; |
||||||
| 479 | } |
||||||
| 480 | |||||||
| 481 | // What is the vertical spacing? |
||||||
| 482 | public function GetVertSpacing() |
||||||
| 483 | { |
||||||
| 484 | return $this->iVertSpacing; |
||||||
| 485 | } |
||||||
| 486 | |||||||
| 487 | // Convert a date to timestamp |
||||||
| 488 | public function NormalizeDate($aDate) |
||||||
| 489 | { |
||||||
| 490 | if ($aDate === false) { |
||||||
| 491 | return false; |
||||||
| 492 | } |
||||||
| 493 | |||||||
| 494 | if (is_string($aDate)) { |
||||||
| 495 | $t = strtotime($aDate); |
||||||
| 496 | if ($t === false || $t === -1) { |
||||||
| 497 | Util\JpGraphError::RaiseL(6016, $aDate); |
||||||
| 498 | //("Date string ($aDate) specified for Gantt activity can not be interpretated. Please make sure it is a valid time string, e.g. 2005-04-23 13:30"); |
||||||
| 499 | } |
||||||
| 500 | |||||||
| 501 | return $t; |
||||||
| 502 | } |
||||||
| 503 | if (is_int($aDate) || is_float($aDate)) { |
||||||
| 504 | return $aDate; |
||||||
| 505 | } |
||||||
| 506 | Util\JpGraphError::RaiseL(6017, $aDate); |
||||||
| 507 | |||||||
| 508 | //Unknown date format in GanttScale ($aDate)."); |
||||||
| 509 | } |
||||||
| 510 | |||||||
| 511 | // Convert a time string to minutes |
||||||
| 512 | |||||||
| 513 | public function TimeToMinutes($aTimeString) |
||||||
| 514 | { |
||||||
| 515 | // Split in hours and minutes |
||||||
| 516 | $pos = strpos($aTimeString, ':'); |
||||||
| 517 | $minint = 60; |
||||||
| 518 | if ($pos === false) { |
||||||
| 519 | $hourint = $aTimeString; |
||||||
| 520 | $minint = 0; |
||||||
| 521 | } else { |
||||||
| 522 | $hourint = floor(substr($aTimeString, 0, $pos)); |
||||||
|
0 ignored issues
–
show
substr($aTimeString, 0, $pos) of type string is incompatible with the type double|integer expected by parameter $num of floor().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 523 | $minint = floor(substr($aTimeString, $pos + 1)); |
||||||
| 524 | } |
||||||
| 525 | $minint += 60 * $hourint; |
||||||
| 526 | |||||||
| 527 | return $minint; |
||||||
| 528 | } |
||||||
| 529 | |||||||
| 530 | // Stroke the day scale (including gridlines) |
||||||
| 531 | public function StrokeMinutes($aYCoord, $getHeight = false) |
||||||
| 532 | { |
||||||
| 533 | $img = $this->iImg; |
||||||
| 534 | $xt = $img->left_margin + $this->iLabelWidth; |
||||||
| 535 | $yt = $aYCoord + $img->top_margin; |
||||||
| 536 | if ($this->minute->iShowLabels) { |
||||||
| 537 | $img->SetFont($this->minute->iFFamily, $this->minute->iFStyle, $this->minute->iFSize); |
||||||
| 538 | $yb = $yt + $img->GetFontHeight() + |
||||||
| 539 | $this->minute->iTitleVertMargin + $this->minute->iFrameWeight; |
||||||
| 540 | if ($getHeight) { |
||||||
| 541 | return $yb - $img->top_margin; |
||||||
| 542 | } |
||||||
| 543 | $xb = $img->width - $img->right_margin + 1; |
||||||
| 544 | $img->SetColor($this->minute->iBackgroundColor); |
||||||
| 545 | $img->FilledRectangle($xt, $yt, $xb, $yb); |
||||||
| 546 | |||||||
| 547 | $x = $xt; |
||||||
| 548 | $img->SetTextAlign('center'); |
||||||
| 549 | $day = date('w', $this->iStartDate); |
||||||
| 550 | $minint = $this->minute->GetIntervall(); |
||||||
| 551 | |||||||
| 552 | if (60 % $minint !== 0) { |
||||||
| 553 | Util\JpGraphError::RaiseL(6018, $minint); |
||||||
| 554 | //'Intervall for minutes must divide the hour evenly, e.g. 1,5,10,12,15,20,30 etc You have specified an intervall of '.$minint.' minutes.'); |
||||||
| 555 | } |
||||||
| 556 | |||||||
| 557 | $n = 60 / $minint; |
||||||
| 558 | $datestamp = $this->iStartDate; |
||||||
| 559 | $width = $this->GetHourWidth() / $n; |
||||||
| 560 | if ($width < 8) { |
||||||
| 561 | // TO small width to draw minute scale |
||||||
| 562 | Util\JpGraphError::RaiseL(6019, $width); |
||||||
| 563 | //('The available width ('.$width.') for minutes are to small for this scale to be displayed. Please use auto-sizing or increase the width of the graph.'); |
||||||
| 564 | } |
||||||
| 565 | |||||||
| 566 | $nh = ceil(24 * 60 / $this->TimeToMinutes($this->hour->GetIntervall())); |
||||||
| 567 | $nd = $this->GetNumberOfDays(); |
||||||
| 568 | // Convert to intervall to seconds |
||||||
| 569 | $minint *= 60; |
||||||
| 570 | for ($j = 0; $j < $nd; ++$j, ++$day, $day %= 7) { |
||||||
| 571 | for ($k = 0; $k < $nh; ++$k) { |
||||||
| 572 | for ($i = 0; $i < $n; ++$i, $x += $width, $datestamp += $minint) { |
||||||
| 573 | if ($day == 6 || $day == 0) { |
||||||
| 574 | $img->PushColor($this->day->iWeekendBackgroundColor); |
||||||
| 575 | if ($this->iUsePlotWeekendBackground) { |
||||||
| 576 | $img->FilledRectangle($x, $yt + $this->day->iFrameWeight, $x + $width, $img->height - $img->bottom_margin); |
||||||
| 577 | } else { |
||||||
| 578 | $img->FilledRectangle($x, $yt + $this->day->iFrameWeight, $x + $width, $yb - $this->day->iFrameWeight); |
||||||
| 579 | } |
||||||
| 580 | |||||||
| 581 | $img->PopColor(); |
||||||
| 582 | } |
||||||
| 583 | |||||||
| 584 | if ($day == 0) { |
||||||
| 585 | $img->SetColor($this->day->iSundayTextColor); |
||||||
| 586 | } else { |
||||||
| 587 | $img->SetColor($this->day->iTextColor); |
||||||
| 588 | } |
||||||
| 589 | |||||||
| 590 | switch ($this->minute->iStyle) { |
||||||
| 591 | case MINUTESTYLE_CUSTOM: |
||||||
| 592 | $txt = date($this->minute->iLabelFormStr, $datestamp); |
||||||
| 593 | |||||||
| 594 | break; |
||||||
| 595 | case MINUTESTYLE_MM: |
||||||
| 596 | default: |
||||||
| 597 | // 15 |
||||||
| 598 | $txt = date('i', $datestamp); |
||||||
| 599 | |||||||
| 600 | break; |
||||||
| 601 | } |
||||||
| 602 | $img->StrokeText(round($x + $width / 2), round($yb - $this->minute->iTitleVertMargin), $txt); |
||||||
| 603 | |||||||
| 604 | // Fix a rounding problem the wrong way .. |
||||||
| 605 | // If we also have hour scale then don't draw the firsta or last |
||||||
| 606 | // gridline since that will be overwritten by the hour scale gridline if such exists. |
||||||
| 607 | // However, due to the propagation of rounding of the 'x+=width' term in the loop |
||||||
| 608 | // this might sometimes be one pixel of so we fix this by not drawing it. |
||||||
| 609 | // The proper way to fix it would be to re-calculate the scale for each step and |
||||||
| 610 | // not using the additive term. |
||||||
| 611 | if (!(($i == $n || $i == 0) && $this->hour->iShowLabels && $this->hour->grid->iShow)) { |
||||||
| 612 | $img->SetColor($this->minute->grid->iColor); |
||||||
| 613 | $img->SetLineWeight($this->minute->grid->iWeight); |
||||||
| 614 | $img->Line($x, $yt, $x, $yb); |
||||||
| 615 | $this->minute->grid->Stroke($img, $x, $yb, $x, $img->height - $img->bottom_margin); |
||||||
| 616 | } |
||||||
| 617 | } |
||||||
| 618 | } |
||||||
| 619 | } |
||||||
| 620 | $img->SetColor($this->minute->iFrameColor); |
||||||
| 621 | $img->SetLineWeight($this->minute->iFrameWeight); |
||||||
| 622 | $img->Rectangle($xt, $yt, $xb, $yb); |
||||||
| 623 | |||||||
| 624 | return $yb - $img->top_margin; |
||||||
| 625 | } |
||||||
| 626 | |||||||
| 627 | return $aYCoord; |
||||||
| 628 | } |
||||||
| 629 | |||||||
| 630 | // Stroke the day scale (including gridlines) |
||||||
| 631 | public function StrokeHours($aYCoord, $getHeight = false) |
||||||
| 632 | { |
||||||
| 633 | $img = $this->iImg; |
||||||
| 634 | $xt = $img->left_margin + $this->iLabelWidth; |
||||||
| 635 | $yt = $aYCoord + $img->top_margin; |
||||||
| 636 | if ($this->hour->iShowLabels) { |
||||||
| 637 | $img->SetFont($this->hour->iFFamily, $this->hour->iFStyle, $this->hour->iFSize); |
||||||
| 638 | $yb = $yt + $img->GetFontHeight() + |
||||||
| 639 | $this->hour->iTitleVertMargin + $this->hour->iFrameWeight; |
||||||
| 640 | if ($getHeight) { |
||||||
| 641 | return $yb - $img->top_margin; |
||||||
| 642 | } |
||||||
| 643 | $xb = $img->width - $img->right_margin + 1; |
||||||
| 644 | $img->SetColor($this->hour->iBackgroundColor); |
||||||
| 645 | $img->FilledRectangle($xt, $yt, $xb, $yb); |
||||||
| 646 | |||||||
| 647 | $x = $xt; |
||||||
| 648 | $img->SetTextAlign('center'); |
||||||
| 649 | $tmp = $this->hour->GetIntervall(); |
||||||
| 650 | $minint = $this->TimeToMinutes($tmp); |
||||||
| 651 | if (1440 % $minint !== 0) { |
||||||
| 652 | Util\JpGraphError::RaiseL(6020, $tmp); |
||||||
| 653 | //('Intervall for hours must divide the day evenly, e.g. 0:30, 1:00, 1:30, 4:00 etc. You have specified an intervall of '.$tmp); |
||||||
| 654 | } |
||||||
| 655 | |||||||
| 656 | $n = ceil(24 * 60 / $minint); |
||||||
| 657 | $datestamp = $this->iStartDate; |
||||||
| 658 | $day = date('w', $this->iStartDate); |
||||||
| 659 | $doback = !$this->minute->iShowLabels; |
||||||
| 660 | $width = $this->GetDayWidth() / $n; |
||||||
| 661 | for ($j = 0; $j < $this->GetNumberOfDays(); ++$j, ++$day, $day %= 7) { |
||||||
| 662 | for ($i = 0; $i < $n; ++$i, $x += $width) { |
||||||
| 663 | if ($day == 6 || $day == 0) { |
||||||
| 664 | $img->PushColor($this->day->iWeekendBackgroundColor); |
||||||
| 665 | if ($this->iUsePlotWeekendBackground && $doback) { |
||||||
| 666 | $img->FilledRectangle($x, $yt + $this->day->iFrameWeight, $x + $width, $img->height - $img->bottom_margin); |
||||||
| 667 | } else { |
||||||
| 668 | $img->FilledRectangle($x, $yt + $this->day->iFrameWeight, $x + $width, $yb - $this->day->iFrameWeight); |
||||||
| 669 | } |
||||||
| 670 | |||||||
| 671 | $img->PopColor(); |
||||||
| 672 | } |
||||||
| 673 | |||||||
| 674 | if ($day == 0) { |
||||||
| 675 | $img->SetColor($this->day->iSundayTextColor); |
||||||
| 676 | } else { |
||||||
| 677 | $img->SetColor($this->day->iTextColor); |
||||||
| 678 | } |
||||||
| 679 | |||||||
| 680 | switch ($this->hour->iStyle) { |
||||||
| 681 | case HOURSTYLE_HMAMPM: |
||||||
| 682 | // 1:35pm |
||||||
| 683 | $txt = date('g:ia', $datestamp); |
||||||
| 684 | |||||||
| 685 | break; |
||||||
| 686 | case HOURSTYLE_H24: |
||||||
| 687 | // 13 |
||||||
| 688 | $txt = date('H', $datestamp); |
||||||
| 689 | |||||||
| 690 | break; |
||||||
| 691 | case HOURSTYLE_HAMPM: |
||||||
| 692 | $txt = date('ga', $datestamp); |
||||||
| 693 | |||||||
| 694 | break; |
||||||
| 695 | case HOURSTYLE_CUSTOM: |
||||||
| 696 | $txt = date($this->hour->iLabelFormStr, $datestamp); |
||||||
| 697 | |||||||
| 698 | break; |
||||||
| 699 | case HOURSTYLE_HM24: |
||||||
| 700 | default: |
||||||
| 701 | $txt = date('H:i', $datestamp); |
||||||
| 702 | |||||||
| 703 | break; |
||||||
| 704 | } |
||||||
| 705 | $img->StrokeText(round($x + $width / 2), round($yb - $this->hour->iTitleVertMargin), $txt); |
||||||
| 706 | $img->SetColor($this->hour->grid->iColor); |
||||||
| 707 | $img->SetLineWeight($this->hour->grid->iWeight); |
||||||
| 708 | $img->Line($x, $yt, $x, $yb); |
||||||
| 709 | $this->hour->grid->Stroke($img, $x, $yb, $x, $img->height - $img->bottom_margin); |
||||||
| 710 | //$datestamp += $minint*60 |
||||||
| 711 | $datestamp = mktime( |
||||||
| 712 | date('H', $datestamp), |
||||||
|
0 ignored issues
–
show
date('H', $datestamp) of type string is incompatible with the type integer expected by parameter $hour of mktime().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 713 | date('i', $datestamp) + $minint, |
||||||
|
0 ignored issues
–
show
date('i', $datestamp) + $minint of type double is incompatible with the type integer expected by parameter $minute of mktime().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 714 | 0, |
||||||
| 715 | date('m', $datestamp), |
||||||
|
0 ignored issues
–
show
date('m', $datestamp) of type string is incompatible with the type integer expected by parameter $month of mktime().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 716 | date('d', $datestamp) + 1, |
||||||
| 717 | date('Y', $datestamp) |
||||||
|
0 ignored issues
–
show
date('Y', $datestamp) of type string is incompatible with the type integer expected by parameter $year of mktime().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 718 | ); |
||||||
| 719 | } |
||||||
| 720 | } |
||||||
| 721 | $img->SetColor($this->hour->iFrameColor); |
||||||
| 722 | $img->SetLineWeight($this->hour->iFrameWeight); |
||||||
| 723 | $img->Rectangle($xt, $yt, $xb, $yb); |
||||||
| 724 | |||||||
| 725 | return $yb - $img->top_margin; |
||||||
| 726 | } |
||||||
| 727 | |||||||
| 728 | return $aYCoord; |
||||||
| 729 | } |
||||||
| 730 | |||||||
| 731 | // Stroke the day scale (including gridlines) |
||||||
| 732 | public function StrokeDays($aYCoord, $getHeight = false) |
||||||
| 733 | { |
||||||
| 734 | $img = $this->iImg; |
||||||
| 735 | $daywidth = $this->GetDayWidth(); |
||||||
| 736 | $xt = $img->left_margin + $this->iLabelWidth; |
||||||
| 737 | $yt = $aYCoord + $img->top_margin; |
||||||
| 738 | if ($this->day->iShowLabels) { |
||||||
| 739 | $img->SetFont($this->day->iFFamily, $this->day->iFStyle, $this->day->iFSize); |
||||||
| 740 | $yb = $yt + $img->GetFontHeight() + $this->day->iTitleVertMargin + $this->day->iFrameWeight; |
||||||
| 741 | if ($getHeight) { |
||||||
| 742 | return $yb - $img->top_margin; |
||||||
| 743 | } |
||||||
| 744 | $xb = $img->width - $img->right_margin + 1; |
||||||
| 745 | $img->SetColor($this->day->iBackgroundColor); |
||||||
| 746 | $img->FilledRectangle($xt, $yt, $xb, $yb); |
||||||
| 747 | |||||||
| 748 | $x = $xt; |
||||||
| 749 | $img->SetTextAlign('center'); |
||||||
| 750 | $day = date('w', $this->iStartDate); |
||||||
| 751 | $datestamp = $this->iStartDate; |
||||||
| 752 | |||||||
| 753 | $doback = !($this->hour->iShowLabels || $this->minute->iShowLabels); |
||||||
| 754 | |||||||
| 755 | setlocale(LC_TIME, $this->iDateLocale->iLocale); |
||||||
| 756 | |||||||
| 757 | for ($i = 0; $i < $this->GetNumberOfDays(); ++$i, $x += $daywidth, ++$day, $day %= 7) { |
||||||
| 758 | if ($day == 6 || $day == 0) { |
||||||
| 759 | $img->SetColor($this->day->iWeekendBackgroundColor); |
||||||
| 760 | if ($this->iUsePlotWeekendBackground && $doback) { |
||||||
| 761 | $img->FilledRectangle( |
||||||
| 762 | $x, |
||||||
| 763 | $yt + $this->day->iFrameWeight, |
||||||
| 764 | $x + $daywidth, |
||||||
| 765 | $img->height - $img->bottom_margin |
||||||
| 766 | ); |
||||||
| 767 | } else { |
||||||
| 768 | $img->FilledRectangle( |
||||||
| 769 | $x, |
||||||
| 770 | $yt + $this->day->iFrameWeight, |
||||||
| 771 | $x + $daywidth, |
||||||
| 772 | $yb - $this->day->iFrameWeight |
||||||
| 773 | ); |
||||||
| 774 | } |
||||||
| 775 | } |
||||||
| 776 | |||||||
| 777 | $mn = strftime('%m', $datestamp); |
||||||
| 778 | if ($mn[0] == '0') { |
||||||
| 779 | $mn = $mn[1]; |
||||||
| 780 | } |
||||||
| 781 | |||||||
| 782 | switch ($this->day->iStyle) { |
||||||
| 783 | case DAYSTYLE_LONG: |
||||||
| 784 | // "Monday" |
||||||
| 785 | $txt = strftime('%A', $datestamp); |
||||||
| 786 | |||||||
| 787 | break; |
||||||
| 788 | case DAYSTYLE_SHORT: |
||||||
| 789 | // "Mon" |
||||||
| 790 | $txt = strftime('%a', $datestamp); |
||||||
| 791 | |||||||
| 792 | break; |
||||||
| 793 | case DAYSTYLE_SHORTDAYDATE1: |
||||||
| 794 | // "Mon 23/6" |
||||||
| 795 | $txt = strftime('%a %d/' . $mn, $datestamp); |
||||||
| 796 | |||||||
| 797 | break; |
||||||
| 798 | case DAYSTYLE_SHORTDAYDATE2: |
||||||
| 799 | // "Mon 23 Jun" |
||||||
| 800 | $txt = strftime('%a %d %b', $datestamp); |
||||||
| 801 | |||||||
| 802 | break; |
||||||
| 803 | case DAYSTYLE_SHORTDAYDATE3: |
||||||
| 804 | // "Mon 23 Jun 2003" |
||||||
| 805 | $txt = strftime('%a %d %b %Y', $datestamp); |
||||||
| 806 | |||||||
| 807 | break; |
||||||
| 808 | case DAYSTYLE_LONGDAYDATE1: |
||||||
| 809 | // "Monday 23 Jun" |
||||||
| 810 | $txt = strftime('%A %d %b', $datestamp); |
||||||
| 811 | |||||||
| 812 | break; |
||||||
| 813 | case DAYSTYLE_LONGDAYDATE2: |
||||||
| 814 | // "Monday 23 Jun 2003" |
||||||
| 815 | $txt = strftime('%A %d %b %Y', $datestamp); |
||||||
| 816 | |||||||
| 817 | break; |
||||||
| 818 | case DAYSTYLE_SHORTDATE1: |
||||||
| 819 | // "23/6" |
||||||
| 820 | $txt = strftime('%d/' . $mn, $datestamp); |
||||||
| 821 | |||||||
| 822 | break; |
||||||
| 823 | case DAYSTYLE_SHORTDATE2: |
||||||
| 824 | // "23 Jun" |
||||||
| 825 | $txt = strftime('%d %b', $datestamp); |
||||||
| 826 | |||||||
| 827 | break; |
||||||
| 828 | case DAYSTYLE_SHORTDATE3: |
||||||
| 829 | // "Mon 23" |
||||||
| 830 | $txt = strftime('%a %d', $datestamp); |
||||||
| 831 | |||||||
| 832 | break; |
||||||
| 833 | case DAYSTYLE_SHORTDATE4: |
||||||
| 834 | // "23" |
||||||
| 835 | $txt = strftime('%d', $datestamp); |
||||||
| 836 | |||||||
| 837 | break; |
||||||
| 838 | case DAYSTYLE_CUSTOM: |
||||||
| 839 | // Custom format |
||||||
| 840 | $txt = strftime($this->day->iLabelFormStr, $datestamp); |
||||||
| 841 | |||||||
| 842 | break; |
||||||
| 843 | case DAYSTYLE_ONELETTER: |
||||||
| 844 | default: |
||||||
| 845 | // "M" |
||||||
| 846 | $txt = strftime('%A', $datestamp); |
||||||
| 847 | $txt = strtoupper($txt[0]); |
||||||
| 848 | |||||||
| 849 | break; |
||||||
| 850 | } |
||||||
| 851 | |||||||
| 852 | if ($day == 0) { |
||||||
| 853 | $img->SetColor($this->day->iSundayTextColor); |
||||||
| 854 | } else { |
||||||
| 855 | $img->SetColor($this->day->iTextColor); |
||||||
| 856 | } |
||||||
| 857 | |||||||
| 858 | $img->StrokeText( |
||||||
| 859 | round($x + $daywidth / 2 + 1), |
||||||
| 860 | round($yb - $this->day->iTitleVertMargin), |
||||||
| 861 | $txt |
||||||
| 862 | ); |
||||||
| 863 | $img->SetColor($this->day->grid->iColor); |
||||||
| 864 | $img->SetLineWeight($this->day->grid->iWeight); |
||||||
| 865 | $img->Line($x, $yt, $x, $yb); |
||||||
| 866 | $this->day->grid->Stroke($img, $x, $yb, $x, $img->height - $img->bottom_margin); |
||||||
| 867 | $datestamp = mktime(0, 0, 0, date('m', $datestamp), date('d', $datestamp) + 1, date('Y', $datestamp)); |
||||||
|
0 ignored issues
–
show
date('Y', $datestamp) of type string is incompatible with the type integer expected by parameter $year of mktime().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
date('m', $datestamp) of type string is incompatible with the type integer expected by parameter $month of mktime().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 868 | //$datestamp += SECPERDAY; |
||||||
| 869 | } |
||||||
| 870 | $img->SetColor($this->day->iFrameColor); |
||||||
| 871 | $img->SetLineWeight($this->day->iFrameWeight); |
||||||
| 872 | $img->Rectangle($xt, $yt, $xb, $yb); |
||||||
| 873 | |||||||
| 874 | return $yb - $img->top_margin; |
||||||
| 875 | } |
||||||
| 876 | |||||||
| 877 | return $aYCoord; |
||||||
| 878 | } |
||||||
| 879 | |||||||
| 880 | // Stroke week header and grid |
||||||
| 881 | public function StrokeWeeks($aYCoord, $getHeight = false) |
||||||
| 882 | { |
||||||
| 883 | if ($this->week->iShowLabels) { |
||||||
| 884 | $img = $this->iImg; |
||||||
| 885 | $yt = $aYCoord + $img->top_margin; |
||||||
| 886 | $img->SetFont($this->week->iFFamily, $this->week->iFStyle, $this->week->iFSize); |
||||||
| 887 | $yb = $yt + $img->GetFontHeight() + $this->week->iTitleVertMargin + $this->week->iFrameWeight; |
||||||
| 888 | |||||||
| 889 | if ($getHeight) { |
||||||
| 890 | return $yb - $img->top_margin; |
||||||
| 891 | } |
||||||
| 892 | |||||||
| 893 | $xt = $img->left_margin + $this->iLabelWidth; |
||||||
| 894 | $weekwidth = $this->GetDayWidth() * 7; |
||||||
| 895 | $wdays = $this->iDateLocale->GetDayAbb(); |
||||||
|
0 ignored issues
–
show
|
|||||||
| 896 | $xb = $img->width - $img->right_margin + 1; |
||||||
| 897 | $week = $this->iStartDate; |
||||||
| 898 | $weeknbr = $this->GetWeekNbr($week); |
||||||
| 899 | $img->SetColor($this->week->iBackgroundColor); |
||||||
| 900 | $img->FilledRectangle($xt, $yt, $xb, $yb); |
||||||
| 901 | $img->SetColor($this->week->grid->iColor); |
||||||
| 902 | $x = $xt; |
||||||
| 903 | if ($this->week->iStyle == WEEKSTYLE_WNBR) { |
||||||
| 904 | $img->SetTextAlign('center'); |
||||||
| 905 | $txtOffset = $weekwidth / 2 + 1; |
||||||
| 906 | } elseif ($this->week->iStyle == WEEKSTYLE_FIRSTDAY || |
||||||
| 907 | $this->week->iStyle == WEEKSTYLE_FIRSTDAY2 || |
||||||
| 908 | $this->week->iStyle == WEEKSTYLE_FIRSTDAYWNBR || |
||||||
| 909 | $this->week->iStyle == WEEKSTYLE_FIRSTDAY2WNBR) { |
||||||
| 910 | $img->SetTextAlign('left'); |
||||||
| 911 | $txtOffset = 3; |
||||||
| 912 | } else { |
||||||
| 913 | Util\JpGraphError::RaiseL(6021); |
||||||
| 914 | //("Unknown formatting style for week."); |
||||||
| 915 | } |
||||||
| 916 | |||||||
| 917 | for ($i = 0; $i < $this->GetNumberOfDays() / 7; ++$i, $x += $weekwidth) { |
||||||
| 918 | $img->PushColor($this->week->iTextColor); |
||||||
| 919 | |||||||
| 920 | if ($this->week->iStyle == WEEKSTYLE_WNBR) { |
||||||
| 921 | $txt = sprintf($this->week->iLabelFormStr, $weeknbr); |
||||||
| 922 | } elseif ($this->week->iStyle == WEEKSTYLE_FIRSTDAY || |
||||||
| 923 | $this->week->iStyle == WEEKSTYLE_FIRSTDAYWNBR) { |
||||||
| 924 | $txt = date('j/n', $week); |
||||||
| 925 | } elseif ($this->week->iStyle == WEEKSTYLE_FIRSTDAY2 || |
||||||
| 926 | $this->week->iStyle == WEEKSTYLE_FIRSTDAY2WNBR) { |
||||||
| 927 | $monthnbr = date('n', $week) - 1; |
||||||
| 928 | $shortmonth = $this->iDateLocale->GetShortMonthName($monthnbr); |
||||||
| 929 | $txt = date('j', $week) . ' ' . $shortmonth; |
||||||
| 930 | } |
||||||
| 931 | |||||||
| 932 | if ($this->week->iStyle == WEEKSTYLE_FIRSTDAYWNBR || |
||||||
| 933 | $this->week->iStyle == WEEKSTYLE_FIRSTDAY2WNBR) { |
||||||
| 934 | $w = sprintf($this->week->iLabelFormStr, $weeknbr); |
||||||
| 935 | $txt .= ' ' . $w; |
||||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
| 936 | } |
||||||
| 937 | |||||||
| 938 | $img->StrokeText( |
||||||
| 939 | round($x + $txtOffset), |
||||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
| 940 | round($yb - $this->week->iTitleVertMargin), |
||||||
| 941 | $txt |
||||||
| 942 | ); |
||||||
| 943 | |||||||
| 944 | $week = strtotime('+7 day', $week); |
||||||
| 945 | $weeknbr = $this->GetWeekNbr($week); |
||||||
| 946 | $img->PopColor(); |
||||||
| 947 | $img->SetLineWeight($this->week->grid->iWeight); |
||||||
| 948 | $img->Line($x, $yt, $x, $yb); |
||||||
| 949 | $this->week->grid->Stroke($img, $x, $yb, $x, $img->height - $img->bottom_margin); |
||||||
| 950 | } |
||||||
| 951 | $img->SetColor($this->week->iFrameColor); |
||||||
| 952 | $img->SetLineWeight($this->week->iFrameWeight); |
||||||
| 953 | $img->Rectangle($xt, $yt, $xb, $yb); |
||||||
| 954 | |||||||
| 955 | return $yb - $img->top_margin; |
||||||
| 956 | } |
||||||
| 957 | |||||||
| 958 | return $aYCoord; |
||||||
| 959 | } |
||||||
| 960 | |||||||
| 961 | // Format the mont scale header string |
||||||
| 962 | public function GetMonthLabel($aMonthNbr, $year) |
||||||
| 963 | { |
||||||
| 964 | $sn = $this->iDateLocale->GetShortMonthName($aMonthNbr); |
||||||
| 965 | $ln = $this->iDateLocale->GetLongMonthName($aMonthNbr); |
||||||
| 966 | switch ($this->month->iStyle) { |
||||||
| 967 | case MONTHSTYLE_SHORTNAME: |
||||||
| 968 | $m = $sn; |
||||||
| 969 | |||||||
| 970 | break; |
||||||
| 971 | case MONTHSTYLE_LONGNAME: |
||||||
| 972 | $m = $ln; |
||||||
| 973 | |||||||
| 974 | break; |
||||||
| 975 | case MONTHSTYLE_SHORTNAMEYEAR2: |
||||||
| 976 | $m = $sn . " '" . substr('' . $year, 2); |
||||||
| 977 | |||||||
| 978 | break; |
||||||
| 979 | case MONTHSTYLE_SHORTNAMEYEAR4: |
||||||
| 980 | $m = $sn . ' ' . $year; |
||||||
| 981 | |||||||
| 982 | break; |
||||||
| 983 | case MONTHSTYLE_LONGNAMEYEAR2: |
||||||
| 984 | $m = $ln . " '" . substr('' . $year, 2); |
||||||
| 985 | |||||||
| 986 | break; |
||||||
| 987 | case MONTHSTYLE_LONGNAMEYEAR4: |
||||||
| 988 | $m = $ln . ' ' . $year; |
||||||
| 989 | |||||||
| 990 | break; |
||||||
| 991 | case MONTHSTYLE_FIRSTLETTER: |
||||||
| 992 | $m = $sn[0]; |
||||||
| 993 | |||||||
| 994 | break; |
||||||
| 995 | } |
||||||
| 996 | |||||||
| 997 | return $m; |
||||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||||
| 998 | } |
||||||
| 999 | |||||||
| 1000 | // Stroke month scale and gridlines |
||||||
| 1001 | public function StrokeMonths($aYCoord, $getHeight = false) |
||||||
| 1002 | { |
||||||
| 1003 | if ($this->month->iShowLabels) { |
||||||
| 1004 | $img = $this->iImg; |
||||||
| 1005 | $img->SetFont($this->month->iFFamily, $this->month->iFStyle, $this->month->iFSize); |
||||||
| 1006 | $yt = $aYCoord + $img->top_margin; |
||||||
| 1007 | $yb = $yt + $img->GetFontHeight() + $this->month->iTitleVertMargin + $this->month->iFrameWeight; |
||||||
| 1008 | if ($getHeight) { |
||||||
| 1009 | return $yb - $img->top_margin; |
||||||
| 1010 | } |
||||||
| 1011 | $monthnbr = $this->GetMonthNbr($this->iStartDate) - 1; |
||||||
| 1012 | $xt = $img->left_margin + $this->iLabelWidth; |
||||||
| 1013 | $xb = $img->width - $img->right_margin + 1; |
||||||
| 1014 | |||||||
| 1015 | $img->SetColor($this->month->iBackgroundColor); |
||||||
| 1016 | $img->FilledRectangle($xt, $yt, $xb, $yb); |
||||||
| 1017 | |||||||
| 1018 | $img->SetLineWeight($this->month->grid->iWeight); |
||||||
| 1019 | $img->SetColor($this->month->iTextColor); |
||||||
| 1020 | $year = 0 + strftime('%Y', $this->iStartDate); |
||||||
| 1021 | $img->SetTextAlign('center'); |
||||||
| 1022 | if ($this->GetMonthNbr($this->iStartDate) == $this->GetMonthNbr($this->iEndDate) |
||||||
| 1023 | && $this->GetYear($this->iStartDate) == $this->GetYear($this->iEndDate)) { |
||||||
| 1024 | $monthwidth = $this->GetDayWidth() * ($this->GetMonthDayNbr($this->iEndDate) - $this->GetMonthDayNbr($this->iStartDate) + 1); |
||||||
| 1025 | } else { |
||||||
| 1026 | $monthwidth = $this->GetDayWidth() * ($this->GetNumDaysInMonth($monthnbr, $year) - $this->GetMonthDayNbr($this->iStartDate) + 1); |
||||||
| 1027 | } |
||||||
| 1028 | // Is it enough space to stroke the first month? |
||||||
| 1029 | $monthName = $this->GetMonthLabel($monthnbr, $year); |
||||||
| 1030 | if ($monthwidth >= 1.2 * $img->GetTextWidth($monthName)) { |
||||||
| 1031 | $img->SetColor($this->month->iTextColor); |
||||||
| 1032 | $img->StrokeText( |
||||||
| 1033 | round($xt + $monthwidth / 2 + 1), |
||||||
| 1034 | round($yb - $this->month->iTitleVertMargin), |
||||||
| 1035 | $monthName |
||||||
| 1036 | ); |
||||||
| 1037 | } |
||||||
| 1038 | $x = $xt + $monthwidth; |
||||||
| 1039 | while ($x < $xb) { |
||||||
| 1040 | $img->SetColor($this->month->grid->iColor); |
||||||
| 1041 | $img->Line($x, $yt, $x, $yb); |
||||||
| 1042 | $this->month->grid->Stroke($img, $x, $yb, $x, $img->height - $img->bottom_margin); |
||||||
| 1043 | ++$monthnbr; |
||||||
| 1044 | if ($monthnbr == 12) { |
||||||
| 1045 | $monthnbr = 0; |
||||||
| 1046 | ++$year; |
||||||
| 1047 | } |
||||||
| 1048 | $monthName = $this->GetMonthLabel($monthnbr, $year); |
||||||
| 1049 | $monthwidth = $this->GetDayWidth() * $this->GetNumDaysInMonth($monthnbr, $year); |
||||||
| 1050 | if ($x + $monthwidth < $xb) { |
||||||
| 1051 | $w = $monthwidth; |
||||||
| 1052 | } else { |
||||||
| 1053 | $w = $xb - $x; |
||||||
| 1054 | } |
||||||
| 1055 | |||||||
| 1056 | if ($w >= 1.2 * $img->GetTextWidth($monthName)) { |
||||||
| 1057 | $img->SetColor($this->month->iTextColor); |
||||||
| 1058 | $img->StrokeText( |
||||||
| 1059 | round($x + $w / 2 + 1), |
||||||
| 1060 | round($yb - $this->month->iTitleVertMargin), |
||||||
| 1061 | $monthName |
||||||
| 1062 | ); |
||||||
| 1063 | } |
||||||
| 1064 | $x += $monthwidth; |
||||||
| 1065 | } |
||||||
| 1066 | $img->SetColor($this->month->iFrameColor); |
||||||
| 1067 | $img->SetLineWeight($this->month->iFrameWeight); |
||||||
| 1068 | $img->Rectangle($xt, $yt, $xb, $yb); |
||||||
| 1069 | |||||||
| 1070 | return $yb - $img->top_margin; |
||||||
| 1071 | } |
||||||
| 1072 | |||||||
| 1073 | return $aYCoord; |
||||||
| 1074 | } |
||||||
| 1075 | |||||||
| 1076 | // Stroke year scale and gridlines |
||||||
| 1077 | public function StrokeYears($aYCoord, $getHeight = false) |
||||||
| 1078 | { |
||||||
| 1079 | if ($this->year->iShowLabels) { |
||||||
| 1080 | $img = $this->iImg; |
||||||
| 1081 | $yt = $aYCoord + $img->top_margin; |
||||||
| 1082 | $img->SetFont($this->year->iFFamily, $this->year->iFStyle, $this->year->iFSize); |
||||||
| 1083 | $yb = $yt + $img->GetFontHeight() + $this->year->iTitleVertMargin + $this->year->iFrameWeight; |
||||||
| 1084 | |||||||
| 1085 | if ($getHeight) { |
||||||
| 1086 | return $yb - $img->top_margin; |
||||||
| 1087 | } |
||||||
| 1088 | |||||||
| 1089 | $xb = $img->width - $img->right_margin + 1; |
||||||
| 1090 | $xt = $img->left_margin + $this->iLabelWidth; |
||||||
| 1091 | $year = $this->GetYear($this->iStartDate); |
||||||
| 1092 | $img->SetColor($this->year->iBackgroundColor); |
||||||
| 1093 | $img->FilledRectangle($xt, $yt, $xb, $yb); |
||||||
| 1094 | $img->SetLineWeight($this->year->grid->iWeight); |
||||||
| 1095 | $img->SetTextAlign('center'); |
||||||
| 1096 | if ($year == $this->GetYear($this->iEndDate)) { |
||||||
| 1097 | $yearwidth = $this->GetDayWidth() * ($this->GetYearDayNbr($this->iEndDate) - $this->GetYearDayNbr($this->iStartDate) + 1); |
||||||
| 1098 | } else { |
||||||
| 1099 | $yearwidth = $this->GetDayWidth() * ($this->GetNumDaysInYear($year) - $this->GetYearDayNbr($this->iStartDate) + 1); |
||||||
| 1100 | } |
||||||
| 1101 | |||||||
| 1102 | // The space for a year must be at least 20% bigger than the actual text |
||||||
| 1103 | // so we allow 10% margin on each side |
||||||
| 1104 | if ($yearwidth >= 1.20 * $img->GetTextWidth('' . $year)) { |
||||||
| 1105 | $img->SetColor($this->year->iTextColor); |
||||||
| 1106 | $img->StrokeText( |
||||||
| 1107 | round($xt + $yearwidth / 2 + 1), |
||||||
| 1108 | round($yb - $this->year->iTitleVertMargin), |
||||||
| 1109 | $year |
||||||
| 1110 | ); |
||||||
| 1111 | } |
||||||
| 1112 | $x = $xt + $yearwidth; |
||||||
| 1113 | while ($x < $xb) { |
||||||
| 1114 | $img->SetColor($this->year->grid->iColor); |
||||||
| 1115 | $img->Line($x, $yt, $x, $yb); |
||||||
| 1116 | $this->year->grid->Stroke($img, $x, $yb, $x, $img->height - $img->bottom_margin); |
||||||
| 1117 | ++$year; |
||||||
| 1118 | $yearwidth = $this->GetDayWidth() * $this->GetNumDaysInYear($year); |
||||||
| 1119 | if ($x + $yearwidth < $xb) { |
||||||
| 1120 | $w = $yearwidth; |
||||||
| 1121 | } else { |
||||||
| 1122 | $w = $xb - $x; |
||||||
| 1123 | } |
||||||
| 1124 | |||||||
| 1125 | if ($w >= 1.2 * $img->GetTextWidth('' . $year)) { |
||||||
| 1126 | $img->SetColor($this->year->iTextColor); |
||||||
| 1127 | $img->StrokeText( |
||||||
| 1128 | round($x + $w / 2 + 1), |
||||||
| 1129 | round($yb - $this->year->iTitleVertMargin), |
||||||
| 1130 | $year |
||||||
| 1131 | ); |
||||||
| 1132 | } |
||||||
| 1133 | $x += $yearwidth; |
||||||
| 1134 | } |
||||||
| 1135 | $img->SetColor($this->year->iFrameColor); |
||||||
| 1136 | $img->SetLineWeight($this->year->iFrameWeight); |
||||||
| 1137 | $img->Rectangle($xt, $yt, $xb, $yb); |
||||||
| 1138 | |||||||
| 1139 | return $yb - $img->top_margin; |
||||||
| 1140 | } |
||||||
| 1141 | |||||||
| 1142 | return $aYCoord; |
||||||
| 1143 | } |
||||||
| 1144 | |||||||
| 1145 | // Stroke table title (upper left corner) |
||||||
| 1146 | public function StrokeTableHeaders($aYBottom) |
||||||
| 1147 | { |
||||||
| 1148 | $img = $this->iImg; |
||||||
| 1149 | $xt = $img->left_margin; |
||||||
| 1150 | $yt = $img->top_margin; |
||||||
| 1151 | $xb = $xt + $this->iLabelWidth; |
||||||
| 1152 | $yb = $aYBottom + $img->top_margin; |
||||||
| 1153 | |||||||
| 1154 | if ($this->tableTitle->iShow) { |
||||||
| 1155 | $img->SetColor($this->iTableHeaderBackgroundColor); |
||||||
| 1156 | $img->FilledRectangle($xt, $yt, $xb, $yb); |
||||||
| 1157 | $this->tableTitle->Align('center', 'top'); |
||||||
| 1158 | $this->tableTitle->Stroke($img, $xt + ($xb - $xt) / 2 + 1, $yt + 2); |
||||||
| 1159 | $img->SetColor($this->iTableHeaderFrameColor); |
||||||
| 1160 | $img->SetLineWeight($this->iTableHeaderFrameWeight); |
||||||
| 1161 | $img->Rectangle($xt, $yt, $xb, $yb); |
||||||
| 1162 | } |
||||||
| 1163 | |||||||
| 1164 | $this->actinfo->Stroke($img, $xt, $yt, $xb, $yb, $this->tableTitle->iShow); |
||||||
| 1165 | |||||||
| 1166 | // Draw the horizontal dividing line |
||||||
| 1167 | $this->dividerh->Stroke($img, $xt, $yb, $img->width - $img->right_margin, $yb); |
||||||
| 1168 | |||||||
| 1169 | // Draw the vertical dividing line |
||||||
| 1170 | // We do the width "manually" since we want the line only to grow |
||||||
| 1171 | // to the left |
||||||
| 1172 | $fancy = $this->divider->iStyle == 'fancy'; |
||||||
| 1173 | if ($fancy) { |
||||||
| 1174 | $this->divider->iStyle = 'solid'; |
||||||
| 1175 | } |
||||||
| 1176 | |||||||
| 1177 | $tmp = $this->divider->iWeight; |
||||||
| 1178 | $this->divider->iWeight = 1; |
||||||
| 1179 | $y = $img->height - $img->bottom_margin; |
||||||
| 1180 | for ($i = 0; $i < $tmp; ++$i) { |
||||||
| 1181 | $this->divider->Stroke($img, $xb - $i, $yt, $xb - $i, $y); |
||||||
| 1182 | } |
||||||
| 1183 | |||||||
| 1184 | // Should we draw "fancy" divider |
||||||
| 1185 | if ($fancy) { |
||||||
| 1186 | $img->SetLineWeight(1); |
||||||
| 1187 | $img->SetColor($this->iTableHeaderFrameColor); |
||||||
| 1188 | $img->Line($xb, $yt, $xb, $y); |
||||||
| 1189 | $img->Line($xb - $tmp + 1, $yt, $xb - $tmp + 1, $y); |
||||||
| 1190 | $img->SetColor('white'); |
||||||
| 1191 | $img->Line($xb - $tmp + 2, $yt, $xb - $tmp + 2, $y); |
||||||
| 1192 | } |
||||||
| 1193 | } |
||||||
| 1194 | |||||||
| 1195 | // Main entry point to stroke scale |
||||||
| 1196 | public function Stroke() |
||||||
| 1197 | { |
||||||
| 1198 | if (!$this->IsRangeSet()) { |
||||||
| 1199 | Util\JpGraphError::RaiseL(6022); |
||||||
| 1200 | //("Gantt scale has not been specified."); |
||||||
| 1201 | } |
||||||
| 1202 | $img = $this->iImg; |
||||||
| 1203 | |||||||
| 1204 | // If minutes are displayed then hour interval must be 1 |
||||||
| 1205 | if ($this->IsDisplayMinute() && $this->hour->GetIntervall() > 1) { |
||||||
| 1206 | Util\JpGraphError::RaiseL(6023); |
||||||
| 1207 | //('If you display both hour and minutes the hour intervall must be 1 (Otherwise it doesn\' make sense to display minutes).'); |
||||||
| 1208 | } |
||||||
| 1209 | |||||||
| 1210 | // Stroke all headers. As argument we supply the offset from the |
||||||
| 1211 | // top which depends on any previous headers |
||||||
| 1212 | |||||||
| 1213 | // First find out the height of each header |
||||||
| 1214 | $offy = $this->StrokeYears(0, true); |
||||||
| 1215 | $offm = $this->StrokeMonths($offy, true); |
||||||
| 1216 | $offw = $this->StrokeWeeks($offm, true); |
||||||
| 1217 | $offd = $this->StrokeDays($offw, true); |
||||||
| 1218 | $offh = $this->StrokeHours($offd, true); |
||||||
| 1219 | $offmin = $this->StrokeMinutes($offh, true); |
||||||
| 1220 | |||||||
| 1221 | // ... then we can stroke them in the "backwards order to ensure that |
||||||
| 1222 | // the larger scale gridlines is stroked over the smaller scale gridline |
||||||
| 1223 | $this->StrokeMinutes($offh); |
||||||
| 1224 | $this->StrokeHours($offd); |
||||||
| 1225 | $this->StrokeDays($offw); |
||||||
| 1226 | $this->StrokeWeeks($offm); |
||||||
| 1227 | $this->StrokeMonths($offy); |
||||||
| 1228 | $this->StrokeYears(0); |
||||||
| 1229 | |||||||
| 1230 | // Now when we now the oaverall size of the scale headers |
||||||
| 1231 | // we can stroke the overall table headers |
||||||
| 1232 | $this->StrokeTableHeaders($offmin); |
||||||
| 1233 | |||||||
| 1234 | // Now we can calculate the correct scaling factor for each vertical position |
||||||
| 1235 | $this->iAvailableHeight = $img->height - $img->top_margin - $img->bottom_margin - $offd; |
||||||
| 1236 | |||||||
| 1237 | $this->iVertHeaderSize = $offmin; |
||||||
| 1238 | if ($this->iVertSpacing == -1) { |
||||||
| 1239 | $this->iVertSpacing = $this->iAvailableHeight / $this->iVertLines; |
||||||
| 1240 | } |
||||||
| 1241 | } |
||||||
| 1242 | } |
||||||
| 1243 |