Skip to content

Commit

Permalink
refactor: Improve & document CDVConfigParser class
Browse files Browse the repository at this point in the history
  • Loading branch information
dpogue committed Aug 23, 2024
1 parent f9634a2 commit 491429c
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Licensed to the Apache Software Foundation (ASF) under one
*/

#import "CDVIntentAndNavigationFilter.h"
#import <Cordova/CDVConfigParser.h>

@interface CDVIntentAndNavigationFilter ()

Expand Down Expand Up @@ -73,9 +74,7 @@ - (void)parser:(NSXMLParser*)parser parseErrorOccurred:(NSError*)parseError

- (void)pluginInitialize
{
if ([self.viewController isKindOfClass:[CDVViewController class]]) {
[(CDVViewController*)self.viewController parseSettingsWithParser:self];
}
[CDVConfigParser parseConfigFile:self.viewController.configFilePath withDelegate:self];
}

+ (CDVIntentAndNavigationFilterValue) filterUrl:(NSURL*)url allowIntentsList:(CDVAllowList*)allowIntentsList navigationsAllowList:(CDVAllowList*)navigationsAllowList
Expand Down
48 changes: 38 additions & 10 deletions CordovaLib/Classes/Public/CDVConfigParser.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,47 @@ Licensed to the Apache Software Foundation (ASF) under one
#import <Cordova/CDVConfigParser.h>

@interface CDVConfigParser ()
{
NSString *featureName;
}

@property (nonatomic, readwrite, strong) NSMutableDictionary* pluginsDict;
@property (nonatomic, readwrite, strong) NSMutableDictionary* settings;
@property (nonatomic, readwrite, strong) NSMutableArray* startupPluginNames;
@property (nonatomic, readwrite, strong) NSString* startPage;
@property (nonatomic, readwrite, strong) NSMutableDictionary *pluginsDict;
@property (nonatomic, readwrite, strong) NSMutableDictionary *settings;
@property (nonatomic, readwrite, strong) NSMutableArray *startupPluginNames;
@property (nonatomic, readwrite, strong) NSString *startPage;

@end

@implementation CDVConfigParser

@synthesize pluginsDict, settings, startPage, startupPluginNames;
@synthesize pluginsDict;
@synthesize settings;
@synthesize startPage;
@synthesize startupPluginNames;

+ (instancetype)parseConfigFile:(NSURL *)filePath
{
CDVConfigParser* delegate = [[CDVConfigParser alloc] init];
[CDVConfigParser parseConfigFile:filePath withDelegate:delegate];
return delegate;
}

+ (BOOL)parseConfigFile:(NSURL *)filePath withDelegate:(id <NSXMLParserDelegate>)delegate
{
NSXMLParser *configParser = [[NSXMLParser alloc] initWithContentsOfURL:filePath];

if (configParser == nil) {
NSLog(@"Failed to initialize XML parser.");
return NO;
}

[configParser setDelegate:delegate];
[configParser parse];

return YES;
}

- (id)init
- (instancetype)init
{
self = [super init];
if (self != nil) {
Expand All @@ -44,14 +72,14 @@ - (id)init
return self;
}

- (void)parser:(NSXMLParser*)parser didStartElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qualifiedName attributes:(NSDictionary*)attributeDict
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@"preference"]) {
settings[[attributeDict[@"name"] lowercaseString]] = attributeDict[@"value"];
} else if ([elementName isEqualToString:@"feature"]) { // store feature name to use with correct parameter set
featureName = [attributeDict[@"name"] lowercaseString];
} else if ((featureName != nil) && [elementName isEqualToString:@"param"]) {
NSString* paramName = [attributeDict[@"name"] lowercaseString];
NSString *paramName = [attributeDict[@"name"] lowercaseString];
id value = attributeDict[@"value"];
if ([paramName isEqualToString:@"ios-package"]) {
pluginsDict[featureName] = value;
Expand All @@ -66,14 +94,14 @@ - (void)parser:(NSXMLParser*)parser didStartElement:(NSString*)elementName names
}
}

- (void)parser:(NSXMLParser*)parser didEndElement:(NSString*)elementName namespaceURI:(NSString*)namespaceURI qualifiedName:(NSString*)qualifiedName
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
{
if ([elementName isEqualToString:@"feature"]) { // no longer handling a feature so release
featureName = nil;
}
}

- (void)parser:(NSXMLParser*)parser parseErrorOccurred:(NSError*)parseError
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
{
NSAssert(NO, @"config.xml parse error line %ld col %ld", (long)[parser lineNumber], (long)[parser columnNumber]);
}
Expand Down
44 changes: 16 additions & 28 deletions CordovaLib/Classes/Public/CDVViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,12 @@ - (void)setSplashBackgroundColor:(UIColor *)color
_splashBackgroundColor = color ?: self.backgroundColor;
}

