weight = max( 0.001, ceil( round( $weight * 1000, 6 ) ) / 1000 ); $this->length = $sides[0]; $this->width = $sides[1]; $this->height = $sides[2]; } public function volume(): float { return $this->length * $this->width * $this->height; } /** Too heavy or too big for Canada Post, so it cannot be rated at all. */ public function exceedsLimits(): bool { return $this->weight > self::MAX_WEIGHT_KG || $this->length > self::MAX_SIDE_CM || $this->length + 2 * ( $this->width + $this->height ) > self::MAX_LENGTH_GIRTH_CM; } /** Identical parcels share a key, so they are rated once. */ public function key( bool $withValue ): string { $key = sprintf( '%.3f|%.1f|%.1f|%.1f', $this->weight, $this->length, $this->width, $this->height ); return $withValue ? $key . sprintf( '|%.2f', $this->value ) : $key; } /** @return array{weight: float, dimensions: array{length: float, width: float, height: float}} */ public function toApi(): array { return array( 'weight' => $this->weight, 'dimensions' => array( 'length' => $this->length, 'width' => $this->width, 'height' => $this->height, ), ); } private static function side( float $cm ): float { return max( 0.1, ceil( round( $cm * 10, 6 ) ) / 10 ); } }