Complex classes like StyleManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use StyleManager, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 11 | class StyleManager  | 
            ||
| 12 | { | 
            ||
| 13 | /** Nodes used to find relevant information in the styles XML file */  | 
            ||
| 14 | const XML_NODE_NUM_FMTS = 'numFmts';  | 
            ||
| 15 | const XML_NODE_NUM_FMT = 'numFmt';  | 
            ||
| 16 | const XML_NODE_CELL_XFS = 'cellXfs';  | 
            ||
| 17 | const XML_NODE_XF = 'xf';  | 
            ||
| 18 | |||
| 19 | /** Attributes used to find relevant information in the styles XML file */  | 
            ||
| 20 | const XML_ATTRIBUTE_NUM_FMT_ID = 'numFmtId';  | 
            ||
| 21 | const XML_ATTRIBUTE_FORMAT_CODE = 'formatCode';  | 
            ||
| 22 | const XML_ATTRIBUTE_APPLY_NUMBER_FORMAT = 'applyNumberFormat';  | 
            ||
| 23 | |||
| 24 | /** By convention, default style ID is 0 */  | 
            ||
| 25 | const DEFAULT_STYLE_ID = 0;  | 
            ||
| 26 | |||
| 27 | const NUMBER_FORMAT_GENERAL = 'General';  | 
            ||
| 28 | |||
| 29 | /**  | 
            ||
| 30 | * @see https://msdn.microsoft.com/en-us/library/ff529597(v=office.12).aspx  | 
            ||
| 31 | * @var array Mapping between built-in numFmtId and the associated format - for dates only  | 
            ||
| 32 | */  | 
            ||
| 33 | protected static $builtinNumFmtIdToNumFormatMapping = [  | 
            ||
| 34 | 14 => 'm/d/yyyy', // @NOTE: ECMA spec is 'mm-dd-yy'  | 
            ||
| 35 | 15 => 'd-mmm-yy',  | 
            ||
| 36 | 16 => 'd-mmm',  | 
            ||
| 37 | 17 => 'mmm-yy',  | 
            ||
| 38 | 18 => 'h:mm AM/PM',  | 
            ||
| 39 | 19 => 'h:mm:ss AM/PM',  | 
            ||
| 40 | 20 => 'h:mm',  | 
            ||
| 41 | 21 => 'h:mm:ss',  | 
            ||
| 42 | 22 => 'm/d/yyyy h:mm', // @NOTE: ECMA spec is 'm/d/yy h:mm',  | 
            ||
| 43 | 45 => 'mm:ss',  | 
            ||
| 44 | 46 => '[h]:mm:ss',  | 
            ||
| 45 | 47 => 'mm:ss.0', // @NOTE: ECMA spec is 'mmss.0',  | 
            ||
| 46 | ];  | 
            ||
| 47 | |||
| 48 | /** @var string Path of the XLSX file being read */  | 
            ||
| 49 | protected $filePath;  | 
            ||
| 50 | |||
| 51 | /** @var string Path of the styles XML file */  | 
            ||
| 52 | protected $stylesXMLFilePath;  | 
            ||
| 53 | |||
| 54 | /** @var InternalEntityFactory Factory to create entities */  | 
            ||
| 55 | protected $entityFactory;  | 
            ||
| 56 | |||
| 57 | /** @var array Array containing the IDs of built-in number formats indicating a date */  | 
            ||
| 58 | protected $builtinNumFmtIdIndicatingDates;  | 
            ||
| 59 | |||
| 60 | /** @var array Array containing a mapping NUM_FMT_ID => FORMAT_CODE */  | 
            ||
| 61 | protected $customNumberFormats;  | 
            ||
| 62 | |||
| 63 | /** @var array Array containing a mapping STYLE_ID => [STYLE_ATTRIBUTES] */  | 
            ||
| 64 | protected $stylesAttributes;  | 
            ||
| 65 | |||
| 66 | /** @var array Cache containing a mapping NUM_FMT_ID => IS_DATE_FORMAT. Used to avoid lots of recalculations */  | 
            ||
| 67 | protected $numFmtIdToIsDateFormatCache = [];  | 
            ||
| 68 | |||
| 69 | /**  | 
            ||
| 70 | * @param string $filePath Path of the XLSX file being read  | 
            ||
| 71 | * @param WorkbookRelationshipsManager $workbookRelationshipsManager Helps retrieving workbook relationships  | 
            ||
| 72 | * @param InternalEntityFactory $entityFactory Factory to create entities  | 
            ||
| 73 | */  | 
            ||
| 74 | 71 | public function __construct($filePath, $workbookRelationshipsManager, $entityFactory)  | 
            |
| 81 | |||
| 82 | /**  | 
            ||
| 83 | * Returns whether the style with the given ID should consider  | 
            ||
| 84 | * numeric values as timestamps and format the cell as a date.  | 
            ||
| 85 | *  | 
            ||
| 86 | * @param int $styleId Zero-based style ID  | 
            ||
| 87 | * @return bool Whether the cell with the given cell should display a date instead of a numeric value  | 
            ||
| 88 | */  | 
            ||
| 89 | 44 | public function shouldFormatNumericValueAsDate($styleId)  | 
            |
| 104 | |||
| 105 | /**  | 
            ||
| 106 | * Reads the styles.xml file and extract the relevant information from the file.  | 
            ||
| 107 | *  | 
            ||
| 108 | * @return void  | 
            ||
| 109 | */  | 
            ||
| 110 | 11 | protected function extractRelevantInfo()  | 
            |
| 129 | |||
| 130 | /**  | 
            ||
| 131 | * Extracts number formats from the "numFmt" nodes.  | 
            ||
| 132 | * For simplicity, the styles attributes are kept in memory. This is possible thanks  | 
            ||
| 133 | * to the reuse of formats. So 1 million cells should not use 1 million formats.  | 
            ||
| 134 | *  | 
            ||
| 135 | * @param \Box\Spout\Reader\Wrapper\XMLReader $xmlReader XML Reader positioned on the "numFmts" node  | 
            ||
| 136 | * @return void  | 
            ||
| 137 | */  | 
            ||
| 138 | 8 | protected function extractNumberFormats($xmlReader)  | 
            |
| 151 | |||
| 152 | /**  | 
            ||
| 153 | * Extracts style attributes from the "xf" nodes, inside the "cellXfs" section.  | 
            ||
| 154 | * For simplicity, the styles attributes are kept in memory. This is possible thanks  | 
            ||
| 155 | * to the reuse of styles. So 1 million cells should not use 1 million styles.  | 
            ||
| 156 | *  | 
            ||
| 157 | * @param \Box\Spout\Reader\Wrapper\XMLReader $xmlReader XML Reader positioned on the "cellXfs" node  | 
            ||
| 158 | * @return void  | 
            ||
| 159 | */  | 
            ||
| 160 | 11 | protected function extractStyleAttributes($xmlReader)  | 
            |
| 180 | |||
| 181 | /**  | 
            ||
| 182 | * @return array The custom number formats  | 
            ||
| 183 | */  | 
            ||
| 184 | 6 | protected function getCustomNumberFormats()  | 
            |
| 192 | |||
| 193 | /**  | 
            ||
| 194 | * @return array The styles attributes  | 
            ||
| 195 | */  | 
            ||
| 196 | 11 | protected function getStylesAttributes()  | 
            |
| 204 | |||
| 205 | /**  | 
            ||
| 206 | * @param array $styleAttributes Array containing the style attributes (2 keys: "applyNumberFormat" and "numFmtId")  | 
            ||
| 207 | * @return bool Whether the style with the given attributes indicates that the number is a date  | 
            ||
| 208 | */  | 
            ||
| 209 | 38 | protected function doesStyleIndicateDate($styleAttributes)  | 
            |
| 225 | |||
| 226 | /**  | 
            ||
| 227 | * Returns whether the number format ID indicates that the number is a date.  | 
            ||
| 228 | * The result is cached to avoid recomputing the same thing over and over, as  | 
            ||
| 229 | * "numFmtId" attributes can be shared between multiple styles.  | 
            ||
| 230 | *  | 
            ||
| 231 | * @param int $numFmtId  | 
            ||
| 232 | * @return bool Whether the number format ID indicates that the number is a date  | 
            ||
| 233 | */  | 
            ||
| 234 | 36 | protected function doesNumFmtIdIndicateDate($numFmtId)  | 
            |
| 247 | |||
| 248 | /**  | 
            ||
| 249 | * @param int $numFmtId  | 
            ||
| 250 | * @return string|null The custom number format or NULL if none defined for the given numFmtId  | 
            ||
| 251 | */  | 
            ||
| 252 | 36 | protected function getFormatCodeForNumFmtId($numFmtId)  | 
            |
| 259 | |||
| 260 | /**  | 
            ||
| 261 | * @param int $numFmtId  | 
            ||
| 262 | * @return bool Whether the number format ID indicates that the number is a date  | 
            ||
| 263 | */  | 
            ||
| 264 | 36 | protected function isNumFmtIdBuiltInDateFormat($numFmtId)  | 
            |
| 268 | |||
| 269 | /**  | 
            ||
| 270 | * @param string|null $formatCode  | 
            ||
| 271 | * @return bool Whether the given format code indicates that the number is a date  | 
            ||
| 272 | */  | 
            ||
| 273 | 34 | protected function isFormatCodeCustomDateFormat($formatCode)  | 
            |
| 282 | |||
| 283 | /**  | 
            ||
| 284 | * @param string $formatCode  | 
            ||
| 285 | * @return bool Whether the given format code matches a date format pattern  | 
            ||
| 286 | */  | 
            ||
| 287 | 28 | protected function isFormatCodeMatchingDateFormatPattern($formatCode)  | 
            |
| 311 | |||
| 312 | /**  | 
            ||
| 313 | * Returns the format as defined in "styles.xml" of the given style.  | 
            ||
| 314 | * NOTE: It is assumed that the style DOES have a number format associated to it.  | 
            ||
| 315 | *  | 
            ||
| 316 | * @param int $styleId Zero-based style ID  | 
            ||
| 317 | * @return string The number format code associated with the given style  | 
            ||
| 318 | */  | 
            ||
| 319 | 2 | public function getNumberFormatCode($styleId)  | 
            |
| 334 | }  | 
            ||
| 335 |