-(NSString*)configFilePath{
NSString* path = self.configFile ?: @"config.xml";
- (nullable NSURL *)configFilePath
{
NSString* path = self.configFile;

// if path is relative, resolve it against the main bundle
if(![path isAbsolutePath]){
if (![path isAbsolutePath]) {
NSString* absolutePath = [[NSBundle mainBundle] pathForResource:path ofType:nil];
if(!absolutePath){
NSAssert(NO, @"ERROR: %@ not found in the main bundle!", path);
Expand All @@ -179,42 +180,24 @@ -(NSString*)configFilePath{
return nil;
}

return path;
}

- (void)parseSettingsWithParser:(NSObject <NSXMLParserDelegate>*)delegate
{
// read from config.xml in the app bundle
NSString* path = [self configFilePath];

NSURL* url = [NSURL fileURLWithPath:path];

self.configParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
if (self.configParser == nil) {
NSLog(@"Failed to initialize XML parser.");
return;
}
[self.configParser setDelegate:((id < NSXMLParserDelegate >)delegate)];
[self.configParser parse];
return [NSURL fileURLWithPath:path];
}

- (void)loadSettings
{
CDVConfigParser* delegate = [[CDVConfigParser alloc] init];

[self parseSettingsWithParser:delegate];
CDVConfigParser *parser = [CDVConfigParser parseConfigFile:self.configFilePath];

// Get the plugin dictionary, allowList and settings from the delegate.
self.pluginsMap = delegate.pluginsDict;
self.startupPluginNames = delegate.startupPluginNames;
self.settings = [[CDVSettingsDictionary alloc] initWithDictionary:delegate.settings];
self.pluginsMap = parser.pluginsDict;
self.startupPluginNames = parser.startupPluginNames;
self.settings = [[CDVSettingsDictionary alloc] initWithDictionary:parser.settings];

// And the start folder/page.
if(self.wwwFolderName == nil){
self.wwwFolderName = @"www";
}
if(delegate.startPage && self.startPage == nil){
self.startPage = delegate.startPage;
if(parser.startPage && self.startPage == nil){
self.startPage = parser.startPage;
}
if (self.startPage == nil) {
self.startPage = @"index.html";
Expand Down Expand Up @@ -747,4 +730,9 @@ - (void)showLaunchScreen:(BOOL)visible
}];
}

- (void)parseSettingsWithParser:(id <NSXMLParserDelegate>)delegate
{
[CDVConfigParser parseConfigFile:self.configFilePath withDelegate:delegate];
}

@end
68 changes: 60 additions & 8 deletions CordovaLib/include/Cordova/CDVConfigParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,70 @@
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
*/

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

/**
An object that handles parsing Cordova XML configuration files.
## Overview
The `CDVConfigParser` class provides methods to parse a Cordova XML
configuration file and then access the resulting configuration data.
Use ``parseConfigFile:`` to load data from a file path.
Use ``parseConfigFile:withDelegate:`` if you need to intercept the XML parsing
and handle the data yourself with an ``NSXMLParserDelegate``.
*/
@interface CDVConfigParser : NSObject <NSXMLParserDelegate>
{
NSString* featureName;
}

@property (nonatomic, readonly, strong) NSMutableDictionary* pluginsDict;
@property (nonatomic, readonly, strong) NSMutableDictionary* settings;
@property (nonatomic, readonly, strong) NSMutableArray* startupPluginNames;
@property (nonatomic, readonly, strong) NSString* startPage;
/**
A dictionary mapping Cordova plugin name keys to the plugin classes that implement them.
*/
@property (nonatomic, readonly, strong) NSMutableDictionary *pluginsDict;

/**
A dictionary of Cordova preference keys and their values.
This should not be used directly, you should only use it to initialize a
``CDVSettingsDictionary`` object.
*/
@property (nonatomic, readonly, strong) NSMutableDictionary *settings;

/**
An array of plugin names to load immediately when Cordova initializes.
*/
@property (nonatomic, readonly, strong) NSMutableArray *startupPluginNames;

/**
The path to the HTML page to display when the web view loads.
*/
@property (nonatomic, nullable, readonly, strong) NSString *startPage;

/**
Parses the given path as a Cordova XML configuration file.
If the file could not be loaded or parsed, the resulting ``CDVConfigParser``
object will have empty values.
- Parameters:
- filePath: The file path URL to the configuration file.
- Returns: A ``CDVConfigParser`` with the parsed result.
*/
+ (instancetype)parseConfigFile:(NSURL *)filePath;

/**
Parses the given path as a Cordova XML configuration file using the given delegate.
- Parameters:
- filePath: The file path URL to the configuration file.
- delegate: The delegate to handle the parsed XML data.
- Returns: Whether the given file was successfully parsed.
*/
+ (BOOL)parseConfigFile:(NSURL *)filePath withDelegate:(id <NSXMLParserDelegate>)delegate;
@end

NS_ASSUME_NONNULL_END
14 changes: 9 additions & 5 deletions CordovaLib/include/Cordova/CDVViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@

@class CDVPlugin;

NS_ASSUME_NONNULL_BEGIN

@interface CDVViewController : UIViewController

NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, nullable, readonly, strong) NSXMLParser *configParser CDV_DEPRECATED(8, "Unused");

@property (nonatomic, readonly, nullable, weak) IBOutlet UIView* webView;

Expand All @@ -47,8 +49,6 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, readonly, strong) CDVSettingsDictionary* settings;

@property (nonatomic, readonly, strong) NSXMLParser* configParser;

@property (nonatomic, readwrite, copy) NSString* appScheme;
@property (nonatomic, readwrite, copy) NSString* configFile;
@property (nonatomic, readwrite, copy) NSString* wwwFolderName;
Expand All @@ -57,6 +57,10 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly, strong) id <CDVWebViewEngineProtocol> webViewEngine;
@property (nonatomic, readonly, strong) id <CDVCommandDelegate> commandDelegate;

/**
The filepath to the Cordova XML configuration file.
*/
@property (nonatomic, nullable, readonly, copy) NSURL *configFilePath;

/**
A boolean value indicating whether to show the splash screen while the webview
Expand Down Expand Up @@ -109,6 +113,6 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)showLaunchScreen:(BOOL)visible;

NS_ASSUME_NONNULL_END

@end

NS_ASSUME_NONNULL_END

0 comments on commit 491429c

Please sign in to comment.