diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml index e5b10f2..4ed32b0 100644 --- a/.idea/libraries/Dart_Packages.xml +++ b/.idea/libraries/Dart_Packages.xml @@ -2,185 +2,277 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.idea/libraries/Dart_SDK.xml b/.idea/libraries/Dart_SDK.xml index c24a4bc..af8e549 100644 --- a/.idea/libraries/Dart_SDK.xml +++ b/.idea/libraries/Dart_SDK.xml @@ -1,25 +1,27 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 2ad03a1..bfc2bb2 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,24 +1,20 @@ + + + + + - - - - + - - - - - - - - - + + - - + + - - + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -117,60 +153,67 @@ + FetchUsersResult + fontVariationSettings + jwt + createPo + createPost + dynamic meta - from - taxonomies - menu - avatar - Content - Guid - Title - Descript - Excerpt - export - Labels - String - ; - : '', - , - : - /// + updatePost + fetchPosts + _onValidUser + me + then + comment + createComment + updatepost + userid + user.id + user + >= 200 && response.statusCode < 300 + deletePst + update user with + deleteUser + fetchUsers + createuser + deleteComment + updatePOst + updateUser + role + createUser + create import this. , ; - : :'${}', + if(this.\ + final + set + : E:\DSI\2019\Flutter\flutter_wordpress\lib\schemas + @@ -217,38 +277,41 @@ - + - - + + + + - - - - + @@ -267,7 +330,6 @@ @@ -281,339 +343,363 @@ - - - + + + + + + + - - - - + + - - - + + + + - - - - - + + + + - - - - - - + + + + + + + + + + + - - - - - - - + + + + + + + - + + + + + + + + - + + - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - + - + + + + + + + + + + + + + + + + + + - - - + - + - - + + - - - - + - - + + - + + + + + + + + + - - + + - + - - + + - + - - - - - + + - + - - - + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - - + - - + + - + - - - - - - - - - - - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - - + + + + + + + + + + + - + - - + + - + + - - - - - - - - - - - - - - - - - - - - - - + - - + + diff --git a/CHANGELOG.md b/CHANGELOG.md index 469fb00..5a0e5f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,25 @@ -## [0.1.1] - Added Models +## [0.3.0-nullsafety.0] - Type Safety + +* Added type safety + +## [0.2.1] - 26/04/2020 +* Custom post types + +## [0.2.0] - 21/04/2020 +* Create, Update and Delete Comments +* Create, Update and Delete Posts +* Update and Delete Users + +## [0.1.4] - 27/02/2019 +* Updated homepage URL + +## [0.1.3] - 26/02/2019 +* Update example. Update post fetching to include author, comments. Add fetching comments as a hierarchy. + +## [0.1.2] - 16/02/2019 +* Add fetch categories, tags, pages. Add create post, comments. + +## [0.1.1] - 14/02/2019 * Update README.md. Add fetch users list, fetch comments list. * Implemented authorization function and fetching of Posts with parameters diff --git a/README.md b/README.md index 0c52c84..fd2ef6b 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,32 @@ # Flutter Wordpress +[pub.dev](https://pub.dev/packages/flutter_wordpress) + This library uses [WordPress REST API V2](https://developer.wordpress.org/rest-api/) to provide a way for your application to interact with your WordPress website. +[Tutorial - by Ritesh Sharma](https://medium.com/flutter-community/building-flutter-apps-with-wordpress-backend-part-1-e56414a4a79b) + +## Screenshots + + + ## Requirements + For authentication and usage of administrator level REST APIs, you need to use either of the two popular authentication plugins in your WordPress site: + 1. [Application Passwords](https://wordpress.org/plugins/application-passwords/) -2. [JWT Authentication for WP REST API](https://wordpress.org/plugins/jwt-authentication-for-wp-rest-api/) +2. [JWT Authentication for WP REST API](https://wordpress.org/plugins/jwt-authentication-for-wp-rest-api/) (recommended) ## Getting Started ### 1. Import library +#### First: + +Find your pubspec.yaml in the root of your project and add flutter_wordpress: ^0.2.0 under dependencies: + +#### Second: + ```dart import 'package:flutter_wordpress/flutter_wordpress.dart' as wp; ``` @@ -22,10 +38,10 @@ wp.WordPress wordPress; // adminName and adminKey is needed only for admin level APIs wordPress = wp.WordPress( - baseUrl: 'http://localhost', - authenticator: wp.WordPressAuthenticator.ApplicationPasswords, - adminName: '', - adminKey: '', + baseUrl: 'http://localhost', + authenticator: wp.WordPressAuthenticator.JWT, + adminName: '', + adminKey: '', ); ``` @@ -33,14 +49,14 @@ wordPress = wp.WordPress( ```dart Future response = wordPress.authenticateUser( - username: 'username', - password: 'password', - ); + username: 'ChiefEditor', + password: 'chiefeditor@123', +); response.then((user) { - print(user.toString()); + createPost(user); }).catchError((err) { - print(err.toString()); + print('Failed to fetch user: $err'); }); ``` @@ -48,46 +64,235 @@ response.then((user) { ```dart Future> posts = wordPress.fetchPosts( - params: wp.ParamsPostList( - context: wp.WordPressContext.view, - pageNum: 1, - perPage: 20, - order: wp.Order.desc, - orderBy: wp.PostsOrderBy.date, - ), - ); + postParams: wp.ParamsPostList( + context: wp.WordPressContext.view, + pageNum: 1, + perPage: 20, + order: wp.Order.desc, + orderBy: wp.PostOrderBy.date, + ), + fetchAuthor: true, + fetchFeaturedMedia: true, + fetchComments: true, + postType: 'post' +); ``` ### 5. Fetch Users ```dart Future> users = wordPress.fetchUsers( - params: wp.ParamsUserList( - context: wp.WordPressContext.view, - pageNum: 1, - perPage: 30, - order: wp.Order.asc, - orderBy: wp.UsersOrderBy.name, - role: wp.UserRole.subscriber, - ), - ); + params: wp.ParamsUserList( + context: wp.WordPressContext.view, + pageNum: 1, + perPage: 30, + order: wp.Order.asc, + orderBy: wp.UsersOrderBy.name, + roles: ['subscriber'], + ), +); ``` ### 6. Fetch Comments ```dart Future> comments = wordPress.fetchComments( - params: wp.ParamsCommentList( - context: wp.WordPressContext.view, - pageNum: 1, - perPage: 30, - includePostIDs: [1], + params: wp.ParamsCommentList( + context: wp.WordPressContext.view, + pageNum: 1, + perPage: 30, + includePostIDs: [1], + ), +); +``` + +### 7. Create User + +```dart +Future createUser({@required String email, @required String username, @required String password, @required List roles}) async { + await widget.wordPress.createUser( + user: wp.User( + email: email, + password: password, + username: username, + roles: roles + ) + ).then((p) { + print('User created successfully ${p}'); + }).catchError((err) { + print('Failed to create user: $err'); + }); + } +``` + +### 8. Create Post + +```dart + void createPost({@required wp.User user}) { + final post = widget.wordPress.createPost( + post: new wp.Post( + title: 'First post as a Chief Editor', + content: 'Blah! blah! blah!', + excerpt: 'Discussion about blah!', + authorID: user.id, + commentStatus: wp.PostCommentStatus.open, + pingStatus: wp.PostPingStatus.closed, + status: wp.PostPageStatus.publish, + format: wp.PostFormat.standard, + sticky: true, ), ); + + post.then((p) { + print('Post created successfully with ID: ${p.id}'); + }).catchError((err) { + print('Failed to create post: $err'); + }); + } ``` -## Future Work -1. Implementing OAuth 2.0 authentication. +### 9. create Comment + +```dart + void createComment({@required int userId, @required int postId}) { + final comment = widget.wordPress.createComment( + comment: new wp.Comment( + author: userId, + post: postId, + content: "First!", + parent: 0, + ), + ); + + comment.then((c) { + print('Comment successfully posted with ID: ${c.id}'); + }).catchError((err) { + print('Failed to comment: $err'); + }); + } +``` +### 10. Update Comment +```dart +Future updateComment({@required int id, @required int postId, @required wp.User user}) async { + await widget.wordPress.updateComment( + comment: new wp.Comment( + content: "Comment Updated2!", + author: user.id, + post: postId, + ), + id: id, + ).then((c) { + print('Comment updated successfully "$c"'); + }).catchError((err) { + print('Failed to update Comment: $err'); + }); + } +``` + +### 11. Update Post + +```dart +Future updatePost({@required int id, @required int userId}) async { + await widget.wordPress.updatePost( + post: new wp.Post( + title: 'First post as a Chief Editor', + content: 'Blah! blah! blah!', + excerpt: 'Discussion about blah!', + authorID: userId, + commentStatus: wp.PostCommentStatus.open, + pingStatus: wp.PostPingStatus.closed, + status: wp.PostPageStatus.publish, + format: wp.PostFormat.standard, + sticky: true, + ), + id: id, // + ).then((p) { + print('Post updated successfully with ID ${p}'); + }).catchError((err) { + print('Failed to update post: $err'); + }); + } +``` + +### 12. Update User + +```dart +Future updateUser({@required int id, @required String username, @required String email}) async { + await widget.wordPress.updateUser( + user: new wp.User( + description: "This is description for this user", + username: username, + id: id, + email: email + ), + id: id, + ).then((u) { + print('User updated successfully $u'); + }).catchError((err) { + print('Failed to update User: $err'); + }); + } +``` + + +### 13. Delete Comment + +```dart +Future deleteComment({@required int id}) async { + await widget.wordPress.deleteComment(id: id).then((c) { + print('Comment Deleted successfully: $c'); + }).catchError((err) { + print('Failed to Delete comment: $err'); + }); + } +``` + +### 14. Delete Post + +```dart + Future deletePost({@required int id}) async { + await widget.wordPress.deletePost(id: id).then((p) { + print('Post Deleted successfully: $p'); + }).catchError((err) { + print('Failed to Delete post: $err'); + }); + } +``` + +### 15. Delete User + +```dart + Future deleteUser({@required int id, @required int reassign}) async { + await widget.wordPress.deleteUser(id: id, reassign: reassign).then((u) { + print('User Deleted successfully: $u'); + }).catchError((err) { + print('Failed to Delete user: $err'); + }); + } +``` + +### 16. Upload Media + +```dart + uploadMedia(File image) async { + var media = await wordPress.uploadMedia(image).then((m) { + print('Media uploaded successfully: $m'); + }).catchError((err) { + print('Failed to upload Media: $err'); + }); + int mediaID = media['id']; +} +``` + +## Future Work + +1. Implementing OAuth 2.0 authentication. +## Contributors +- [Suraj Shettigar](https://github.com/SurajShettigar) +- [Sachin Ganesh](https://github.com/SachinGanesh) +- [Harm-Jan Roskam](https://github.com/harmjanr) +- [Yahya Makarim](https://github.com/ymakarim) +- [Garv Maggu](https://github.com/GarvMaggu) diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies new file mode 100644 index 0000000..2d152ed --- /dev/null +++ b/example/.flutter-plugins-dependencies @@ -0,0 +1 @@ +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"video_player_avfoundation","path":"/Users/ritheshsalyan/Developer/DevTools/flutter/.pub-cache/hosted/pub.dartlang.org/video_player_avfoundation-2.3.0/","dependencies":[]},{"name":"wakelock","path":"/Users/ritheshsalyan/Developer/DevTools/flutter/.pub-cache/hosted/pub.dartlang.org/wakelock-0.6.1+1/","dependencies":[]},{"name":"webview_flutter_wkwebview","path":"/Users/ritheshsalyan/Developer/DevTools/flutter/.pub-cache/hosted/pub.dartlang.org/webview_flutter_wkwebview-2.7.1/","dependencies":[]}],"android":[{"name":"video_player_android","path":"/Users/ritheshsalyan/Developer/DevTools/flutter/.pub-cache/hosted/pub.dartlang.org/video_player_android-2.3.0/","dependencies":[]},{"name":"wakelock","path":"/Users/ritheshsalyan/Developer/DevTools/flutter/.pub-cache/hosted/pub.dartlang.org/wakelock-0.6.1+1/","dependencies":[]},{"name":"webview_flutter_android","path":"/Users/ritheshsalyan/Developer/DevTools/flutter/.pub-cache/hosted/pub.dartlang.org/webview_flutter_android-2.8.3/","dependencies":[]}],"macos":[{"name":"wakelock_macos","path":"/Users/ritheshsalyan/Developer/DevTools/flutter/.pub-cache/hosted/pub.dartlang.org/wakelock_macos-0.4.0/","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"video_player_web","path":"/Users/ritheshsalyan/Developer/DevTools/flutter/.pub-cache/hosted/pub.dartlang.org/video_player_web-2.0.7/","dependencies":[]},{"name":"wakelock_web","path":"/Users/ritheshsalyan/Developer/DevTools/flutter/.pub-cache/hosted/pub.dartlang.org/wakelock_web-0.4.0/","dependencies":[]}]},"dependencyGraph":[{"name":"video_player","dependencies":["video_player_android","video_player_avfoundation","video_player_web"]},{"name":"video_player_android","dependencies":[]},{"name":"video_player_avfoundation","dependencies":[]},{"name":"video_player_web","dependencies":[]},{"name":"wakelock","dependencies":["wakelock_macos","wakelock_web"]},{"name":"wakelock_macos","dependencies":[]},{"name":"wakelock_web","dependencies":[]},{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2022-02-23 10:31:39.189036","version":"2.8.1"} \ No newline at end of file diff --git a/example/.gitignore b/example/.gitignore index 47e0b4d..4f8a952 100644 --- a/example/.gitignore +++ b/example/.gitignore @@ -9,6 +9,7 @@ .buildlog/ .history .svn/ +*flutter_export_environment* # IntelliJ related *.iml diff --git a/example/README.md b/example/README.md index 6d17fb3..accbbc6 100644 --- a/example/README.md +++ b/example/README.md @@ -1,16 +1,11 @@ -# example +# Flutter Wordpress Example +Basic login, displaying posts and comments have been implemented in this example flutter app. -A new Flutter project. +## Screenshots + + + -## Getting Started -This project is a starting point for a Flutter application. -A few resources to get you started if this is your first Flutter project: -- [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) - -For help getting started with Flutter, view our -[online documentation](https://flutter.io/docs), which offers tutorials, -samples, guidance on mobile development, and a full API reference. diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml new file mode 100644 index 0000000..61b6c4d --- /dev/null +++ b/example/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/example/android/.gitignore b/example/android/.gitignore new file mode 100644 index 0000000..6f56801 --- /dev/null +++ b/example/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 3d260e6..faf22c5 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -22,23 +22,32 @@ if (flutterVersionName == null) { } apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 27 + compileSdkVersion flutter.compileSdkVersion - lintOptions { - disable 'InvalidPackage' + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.example" - minSdkVersion 16 - targetSdkVersion 27 + minSdkVersion 19//flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { @@ -55,7 +64,5 @@ flutter { } dependencies { - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" } diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..c208884 --- /dev/null +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 6852e82..3f41384 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,39 +1,34 @@ - - - - - - - + + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" + /> + + diff --git a/example/android/app/src/main/java/com/example/example/MainActivity.java b/example/android/app/src/main/java/com/example/example/MainActivity.java deleted file mode 100644 index 84f8920..0000000 --- a/example/android/app/src/main/java/com/example/example/MainActivity.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.example; - -import android.os.Bundle; -import io.flutter.app.FlutterActivity; -import io.flutter.plugins.GeneratedPluginRegistrant; - -public class MainActivity extends FlutterActivity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - GeneratedPluginRegistrant.registerWith(this); - } -} diff --git a/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt new file mode 100644 index 0000000..e793a00 --- /dev/null +++ b/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..3db14bb --- /dev/null +++ b/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml index 00fa441..d460d1e 100644 --- a/example/android/app/src/main/res/values/styles.xml +++ b/example/android/app/src/main/res/values/styles.xml @@ -1,8 +1,18 @@ - + + diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..c208884 --- /dev/null +++ b/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/build.gradle b/example/android/build.gradle index bb8a303..4256f91 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -1,18 +1,20 @@ buildscript { + ext.kotlin_version = '1.6.10' repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath 'com.android.tools.build:gradle:4.1.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() - jcenter() + mavenCentral() } } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index 8bd86f6..94adc3a 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1 +1,3 @@ org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 2819f02..bc6a58a 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle index 5a2f14f..44e62bc 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -1,15 +1,11 @@ include ':app' -def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() -def plugins = new Properties() -def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') -if (pluginsFile.exists()) { - pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } -} +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } -plugins.each { name, path -> - def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() - include ":$name" - project(":$name").projectDir = pluginDirectory -} +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/example/images/screenshots/login.png b/example/images/screenshots/login.png new file mode 100644 index 0000000..0006dad Binary files /dev/null and b/example/images/screenshots/login.png differ diff --git a/example/images/screenshots/post_comments.png b/example/images/screenshots/post_comments.png new file mode 100644 index 0000000..1f14761 Binary files /dev/null and b/example/images/screenshots/post_comments.png differ diff --git a/example/images/screenshots/posts.png b/example/images/screenshots/posts.png new file mode 100644 index 0000000..aac6004 Binary files /dev/null and b/example/images/screenshots/posts.png differ diff --git a/example/ios/.gitignore b/example/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/example/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig index 592ceee..ec97fc6 100644 --- a/example/ios/Flutter/Debug.xcconfig +++ b/example/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/example/ios/Flutter/Flutter.podspec b/example/ios/Flutter/Flutter.podspec new file mode 100644 index 0000000..5ca3041 --- /dev/null +++ b/example/ios/Flutter/Flutter.podspec @@ -0,0 +1,18 @@ +# +# NOTE: This podspec is NOT to be published. It is only used as a local source! +# + +Pod::Spec.new do |s| + s.name = 'Flutter' + s.version = '1.0.0' + s.summary = 'High-performance, high-fidelity mobile apps.' + s.description = <<-DESC +Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS. + DESC + s.homepage = 'https://flutter.io' + s.license = { :type => 'MIT' } + s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } + s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s } + s.ios.deployment_target = '8.0' + s.vendored_frameworks = 'Flutter.framework' +end diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig index 592ceee..c4855bf 100644 --- a/example/ios/Flutter/Release.xcconfig +++ b/example/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/example/ios/Podfile b/example/ios/Podfile new file mode 100644 index 0000000..f7d6a5e --- /dev/null +++ b/example/ios/Podfile @@ -0,0 +1,38 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 5229fca..d3d9665 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -8,12 +8,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; @@ -29,8 +24,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -40,15 +33,12 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; @@ -62,8 +52,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -73,10 +61,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( - 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, - 3B80C3931E831B6300D905FE /* App.framework */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */, @@ -190,7 +175,6 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -210,7 +194,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/example/lib/display_posts.dart b/example/lib/display_posts.dart new file mode 100644 index 0000000..2d48bd8 --- /dev/null +++ b/example/lib/display_posts.dart @@ -0,0 +1,428 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_wordpress/flutter_wordpress.dart' as wp; + +import 'post_page.dart'; + +class PostListPage extends StatelessWidget { + final wp.WordPress wordPress; + final wp.User user; + + PostListPage({Key key, @required this.wordPress, this.user}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Posts"), + ), + body: Center( + child: PostsBuilder( + wordPress: wordPress, + user: user, + ), + ), + ); + } +} + +class PostsBuilder extends StatefulWidget { + final wp.WordPress wordPress; + final wp.User user; + + PostsBuilder({Key key, @required this.wordPress, this.user}); + + @override + PostsBuilderState createState() => PostsBuilderState(); +} + +class PostsBuilderState extends State { + final paddingCardsList = EdgeInsets.symmetric(vertical: 4.0, horizontal: 8.0); + final padding_4 = EdgeInsets.all(4.0); + final padding_8 = EdgeInsets.all(8.0); + final padding_16 = EdgeInsets.all(16.0); + + Future> posts; + + @override + void initState() { + super.initState(); + + fetchPosts(); + } + + void createPost({@required wp.User user}) { + final post = widget.wordPress.createPost( + post: new wp.Post( + title: 'First post as a Chief Editor', + content: 'Blah! blah! blah!', + excerpt: 'Discussion about blah!', + authorID: user.id, + commentStatus: wp.PostCommentStatus.open, + pingStatus: wp.PostPingStatus.closed, + status: wp.PostPageStatus.publish, + format: wp.PostFormat.standard, + sticky: true, + ), + ); + + post.then((p) { + print('Post created successfully with ID: ${p.id}'); + }).catchError((err) { + print('Failed to create post: $err'); + }); + } + +// yahya + + Future createUser({@required String email, @required String username, @required String password, @required List roles}) async { + await widget.wordPress.createUser( + user: wp.User( + email: email, + password: password, + username: username, + roles: roles + ) + ).then((p) { + print('User created successfully ${p}'); + }).catchError((err) { + print('Failed to create user: $err'); + }); + } + +// ===================== +// UPDATE START +// ===================== + + Future updatePost({@required int id, @required int userId}) async { + await widget.wordPress.updatePost( + post: new wp.Post( + title: 'First post as a Chief Editor', + content: 'Blah! blah! blah!', + excerpt: 'Discussion about blah!', + authorID: userId, + commentStatus: wp.PostCommentStatus.open, + pingStatus: wp.PostPingStatus.closed, + status: wp.PostPageStatus.publish, + format: wp.PostFormat.standard, + sticky: true, + ), + id: id, // + ).then((p) { + print('Post updated successfully with ID ${p}'); + }).catchError((err) { + print('Failed to update post: $err'); + }); + } + + Future updateComment({@required int id, @required int postId, @required wp.User user}) async { + await widget.wordPress.updateComment( + comment: new wp.Comment( + content: "Comment Updated2!", + author: user.id, + post: postId, + ), + id: id, + ).then((c) { + print('Comment updated successfully "$c"'); + }).catchError((err) { + print('Failed to update Comment: $err'); + }); + } + + Future updateUser({@required int id, @required String username, @required String email}) async { + await widget.wordPress.updateUser( + user: new wp.User( + description: "This is description for this user", + username: username, + id: id, + email: email + ), + id: id, + ).then((u) { + print('User updated successfully $u'); + }).catchError((err) { + print('Failed to update User: $err'); + }); + } + +// ===================== +// UPDATE END +// ===================== + +// ===================== +// DELETE START +// ===================== + + Future deletePost({@required int id}) async { + await widget.wordPress.deletePost(id: id).then((p) { + print('Post Deleted successfully: $p'); + }).catchError((err) { + print('Failed to Delete post: $err'); + }); + } + + Future deleteComment({@required int id}) async { + await widget.wordPress.deleteComment(id: id).then((c) { + print('Comment Deleted successfully: $c'); + }).catchError((err) { + print('Failed to Delete comment: $err'); + }); + } + + Future deleteUser({@required int id, @required int reassign}) async { + await widget.wordPress.deleteUser(id: id, reassign: reassign).then((u) { + print('User Deleted successfully: $u'); + }).catchError((err) { + print('Failed to Delete user: $err'); + }); + } + +// ===================== +// DELETE END +// ===================== + +// end yahya + + void createComment({@required int userId, @required int postId}) { + final comment = widget.wordPress.createComment( + comment: new wp.Comment( + author: userId, + post: postId, + content: "First!", + parent: 0, + ), + ); + + comment.then((c) { + print('Comment successfully posted with ID: ${c.id}'); + }).catchError((err) { + print('Failed to comment: $err'); + }); + } + + Future fetchPosts() { + setState(() { + posts = widget.wordPress.fetchPosts( + postParams: wp.ParamsPostList(perPage: 1), + fetchAuthor: true, + fetchFeaturedMedia: true, + ); + }); + return posts; + } + + @override + Widget build(BuildContext context) { + return FutureBuilder>( + future: posts, + builder: (context, snapshot) { + if (snapshot.hasData) { + return RefreshIndicator( + child: ListView.builder( + itemBuilder: (context, i) { + int id = snapshot.data[i].id; + String title = snapshot.data[i].title.rendered; + String author = snapshot.data[i].author.name; + String content = snapshot.data[i].content.rendered; + wp.Media featuredMedia = snapshot.data[i].featuredMedia; + + return Padding( + padding: paddingCardsList, + child: GestureDetector( + onTap: () { + openPostPage(snapshot.data[i]); + }, + child: _buildPostCard( + author: author, + title: title, + content: content, + featuredMedia: featuredMedia, + id : id, + ), + ), + ); + }, + itemCount: snapshot.data.length, + ), + onRefresh: fetchPosts, + ); + } else if (snapshot.hasError) { + return Text( + snapshot.error.toString(), + style: TextStyle(color: Colors.red), + ); + } + + return CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Colors.blue), + ); + }, + ); + } + + Widget _buildPostCard({ + String author, + String title, + String content, + wp.Media featuredMedia, + int id, + }) { + return Card( + color: Colors.white, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), + child: Text( + title, + style: Theme.of(context).textTheme.headline6, + ), + ), + _buildFeaturedMedia(featuredMedia), + featuredMedia == null + ? Divider() + : SizedBox( + width: 0, + height: 0, + ), + Padding( + padding: EdgeInsets.symmetric(vertical: 0.0, horizontal: 8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + author, + style: TextStyle( + fontWeight: FontWeight.w200, + ), + ), + ElevatedButton.icon( + onPressed: () { + createComment(postId: 1, userId: 1); + }, + icon: Icon(Icons.settings), + label: Text( + "Create New Comment", + ), + ), + ElevatedButton.icon( + onPressed: () { + updateComment(user: widget.user, id: 1, postId: 1); + }, + icon: Icon(Icons.settings), + label: Text( + "Update Comment with ID #1", + ), + ), + ElevatedButton.icon( + onPressed: () { + deleteComment(id: 1); + }, + icon: Icon(Icons.settings), + label: Text( + "Delete Comment with ID #1", + ), + ), + ElevatedButton.icon( + onPressed: () { + updatePost(userId: widget.user.id, id: 1); + }, + icon: Icon(Icons.settings, color: Colors.white), + label: Text( + "Update Post with ID #1", + style: TextStyle(color: Colors.white), + ), + ), + ElevatedButton.icon( + onPressed: () { + deletePost(id: 1); + }, + icon: Icon(Icons.delete, color: Colors.white), + label: Text( + "Delete Post with ID #1", + style: TextStyle(color: Colors.white), + ), + ), + ElevatedButton.icon( + onPressed: () { + createPost(user: widget.user); + }, + icon: Icon(Icons.add_circle, color: Colors.white,), + label: Text( + "Create New Post", + style: TextStyle(color: Colors.white), + ), + ), + ElevatedButton.icon( + onPressed: () { + createUser(roles: ["subscriber"], username: "myUserName", password: "123", email: "myEmail@domain.com"); + }, + icon: Icon(Icons.add_circle, color: Colors.white,), + label: Text( + "Create New User", + style: TextStyle(color: Colors.white), + ), + ), + ElevatedButton.icon( + onPressed: () { + updateUser(id: 1, email: "newuser@gmaill.com", username: "newuser"); + }, + icon: Icon(Icons.settings, color: Colors.white,), + label: Text( + "Update User with ID #1", + style: TextStyle(color: Colors.white), + ), + ), + ElevatedButton.icon( + onPressed: () { + deleteUser(id: 1, reassign: 1); + }, + icon: Icon(Icons.delete, color: Colors.white,), + label: Text( + "Delete User with ID #1", + style: TextStyle(color: Colors.white), + ), + ) + ], + ), + ), + ], + ), + ); + } + + Widget _buildFeaturedMedia(wp.Media featuredMedia) { + if (featuredMedia == null) { + return SizedBox( + width: 0.0, + height: 0.0, + ); + } + String imgSource = featuredMedia.mediaDetails.sizes.mediumLarge.sourceUrl; + imgSource = imgSource.replaceAll('localhost', '192.168.6.165'); + return Center( + child: Image.network( + imgSource, + fit: BoxFit.cover, + ), + ); + } + + void openPostPage(wp.Post post) { + print('OnTapped'); + Navigator.push( + context, + MaterialPageRoute(builder: (context) { + return SinglePostPage( + wordPress: widget.wordPress, + post: post, + ); + }), + ); + } +} diff --git a/example/lib/generated_plugin_registrant.dart b/example/lib/generated_plugin_registrant.dart new file mode 100644 index 0000000..fd95b4f --- /dev/null +++ b/example/lib/generated_plugin_registrant.dart @@ -0,0 +1,18 @@ +// +// Generated file. Do not edit. +// + +// ignore_for_file: directives_ordering +// ignore_for_file: lines_longer_than_80_chars + +import 'package:video_player_web/video_player_web.dart'; +import 'package:wakelock_web/wakelock_web.dart'; + +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +// ignore: public_member_api_docs +void registerPlugins(Registrar registrar) { + VideoPlayerPlugin.registerWith(registrar); + WakelockWeb.registerWith(registrar); + registrar.registerMessageHandler(); +} diff --git a/example/lib/login.dart b/example/lib/login.dart new file mode 100644 index 0000000..5f02fa9 --- /dev/null +++ b/example/lib/login.dart @@ -0,0 +1,185 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_wordpress/flutter_wordpress.dart' as wp; + +import 'display_posts.dart'; + +const PADDING_16 = EdgeInsets.all(16.0); +const PADDING_8 = EdgeInsets.all(8.0); + +class LoginPage extends StatefulWidget { + @override + LoginPageState createState() => LoginPageState(); +} + +class LoginPageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text( + "Login", + style: TextStyle(fontWeight: FontWeight.w300), + ), + centerTitle: true, + ), + body: LoginFields(), + ); + } +} + +class LoginFields extends StatefulWidget { + @override + LoginFieldsState createState() => LoginFieldsState(); +} + +class LoginFieldsState extends State { + String _username; + String _password; + bool _isDetailValid = true; + bool _isValidating = false; + + @override + void initState() { + super.initState(); + _username = 'YOUR_USERNAME'; + _password = 'YOUR_PASSWORD'; + } + + @override + Widget build(BuildContext context) { + return Center( + child: SingleChildScrollView( + child: Container( + padding: PADDING_16, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: PADDING_8, + child: _buildFormField( + icon: Icon(Icons.person), + labelText: "Username", + hintText: "Username", + initialText: _username, + onChanged: _onUsernameChanged, + ), + ), + Padding( + padding: PADDING_8, + child: _buildFormField( + icon: Icon(Icons.lock), + labelText: "Password", + hintText: "Password", + initialText: _password, + obscureText: true, + onChanged: _onPasswordChanged, + ), + ), + _isDetailValid + ? SizedBox( + width: 0.0, + height: 0.0, + ) + : Padding( + padding: PADDING_8, + child: Text( + "Invalid Username / Password", + style: TextStyle( + color: Colors.red, + ), + ), + ), + ElevatedButton( + onPressed: _isValidating ? () {} : _validateUser, + child: Padding( + padding: PADDING_8, + child: _isValidating + ? CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Colors.white), + ) + : Text('Login'), + ), + ), + ], + ), + ), + )); + } + + Widget _buildFormField({ + Icon icon, + String labelText, + String hintText, + String initialText, + TextInputType inputType = TextInputType.text, + bool obscureText = false, + onChanged, + }) { + return TextField( + decoration: InputDecoration( + icon: icon, + labelText: labelText, + hintText: hintText, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(4.0), + ), + ), + controller: TextEditingController(text: initialText), + keyboardType: inputType, + obscureText: obscureText, + onChanged: onChanged, + ); + } + + void _onUsernameChanged(String value) { + _username = value; + } + + void _onPasswordChanged(String value) { + _password = value; + } + + void _validateUser() { + setState(() { + _isValidating = true; + }); + + wp.WordPress wordPress = new wp.WordPress( + baseUrl: 'YOUR WEBSITE URL', + authenticator: wp.WordPressAuthenticator.JWT, + adminName: '', + adminKey: '', + ); + + final response = + wordPress.authenticateUser(username: _username, password: _password); + + response.then((user) { + setState(() { + _isDetailValid = true; + _isValidating = false; + + _onValidUser(wordPress, user); + }); + }).catchError((err) { + print(err.toString()); + setState(() { + _isDetailValid = false; + _isValidating = false; + }); + }); + } + + void _onValidUser(wp.WordPress wordPress, wp.User user) { + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (context) => PostListPage( + wordPress: wordPress, + user: user, + ), + ), + ); + } +} diff --git a/example/lib/main.dart b/example/lib/main.dart index d3060dc..14416ac 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,162 +1,18 @@ import 'package:flutter/material.dart'; -import 'package:flutter_wordpress/flutter_wordpress.dart' as wp; +import 'login.dart'; void main() { - runApp(MyApp()); + runApp(WordPressApp()); } -class MyApp extends StatelessWidget { +class WordPressApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - primarySwatch: Colors.blue, - ), - home: MyHomePage(title: 'Flutter Demo Home Page'), + debugShowCheckedModeBanner: false, + title: 'WordPress Demo', + theme: ThemeData.light(), + home: LoginPage(), ); } -} - -class MyHomePage extends StatefulWidget { - final String title; - - MyHomePage({ - Key key, - this.title, - }) : super(key: key); - - @override - _MyHomePageState createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Center( - child: PostsBuilder(), - ), - ); - } -} - -class PostsBuilder extends StatefulWidget { - @override - PostsBuilderState createState() => PostsBuilderState(); -} - -class PostsBuilderState extends State { - wp.WordPress wordPress; - Future> posts; - Future> users; - - @override - void initState() { - super.initState(); - - try { - wordPress = wp.WordPress( - baseUrl: 'http://192.168.6.165', - authenticator: wp.WordPressAuthenticator.ApplicationPasswords, - adminName: 'admin', - adminKey: 'EOjD JsYA hKfM RHNI vufW hyUX', - ); - } catch (err) { - print(err.toString()); - } - - /* Future response = wordPress.authenticateUser( - username: 'username', - password: 'password', - ); - - response.then((user) { - print(user.toString()); - }).catchError((err) { - print(err.toString()); - });*/ - - Future> users = wordPress.fetchUsers( - params: wp.ParamsUserList( - context: wp.WordPressContext.view, - pageNum: 1, - perPage: 30, - order: wp.Order.asc, - orderBy: wp.UsersOrderBy.name, - ), - ); - - users.then((response) { - print(response); - }).catchError((err) { - print(err.toString()); - }); - - Future> comments = wordPress.fetchComments( - params: wp.ParamsCommentList( - context: wp.WordPressContext.view, - pageNum: 1, - perPage: 30, - ), - ); - - comments.then((response) { - print(response); - }).catchError((err) { - print(err.toString()); - }); - } - - void fetchPosts() { - setState(() { - posts = wordPress.fetchPosts(params: wp.ParamsPostList()); - }); - } - - void fetchUsers() { - setState(() { - users = wordPress.fetchUsers(params: wp.ParamsUserList()); - }); - } - - @override - Widget build(BuildContext context) { - return FutureBuilder>( - future: posts, - builder: (context, snapshot) { - if (snapshot.hasData) { - return ListView.separated( - itemBuilder: (context, i) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - snapshot.data[i].title.rendered, - style: Theme.of(context).textTheme.title, - ), - Text( - snapshot.data[i].content.rendered, - ), - ], - ); - }, - separatorBuilder: (context, i) { - return Divider(); - }, - itemCount: snapshot.data.length, - ); - } else if (snapshot.hasError) { - return Text( - snapshot.error.toString(), - style: TextStyle(color: Colors.red), - ); - } - return CircularProgressIndicator(); - }, - ); - } -} +} \ No newline at end of file diff --git a/example/lib/post_page.dart b/example/lib/post_page.dart new file mode 100644 index 0000000..caae445 --- /dev/null +++ b/example/lib/post_page.dart @@ -0,0 +1,193 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:flutter_wordpress/flutter_wordpress.dart' as wp; + +class SinglePostPage extends StatelessWidget { + final wp.WordPress wordPress; + final wp.Post post; + + SinglePostPage({Key key, @required this.wordPress, @required this.post}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(post.title.rendered), + ), + body: Padding( + padding: EdgeInsets.all(8.0), + child: PostWithComments(wordPress: wordPress, post: post), + ), + ); + } +} + +class PostWithComments extends StatefulWidget { + final wp.WordPress wordPress; + final wp.Post post; + + PostWithComments({@required this.wordPress, @required this.post}); + + @override + PostWithCommentsState createState() => PostWithCommentsState(); +} + +class PostWithCommentsState extends State { + String _content; + + Future> _comments; + + @override + void initState() { + super.initState(); + + _content = widget.post.content.rendered; + _content = _content.replaceAll('localhost', '192.168.6.165'); + + fetchComments(); + } + + void fetchComments() { + setState(() { + _comments = widget.wordPress.fetchCommentsAsHierarchy( + params: wp.ParamsCommentList( + includePostIDs: [widget.post.id], + )); + }); + } + + @override + Widget build(BuildContext context) { + return CustomScrollView( + slivers: [ + SliverList( + delegate: SliverChildListDelegate( + [ + Html( + data: _content, + // blockSpacing: 0.0, + ), + Divider(), + Row( + children: [ + Icon(Icons.comment), + Text('Comments'), + ], + ), + Divider(), + ], + ), + ), + FutureBuilder( + future: _comments, + builder: (context, snapshot) { + return SliverList( + delegate: _buildCommentsSection(snapshot), + ); + }, + ), + ], + ); + } + + SliverChildDelegate _buildCommentsSection( + AsyncSnapshot> snapshot) { + if (snapshot.hasData) { + return _buildComments(snapshot.data); + } else if (snapshot.hasError) { + return SliverChildListDelegate([ + Text( + 'Error fetching comments: ${snapshot.error.toString()}', + style: TextStyle( + color: Colors.red, + ), + ) + ]); + } + + return SliverChildListDelegate( + [ + Center( + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Colors.blue), + ), + ), + ], + ); + } + + SliverChildBuilderDelegate _buildComments( + List comments) { + return SliverChildBuilderDelegate( + (BuildContext context, int i) { + if (comments == null || comments.length == 0) { + return Center( + child: Padding( + padding: EdgeInsets.all(8.0), + child: Text( + 'No comments', + style: Theme.of(context).textTheme.bodyText1, + ), + ), + ); + } + + if (i % 2 != 0) { + return Divider(); + } + return _buildCommentTile(comments[(i / 2).ceil()]); + }, + childCount: + comments == null || comments.length == 0 ? 1 : comments.length * 2, + ); + } + + Widget _buildCommentTile(wp.CommentHierarchy root) { + if (root.children == null) { + return Padding( + padding: EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Html( + data: root.comment.content.rendered, + // blockSpacing: 0.0, + ), + Text( + root.comment.authorName, + style: TextStyle( + color: Colors.grey, + fontWeight: FontWeight.w300, + ), + ), + ], + ), + ); + } else { + return ExpansionTile( + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Html( + data: root.comment.content.rendered, + // blockSpacing: 0.0, + ), + Text( + root.comment.authorName, + style: TextStyle( + color: Colors.grey, + fontWeight: FontWeight.w300, + ), + ), + ], + ), + children: root.children.map((c) { + return Padding( + padding: EdgeInsets.only(left: 16.0), + child: _buildCommentTile(c), + ); + }).toList(), + ); + } + } +} diff --git a/example/pubspec.yaml b/example/pubspec.yaml index a285b6a..e8f5d8e 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -8,6 +8,7 @@ description: Wordpress API testing example. # build by specifying --build-name and --build-number, respectively. # Read more about versioning at semver.org. version: 1.0.0+1 +publish_to: none environment: sdk: ">=2.0.0-dev.68.0 <3.0.0" @@ -17,10 +18,11 @@ dependencies: path: ../ flutter: sdk: flutter + flutter_html: ^2.2.1 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.2 + cupertino_icons: ^1.0.4 dev_dependencies: flutter_test: diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart index 127f14c..d0684db 100644 --- a/example/test/widget_test.dart +++ b/example/test/widget_test.dart @@ -13,7 +13,7 @@ import 'package:flutter_wordpress_example/main.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); + await tester.pumpWidget(WordPressApp()); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget); diff --git a/lib/constants.dart b/lib/constants.dart index 986e615..0a2a188 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -1,12 +1,17 @@ -const URL_WP_BASE = '/wp-json/wp/v2'; const URL_JWT_BASE = '/wp-json/jwt-auth/v1'; +const URL_WP_BASE = '/wp-json/wp/v2'; const URL_JWT_TOKEN = '$URL_JWT_BASE/token'; const URL_JWT_TOKEN_VALIDATE = '$URL_JWT_BASE/token/validate'; +const URL_CATEGORIES = '$URL_WP_BASE/categories'; +const URL_COMMENTS = '$URL_WP_BASE/comments'; +const URL_MEDIA = '$URL_WP_BASE/media'; +const URL_PAGES = '$URL_WP_BASE/pages'; const URL_POSTS = '$URL_WP_BASE/posts'; +const URL_TAGS = '$URL_WP_BASE/tags'; const URL_USERS = '$URL_WP_BASE/users'; -const URL_COMMENTS = '$URL_WP_BASE/comments'; +const URL_USER_ME = '$URL_WP_BASE/users/me'; enum WordPressAuthenticator { JWT, @@ -19,7 +24,7 @@ enum Order { desc, } -enum PostsOrderBy { +enum PostOrderBy { author, date, id, @@ -30,7 +35,7 @@ enum PostsOrderBy { slug, title, } -enum PostStatus { +enum PostPageStatus { publish, future, draft, @@ -45,7 +50,7 @@ enum PostPingStatus { open, closed, } -enum ObjectFormat { +enum PostFormat { standard, aside, chat, @@ -58,7 +63,7 @@ enum ObjectFormat { audio, } -enum UsersOrderBy { +enum UserOrderBy { id, include, name, @@ -67,15 +72,8 @@ enum UsersOrderBy { email, url, } -enum UserRole { - subscriber, - contributor, - author, - editor, - administrator, -} -enum CommentsOrderBy { +enum CommentOrderBy { date, date_gmt, id, @@ -96,6 +94,55 @@ enum CommentType { //TODO: Add all comment types } +enum CategoryTagOrderBy { + id, + include, + name, + slug, + term_group, + description, + count, +} + +enum PageOrderBy { + author, + date, + id, + include, + modified, + parent, + relevance, + slug, + title, + menu_order, +} + +enum MediaOrderBy { + author, + date, + id, + include, + modified, + parent, + relevance, + slug, + title, +} +enum MediaStatus { + inherit, + publish, + future, + draft, + pending, + private, +} +enum MediaType { + image, + video, + audio, + application, +} + /// Converts an enum string to enum value name. String enumStringToName(String enumString) { return enumString.split('.')[1]; @@ -104,7 +151,7 @@ String enumStringToName(String enumString) { /// Formats a list of [items] to a comma(,) separated string to pass it as a /// URL parameter. String listToUrlString(List items) { - if (items == null || items.length == 0) return ''; + if (items.length == 0) return ''; return items.join(','); } diff --git a/lib/flutter_wordpress.dart b/lib/flutter_wordpress.dart index d6a81a9..e70f57e 100644 --- a/lib/flutter_wordpress.dart +++ b/lib/flutter_wordpress.dart @@ -1,5 +1,5 @@ -/// This library uses WordPress REST API V2 to provide a way for your application -/// to interact with your WordPress website. +/// This library uses [WordPress REST API V2](https://developer.wordpress.org/rest-api/) +/// to provide a way for your application to interact with your WordPress website. /// /// We use terminologies similar to the [WordPress REST API](https://developer.wordpress.org/rest-api/) /// @@ -10,91 +10,85 @@ /// 2. [JWT Authentication for WP REST API](https://wordpress.org/plugins/jwt-authentication-for-wp-rest-api/) library flutter_wordpress; -import 'dart:async' as async; import 'dart:convert'; +import 'dart:io'; -import 'package:meta/meta.dart'; import 'package:http/http.dart' as http; -import 'schemas/jwt_response.dart'; -import 'schemas/avatar_urls.dart'; -import 'schemas/capabilities.dart'; +import 'constants.dart'; +import 'requests/params_category_list.dart'; +import 'requests/params_comment_list.dart'; +import 'requests/params_media_list.dart'; +import 'requests/params_page_list.dart'; +import 'requests/params_post_list.dart'; +import 'requests/params_tag_list.dart'; +import 'requests/params_user_list.dart'; import 'schemas/category.dart'; import 'schemas/comment.dart'; -import 'schemas/content.dart'; -import 'schemas/excerpt.dart'; -import 'schemas/guid.dart'; -import 'schemas/labels.dart'; -import 'schemas/links.dart'; +import 'schemas/comment_hierarchy.dart'; +import 'schemas/fetch_user_result.dart'; +import 'schemas/jwt_response.dart'; import 'schemas/media.dart'; import 'schemas/page.dart'; -import 'schemas/post_statuses.dart'; -import 'schemas/post_types.dart'; import 'schemas/post.dart'; -import 'schemas/settings.dart'; import 'schemas/tag.dart'; -import 'schemas/taxonomies.dart'; -import 'schemas/title.dart'; import 'schemas/user.dart'; import 'schemas/wordpress_error.dart'; -import 'constants.dart'; - -import 'requests/params_post_list.dart'; -import 'requests/params_user_list.dart'; -import 'requests/params_comment_list.dart'; - -export 'schemas/jwt_response.dart'; +export 'constants.dart'; +export 'requests/params_category_list.dart'; +export 'requests/params_comment_list.dart'; +export 'requests/params_media_list.dart'; +export 'requests/params_page_list.dart'; +export 'requests/params_post_list.dart'; +export 'requests/params_tag_list.dart'; +export 'requests/params_user_list.dart'; export 'schemas/avatar_urls.dart'; -export 'schemas/capabilities.dart'; export 'schemas/category.dart'; export 'schemas/comment.dart'; +export 'schemas/comment_hierarchy.dart'; export 'schemas/content.dart'; export 'schemas/excerpt.dart'; +export 'schemas/fetch_user_result.dart'; export 'schemas/guid.dart'; +export 'schemas/jwt_response.dart'; export 'schemas/labels.dart'; export 'schemas/links.dart'; export 'schemas/media.dart'; export 'schemas/page.dart'; -export 'schemas/post_statuses.dart'; -export 'schemas/post_types.dart'; export 'schemas/post.dart'; export 'schemas/settings.dart'; export 'schemas/tag.dart'; -export 'schemas/taxonomies.dart'; export 'schemas/title.dart'; export 'schemas/user.dart'; export 'schemas/wordpress_error.dart'; -export 'constants.dart'; - -export 'requests/params_post_list.dart'; -export 'requests/params_user_list.dart'; -export 'requests/params_comment_list.dart'; - -/// If [WordPressAuthenticator.ApplicationPasswords] is used as an authenticator, -/// [adminName] and [adminKey] is necessary for authentication. -/// https://wordpress.org/plugins/application-passwords/ +/// All WordPress related functionality are defined under this class. class WordPress { - String _baseUrl; - WordPressAuthenticator _authenticator; + late String _baseUrl; + late WordPressAuthenticator _authenticator; + String _token = ""; Map _urlHeader = { 'Authorization': '', }; - WordPress( - {@required String baseUrl, - WordPressAuthenticator authenticator, - String adminName, - String adminKey}) { + /// If [WordPressAuthenticator.ApplicationPasswords] is used as an authenticator, + /// [adminName] and [adminKey] is necessary for authentication. + /// https://wordpress.org/plugins/application-passwords/ + WordPress({ + required String baseUrl, + required WordPressAuthenticator authenticator, + String? adminName, + String? adminKey, + }) { this._baseUrl = baseUrl.endsWith('/') ? baseUrl.substring(0, baseUrl.length - 1) : baseUrl; this._authenticator = authenticator; - if (adminName != null && adminKey != null && this._authenticator != null) { + if (adminName != null && adminKey != null) { switch (this._authenticator) { case WordPressAuthenticator.ApplicationPasswords: String str = '$adminName:$adminKey'; @@ -108,8 +102,14 @@ class WordPress { } } - async.Future authenticateUser( - {@required username, @required password}) async { + /// This returns a [User] object when a user with valid [username] and [password] + /// has been successfully authenticated. + /// + /// In case of an error, a [WordPressError] object is thrown. + Future authenticateUser({ + required username, + required password, + }) async { if (_authenticator == WordPressAuthenticator.ApplicationPasswords) { return _authenticateViaAP(username, password); } else if (_authenticator == WordPressAuthenticator.JWT) { @@ -118,44 +118,68 @@ class WordPress { return fetchUser(username: username); } - async.Future _authenticateViaAP(username, password) async { - //TODO: Implement Application Passwords User Authentication + Future _authenticateViaAP(username, password) async { return fetchUser(username: username); } - async.Future _authenticateViaJWT(username, password) async { + Future _authenticateViaJWT(String username, String password) async { final body = { 'username': username, 'password': password, }; final response = await http.post( - _baseUrl + URL_JWT_TOKEN, + Uri.parse(_baseUrl + URL_JWT_TOKEN), body: body, ); - if (response.statusCode == 200) { - JWTResponse authResponse = - JWTResponse.fromJson(json.decode(response.body)); + if (response.statusCode >= 200 && response.statusCode < 300) { + JWTResponse authResponse = JWTResponse.fromJson( + json.decode(response.body), + ); + _token = authResponse.token!; _urlHeader['Authorization'] = 'Bearer ${authResponse.token}'; return fetchUser(email: authResponse.userEmail); } else { try { - WordPressError err = - WordPressError.fromJson(json.decode(response.body)); - throw err; + throw new WordPressError.fromJson(json.decode(response.body)); } catch (e) { throw new WordPressError(message: response.body); } } } - /// This returns [User] object if the user with [id], [email] or [username] + String getToken() { + return _token; + } + + Future authenticateViaToken(String token) async { + _urlHeader['Authorization'] = 'Bearer ${token}'; + + final response = await http.post( + Uri.parse(_baseUrl + URL_JWT_TOKEN_VALIDATE), + headers: _urlHeader, + ); + + if (response.statusCode >= 200 && response.statusCode < 300) { + return fetchMeUser(); + } else { + throw new WordPressError(message: response.body); + } + } + + /// This returns a [User] object if the user with [id], [email] or [username] /// exists. Otherwise throws [WordPressError]. /// /// Only one parameter is enough to search for the user. - async.Future fetchUser({int id, String email, String username}) async { + /// + /// In case of an error, a [WordPressError] object is thrown. + Future fetchUser({ + int? id, + String? email, + String? username, + }) async { final StringBuffer url = new StringBuffer(_baseUrl + URL_USERS); final Map params = { 'search': '', @@ -168,14 +192,45 @@ class WordPress { url.write(constructUrlParams(params)); - final response = await http.get(url.toString(), headers: _urlHeader); + final response = await http.get( + Uri.parse(url.toString()), + headers: _urlHeader, + ); - if (response.statusCode == 200) { + if (response.statusCode >= 200 && response.statusCode < 300) { final jsonStr = json.decode(response.body); if (jsonStr.length == 0) throw new WordPressError( code: 'wp_empty_list', message: "No users found"); + return User.fromJson(jsonStr[0]); + } else { + try { + WordPressError err = WordPressError.fromJson( + json.decode(response.body), + ); + throw err; + } catch (e) { + throw new WordPressError(message: response.body); + } + } + } + + /// This returns the me [User] object with the current token. Otherwise throws [WordPressError]. + /// + /// In case of an error, a [WordPressError] object is thrown. + Future fetchMeUser() async { + final response = await http.get( + Uri.parse(_baseUrl + URL_USER_ME), + headers: _urlHeader, + ); + + if (response.statusCode >= 200 && response.statusCode < 300) { + final jsonStr = json.decode(response.body); + if (jsonStr.length == 0) + throw new WordPressError( + code: 'wp_empty_user', message: "No user found"); + return User.fromJson(jsonStr); } else { try { WordPressError err = @@ -187,24 +242,369 @@ class WordPress { } } - /// This methods returns a list of [Post] based on the filter parameters + /// This returns a list of [Post] based on the filter parameters /// specified through [ParamsPostList] object. By default it returns only /// [ParamsPostList.perPage] number of posts in page [ParamsPostList.pageNum]. - async.Future> fetchPosts({@required ParamsPostList params}) async { - final StringBuffer url = new StringBuffer(_baseUrl + URL_POSTS); + /// + /// [fetchAuthor], [fetchComments], [fetchCategories], [fetchTags], + /// [fetchFeaturedMedia] and [fetchAttachments] will fetch and set [Post.author], + /// [Post.comments], [Post.categories], [Post.tags], [Post.featuredMedia] and + /// [Post.attachments] respectively. If they are non-existent, their values will + /// null. + /// + /// (**Note:** *Set only those fetch boolean parameters which you need because + /// the more information to fetch, the longer it will take to return all Posts*) + /// + /// [fetchAll] will make as many API requests as is needed to get all posts. + /// This may take a while. + /// + /// In case of an error, a [WordPressError] object is thrown. + Future> fetchPosts( + {required ParamsPostList postParams, + bool fetchAuthor = false, + bool fetchComments = false, + Order orderComments = Order.desc, + CommentOrderBy orderCommentsBy = CommentOrderBy.date, + bool fetchCategories = false, + bool fetchTags = false, + bool fetchFeaturedMedia = false, + bool fetchAttachments = false, + String postType = "posts", + bool fetchAll = false}) async { + int bulkBatchNum = 100; - url.write(params.toString()); + if (fetchAll) { + postParams = postParams.copyWith(perPage: bulkBatchNum); + } + + Map authorsByID = {}; + Map authorIDForPostIDs = {}; + Map postsByID = {}; + Map> commentsForPostIDs = {}; + Map featuredMediaIDForPostIDs = {}; + Map featuredMediaByID = {}; + Map categoriesByID = {}; + Map tagsByID = {}; + Map> attachmentsForPostIDs = {}; + + /// This function fetches post information such as author, comments, categories, + /// tags, featuredMedia and attachments. + var _postPrep = ({ + required Post post, + bool setAuthor = false, + bool setComments = false, + bool setCategories = false, + bool setTags = false, + bool setFeaturedMedia = false, + bool setAttachments = false, + }) async { + if (setAuthor && post.id != null && post.authorID != null) { + authorIDForPostIDs[post.id!] = post.authorID!; + } + if (setComments && post.id != null) { + commentsForPostIDs[post.id!] = []; + } + if (setCategories) { + post.categoryIDs + ?.forEach((id) => categoriesByID[id] = Category(id: id)); + } + if (setTags) { + post.tagIDs?.forEach((id) => tagsByID[id] = Tag(id: id)); + } + if (setFeaturedMedia && post.id != null && post.featuredMediaID != null) { + featuredMediaIDForPostIDs[post.id!] = post.featuredMediaID!; + } + if (setAttachments && post.id != null) { + attachmentsForPostIDs[post.id!] = []; + } + return post; + }; + + final StringBuffer url = + new StringBuffer(_baseUrl + URL_WP_BASE + "/" + postType); + + url.write(postParams.toString()); + + final response = + await http.get(Uri.parse(url.toString()), headers: _urlHeader); + + if (response.statusCode >= 200 && response.statusCode < 300) { + final list = json.decode(response.body); + + for (final post in list) { + var pt = await _postPrep( + post: Post.fromJson(post), + setAuthor: fetchAuthor, + setComments: fetchComments, + setFeaturedMedia: fetchFeaturedMedia, + setCategories: fetchCategories, + setAttachments: fetchAttachments, + ); + if (pt.id != null) postsByID[pt.id!] = pt; + } + + var pids = postsByID.keys.toList(); + + //handler to fetch authors + var handleGettingAuthors = ({bool setAuthor = false}) async { + if (setAuthor) { + var aids = authorIDForPostIDs.values.toList(); + FetchUsersResult authResult = + await fetchUsers(params: ParamsUserList(includeUserIDs: aids)); + authorsByID = Map.fromIterable(authResult.users, + key: (u) => u.id, value: (u) => u); + if (authResult.users.length != authResult.totalUsers && + authResult.totalUsers != null) { + var stride = authResult.users.length; + var numOfCalls = (authResult.totalUsers! / stride) + 1; + for (var i = 2; i <= numOfCalls; i++) { + FetchUsersResult result = await fetchUsers( + params: ParamsUserList( + includeUserIDs: aids, + pageNum: i, + perPage: stride, + )); + result.users.forEach((u) { + if (u.id != null) authorsByID[u.id!] = u; + }); + } + } + } + }; + + //handler to fetch comments + var handleGettingComments = ({bool setComments = false}) async { + if (setComments) { + List comments = await this.fetchComments( + params: ParamsCommentList( + includePostIDs: pids, + order: orderComments, + orderBy: orderCommentsBy, + perPage: bulkBatchNum, + pageNum: 1, + )); + if (comments.length != 0) { + comments.forEach((comment) { + commentsForPostIDs[comment.post]?.add(comment); + }); + var i = 2; + while (comments.length == bulkBatchNum) { + comments = await this.fetchComments( + params: ParamsCommentList( + includePostIDs: pids, + order: orderComments, + orderBy: orderCommentsBy, + perPage: bulkBatchNum, + pageNum: i, + )); + comments.forEach((comment) { + commentsForPostIDs[comment.post]?.add(comment); + }); + i += 1; + } + } + } + }; - final response = await http.get(url.toString(), headers: _urlHeader); + //handler to fetch categories + var handleGettingCategories = ({bool setCategories = false}) async { + if (setCategories) { + var cids = categoriesByID.keys.toList(); + List categories = await this.fetchCategories( + params: ParamsCategoryList( + includeCategoryIDs: cids, + perPage: bulkBatchNum, + pageNum: 1, + )); + if (categories.length != 0) { + categories.forEach((cat) { + if (cat.id != null) categoriesByID[cat.id!] = cat; + }); + var i = 2; + while (categories.length == bulkBatchNum) { + categories = await this.fetchCategories( + params: ParamsCategoryList( + includeCategoryIDs: cids, + perPage: bulkBatchNum, + pageNum: i, + )); + categories.forEach((cat) { + if (cat.id != null) categoriesByID[cat.id!] = cat; + }); + i += 1; + } + } + } + }; - if (response.statusCode == 200) { - List posts = new List(); + //handler to fetch tags + var handleGettingTags = ({bool setTags = false}) async { + var tids = tagsByID.keys.toList(); + if (setTags) { + List tags = await this.fetchTags( + params: ParamsTagList( + includeTagIDs: tids, + perPage: bulkBatchNum, + pageNum: 1, + )); + if (tags.length != 0) { + tags.forEach((tag) { + if (tag.id != null) tagsByID[tag.id!] = tag; + }); + var i = 2; + while (tags.length == bulkBatchNum) { + tags = await this.fetchTags( + params: ParamsTagList( + includeTagIDs: tids, + perPage: bulkBatchNum, + pageNum: i, + )); + tags.forEach((tag) { + if (tag.id != null) tagsByID[tag.id!] = tag; + }); + i += 1; + } + } + } + }; - dynamic list = json.decode(response.body); - list.forEach((post) { - posts.add(Post.fromJson(post)); + //handler to fetch featured media + var handleGettingFeaturedMedia = ({bool setFeaturedMedia = false}) async { + if (setFeaturedMedia) { + var fids = featuredMediaIDForPostIDs.values.toList(); + List media = await this.fetchMediaList( + params: ParamsMediaList( + includeMediaIDs: fids, perPage: bulkBatchNum, pageNum: 1), + ); + if (media.length != 0) { + media.forEach((fm) { + if (fm.id != null) featuredMediaByID[fm.id!] = fm; + }); + var i = 2; + while (media.length == bulkBatchNum) { + media = await this.fetchMediaList( + params: ParamsMediaList( + includeMediaIDs: fids, + perPage: bulkBatchNum, + pageNum: i, + ), + ); + media.forEach((fm) { + if (fm.id != null) featuredMediaByID[fm.id!] = fm; + }); + i += 1; + } + } + } + }; + + //handler to fetch attachments + var handleGettingAttachments = ({bool setAttachments = false}) async { + if (setAttachments) { + List attachments = await this.fetchMediaList( + params: ParamsMediaList( + includeParentIDs: pids, + perPage: bulkBatchNum, + pageNum: 1, + ), + ); + if (attachments.length != 0) { + attachments.forEach((attachment) { + attachmentsForPostIDs[attachment.post]?.add(attachment); + }); + var i = 2; + while (attachments.length == bulkBatchNum) { + attachments = await this.fetchMediaList( + params: ParamsMediaList( + includeParentIDs: pids, + perPage: bulkBatchNum, + pageNum: i, + ), + ); + attachments.forEach((attachment) { + attachmentsForPostIDs[attachment.post]?.add(attachment); + }); + i += 1; + } + } + } + }; + + await Future.wait([ + handleGettingAuthors(setAuthor: fetchAuthor), + handleGettingComments(setComments: fetchComments), + handleGettingCategories(setCategories: fetchCategories), + handleGettingTags(setTags: fetchTags), + handleGettingFeaturedMedia(setFeaturedMedia: fetchFeaturedMedia), + handleGettingAttachments(setAttachments: fetchAttachments), + ]); + + //fill posts + postsByID.values.forEach((post) { + //handle Author + if (fetchAuthor) { + post.author = authorsByID[post.authorID]; + } + //handle comments + if (fetchComments) { + post.comments = commentsForPostIDs[post.id]; + post.commentsHierarchy = []; + if (post.comments != null) { + post.comments?.forEach((comment) { + if (comment.parent == 0) + post.commentsHierarchy?.add( + _commentHierarchyBuilder(post.comments ?? [], comment)); + }); + } + } + //handle categories + if (fetchCategories) { + post.categories = []; + post.categoryIDs?.forEach((catid) { + if (categoriesByID[catid] != null) + post.categories?.add(categoriesByID[catid]!); + }); + } + //handle tags + if (fetchTags) { + post.tags = []; + post.tagIDs?.forEach((id) { + if (tagsByID[id] != null) post.tags?.add(tagsByID[id]!); + }); + } + //handle featured media + if (fetchFeaturedMedia) { + post.featuredMedia = + featuredMediaByID[featuredMediaIDForPostIDs[post.id]]; + } + //handle attachments + if (fetchAttachments) { + post.attachments = attachmentsForPostIDs[post.id]; + } }); - return posts; + + if (fetchAll && response.headers["x-wp-totalpages"] != null) { + final totalPages = int.parse(response.headers["x-wp-totalpages"]!); + + for (int i = postParams.pageNum + 1; i <= totalPages; ++i) { + (await fetchPosts( + postParams: postParams.copyWith(pageNum: i), + fetchAuthor: fetchAuthor, + fetchComments: fetchComments, + orderComments: orderComments, + orderCommentsBy: orderCommentsBy, + fetchCategories: fetchCategories, + fetchTags: fetchTags, + fetchFeaturedMedia: fetchFeaturedMedia, + fetchAttachments: fetchAttachments, + )) + .forEach((p) { + if (p.id != null) postsByID[p.id!] = p; + }); + } + } + + return postsByID.values.toList(); } else { try { WordPressError err = @@ -216,23 +616,104 @@ class WordPress { } } - /// This methods returns a list of [User] based on the filter parameters + ///This recursive function builds the hierarchy of comments for the given post + ///and comment. Only parent comments (direct comments to post) need to be + ///supplied. + CommentHierarchy _commentHierarchyBuilder( + List commentList, + Comment comment, + ) { + final childComments = commentList.where((ele) => + ele.id != comment.id && ele.parent != 0 && ele.parent == comment.id); + + if (childComments.length == 0) { + return new CommentHierarchy(comment: comment); + } else { + List children = []; + childComments.forEach((c) { + children.add(_commentHierarchyBuilder(commentList, c)); + }); + return new CommentHierarchy( + comment: comment, + children: children, + ); + } + } + + /// This returns a list of [Page] based on the filter parameters + /// specified through [ParamsPageList] object. By default it returns only + /// [ParamsPageList.perPage] number of pages in page [ParamsPageList.pageNum]. + /// + /// In case of an error, a [WordPressError] object is thrown. + Future> fetchPages({required ParamsPageList params}) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_PAGES); + + url.write(params.toString()); + + final response = + await http.get(Uri.parse(url.toString()), headers: _urlHeader); + + if (response.statusCode >= 200 && response.statusCode < 300) { + List pages = []; + final list = json.decode(response.body); + list.forEach((page) { + pages.add(Page.fromJson(page)); + }); + return pages; + } else { + try { + WordPressError err = + WordPressError.fromJson(json.decode(response.body)); + throw err; + } catch (e) { + throw new WordPressError(message: response.body); + } + } + } + + /// This returns an object FetchUsersResult based on the filter parameters /// specified through [ParamsUserList] object. By default it returns only /// [ParamsUserList.perPage] number of users in page [ParamsUserList.pageNum]. - async.Future> fetchUsers({@required ParamsUserList params}) async { + /// + /// In case of an error, a [WordPressError] object is thrown. + Future fetchUsers({required ParamsUserList params}) async { final StringBuffer url = new StringBuffer(_baseUrl + URL_USERS); url.write(params.toString()); - final response = await http.get(url.toString(), headers: _urlHeader); + return _doUsersFetch(url); + } + + /// This returns an object FetchUsersResult as defined by the input, based on the filter parameters + /// specified through [ParamsUserList] object. The url it fetches to is defined by the input [String] path. By default it returns only + /// [ParamsUserList.perPage] number of users in page [ParamsUserList.pageNum]. + /// + /// In case of an error, a [WordPressError] object is thrown. + Future fetchCustomUsers({ + required String path, + required ParamsUserList params, + }) async { + final StringBuffer url = new StringBuffer(_baseUrl + path); + url.write(params.toString()); + + return _doUsersFetch(url); + } + + Future _doUsersFetch(StringBuffer url) async { + final response = await http.get( + Uri.parse(url.toString()), + headers: _urlHeader, + ); + + if (response.statusCode >= 200 && response.statusCode < 300) { + List users = []; + final list = json.decode(response.body); + int totalUsers = int.parse(response.headers['x-wp-total']!); - if (response.statusCode == 200) { - List users = new List(); - dynamic list = json.decode(response.body); list.forEach((user) { users.add(User.fromJson(user)); }); - return users; + return FetchUsersResult(users, totalUsers); } else { try { WordPressError err = @@ -244,20 +725,26 @@ class WordPress { } } - /// This methods returns a list of [Comment] based on the filter parameters + /// This returns a list of [Comment] based on the filter parameters /// specified through [ParamsCommentList] object. By default it returns only /// [ParamsCommentList.perPage] number of comments in page [ParamsCommentList.pageNum]. - async.Future> fetchComments( - {@required ParamsCommentList params}) async { + /// + /// In case of an error, a [WordPressError] object is thrown. + Future> fetchComments({ + required ParamsCommentList params, + }) async { final StringBuffer url = new StringBuffer(_baseUrl + URL_COMMENTS); url.write(params.toString()); - final response = await http.get(url.toString(), headers: _urlHeader); + final response = await http.get( + Uri.parse(url.toString()), + headers: _urlHeader, + ); - if (response.statusCode == 200) { - List comments = new List(); - dynamic list = json.decode(response.body); + if (response.statusCode >= 200 && response.statusCode < 300) { + List comments = []; + final list = json.decode(response.body); list.forEach((comment) { comments.add(Comment.fromJson(comment)); }); @@ -272,4 +759,476 @@ class WordPress { } } } + + /// This returns a list of [CommentHierarchy] based on the filter parameters + /// specified through [ParamsCommentList] object. The list returned has all + /// parent comments (i.e. comments directed towards posts) with + /// [CommentHierarchy.children] containing the replies to that comment. + /// + /// In case of an error, a [WordPressError] object is thrown. + Future> fetchCommentsAsHierarchy({ + required ParamsCommentList params, + }) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_COMMENTS); + + url.write(params.toString()); + + final response = await http.get( + Uri.parse(url.toString()), + headers: _urlHeader, + ); + + if (response.statusCode >= 200 && response.statusCode < 300) { + List comments = []; + List commentsHierarchy = []; + final list = json.decode(response.body); + list.forEach((comment) { + comments.add(Comment.fromJson(comment)); + }); + + comments.forEach((comment) { + if (comment.parent == 0) + commentsHierarchy.add(_commentHierarchyBuilder(comments, comment)); + }); + return commentsHierarchy; + } else { + try { + WordPressError err = + WordPressError.fromJson(json.decode(response.body)); + throw err; + } catch (e) { + throw new WordPressError(message: response.body); + } + } + } + + /// This returns a list of [Category] based on the filter parameters + /// specified through [ParamsCategoryList] object. By default it returns only + /// [ParamsCategoryList.perPage] number of categories in page [ParamsCategoryList.pageNum]. + /// + /// In case of an error, a [WordPressError] object is thrown. + Future> fetchCategories({ + required ParamsCategoryList params, + bool fetchAll = false, + }) async { + if (fetchAll) { + params = params.copyWith(perPage: 100); + } + + final StringBuffer url = new StringBuffer(_baseUrl + URL_CATEGORIES); + + url.write(params.toString()); + + final response = await http.get( + Uri.parse(url.toString()), + headers: _urlHeader, + ); + + if (response.statusCode >= 200 && response.statusCode < 300) { + List categories = []; + final list = json.decode(response.body); + list.forEach((category) { + categories.add(Category.fromJson(category)); + }); + + if (fetchAll && response.headers["x-wp-totalpages"] != null) { + final totalPages = int.parse(response.headers["x-wp-totalpages"]!); + + for (int i = params.pageNum + 1; i <= totalPages; ++i) { + categories.addAll( + await fetchCategories(params: params.copyWith(pageNum: i))); + } + } + + return categories; + } else { + try { + WordPressError err = + WordPressError.fromJson(json.decode(response.body)); + throw err; + } catch (e) { + throw new WordPressError(message: response.body); + } + } + } + + /// This returns a list of [Tag] based on the filter parameters + /// specified through [ParamsTagList] object. By default it returns only + /// [ParamsTagList.perPage] number of tags in page [ParamsTagList.pageNum]. + /// + /// In case of an error, a [WordPressError] object is thrown. + Future> fetchTags({required ParamsTagList params}) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_TAGS); + + url.write(params.toString()); + + final response = await http.get( + Uri.parse(url.toString()), + headers: _urlHeader, + ); + + if (response.statusCode >= 200 && response.statusCode < 300) { + List tags = []; + final list = json.decode(response.body); + list.forEach((tag) { + tags.add(Tag.fromJson(tag)); + }); + return tags; + } else { + try { + WordPressError err = + WordPressError.fromJson(json.decode(response.body)); + throw err; + } catch (e) { + throw new WordPressError(message: response.body); + } + } + } + + /// This returns a list of [Media] based on the filter parameters + /// specified through [ParamsMediaList] object. By default it returns only + /// [ParamsMediaList.perPage] number of tags in page [ParamsMediaList.pageNum]. + /// + /// In case of an error, a [WordPressError] object is thrown. + Future> fetchMediaList({required ParamsMediaList params}) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_MEDIA); + + url.write(params.toString()); + + final response = await http.get( + Uri.parse(url.toString()), + headers: _urlHeader, + ); + + if (response.statusCode >= 200 && response.statusCode < 300) { + List media = []; + final list = json.decode(response.body); + list.forEach((m) { + media.add(Media.fromJson(m)); + }); + return media; + } else { + try { + WordPressError err = + WordPressError.fromJson(json.decode(response.body)); + throw err; + } catch (e) { + throw new WordPressError(message: response.body); + } + } + } + + /// This is used to create a [Post] in the site. Before this method can be called, + /// [User] creating the post needs to be authenticated first by calling + /// [WordPress.authenticateUser]. On success, the [Post] object is returned containing + /// post information. + /// + /// In case of an error, a [WordPressError] object is thrown. + /// + /// + + Future createPost({required Post post}) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_POSTS); + + final response = await http.post( + Uri.parse(url.toString()), + headers: _urlHeader, + body: post.toJson(), + ); + + if (response.statusCode >= 200 && response.statusCode < 300) { + return Post.fromJson(json.decode(response.body)); + } else { + try { + WordPressError err = + WordPressError.fromJson(json.decode(response.body)); + throw err; + } catch (e) { + throw new WordPressError(message: response.body); + } + } + } + +// yahya - @mymakarim + + Future uploadMedia(File image) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_MEDIA); + var file = image.readAsBytesSync(); + final response = await http.post( + Uri.parse(url.toString()), + headers: { + "Content-Type": "image/png", + "Content-Disposition": "form-data; filename=firstIg.png", + "Authorization": "${_urlHeader['Authorization']}" + }, + body: file, + ); + + if (response.statusCode >= 200 && response.statusCode < 300) { + return json.decode(response.body); + } else { + try { + WordPressError err = + WordPressError.fromJson(json.decode(response.body)); + throw err; + } catch (e) { + throw new WordPressError(message: response.body); + } + } + } + +// uploadMedia function added by: @GarvMaggu + + Future createUser({required User user}) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_USERS); + + HttpClient httpClient = new HttpClient(); + HttpClientRequest request = + await httpClient.postUrl(Uri.parse(url.toString())); + request.headers + .set(HttpHeaders.contentTypeHeader, "application/json; charset=UTF-8"); + request.headers.set(HttpHeaders.acceptHeader, "application/json"); + request.headers.set('Authorization', "${_urlHeader['Authorization']}"); + + request.add(utf8.encode(json.encode(user.toJson()))); + HttpClientResponse response = await request.close(); + + if (response.statusCode >= 200 && response.statusCode < 300) { + return true; + } else { + response.transform(utf8.decoder).listen((contents) { + try { + WordPressError err = WordPressError.fromJson(json.decode(contents)); + throw err; + } catch (e) { + throw new WordPressError(message: contents); + } + }); + } + + return false; + } + +// ===================== +// UPDATE START +// ===================== + + Future updatePost({required int id, required Post post}) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_POSTS + '/$id'); + + HttpClient httpClient = new HttpClient(); + HttpClientRequest request = + await httpClient.postUrl(Uri.parse(url.toString())); + request.headers + .set(HttpHeaders.contentTypeHeader, "application/json; charset=UTF-8"); + request.headers.set(HttpHeaders.acceptHeader, "application/json"); + request.headers.set('Authorization', "${_urlHeader['Authorization']}"); + + request.add(utf8.encode(json.encode(post.toJson()))); + HttpClientResponse response = await request.close(); + + if (response.statusCode >= 200 && response.statusCode < 300) { + return true; + } else { + response.transform(utf8.decoder).listen((contents) { + try { + WordPressError err = WordPressError.fromJson(json.decode(contents)); + throw err; + } catch (e) { + throw new WordPressError(message: contents); + } + }); + } + return false; + } + + Future updateComment( + {required int id, required Comment comment}) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_COMMENTS + '/$id'); + + HttpClient httpClient = new HttpClient(); + HttpClientRequest request = + await httpClient.postUrl(Uri.parse(url.toString())); + request.headers + .set(HttpHeaders.contentTypeHeader, "application/json; charset=UTF-8"); + request.headers.set(HttpHeaders.acceptHeader, "application/json"); + request.headers.set('Authorization', "${_urlHeader['Authorization']}"); + + request.add(utf8.encode(json.encode(comment.toJson()))); + HttpClientResponse response = await request.close(); + + if (response.statusCode >= 200 && response.statusCode < 300) { + return true; + } else { + response.transform(utf8.decoder).listen((contents) { + try { + WordPressError err = WordPressError.fromJson(json.decode(contents)); + throw err; + } catch (e) { + throw new WordPressError(message: contents); + } + }); + } + return false; + } + + Future updateUser({required int id, required User user}) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_USERS + '/$id'); + + HttpClient httpClient = new HttpClient(); + HttpClientRequest request = + await httpClient.postUrl(Uri.parse(url.toString())); + request.headers + .set(HttpHeaders.contentTypeHeader, "application/json; charset=UTF-8"); + request.headers.set(HttpHeaders.acceptHeader, "application/json"); + request.headers.set('Authorization', "${_urlHeader['Authorization']}"); + + request.add(utf8.encode(json.encode(user.toJson()))); + HttpClientResponse response = await request.close(); + + if (response.statusCode >= 200 && response.statusCode < 300) { + return true; + } else { + response.transform(utf8.decoder).listen((contents) { + try { + WordPressError err = WordPressError.fromJson(json.decode(contents)); + throw err; + } catch (e) { + throw new WordPressError(message: contents); + } + }); + } + return false; + } + +// ===================== +// UPDATE END +// ===================== + +// ===================== +// DELETE START +// ===================== + + Future deletePost({required int id}) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_POSTS + '/$id'); + + HttpClient httpClient = new HttpClient(); + HttpClientRequest request = + await httpClient.deleteUrl(Uri.parse(url.toString())); + request.headers + .set(HttpHeaders.contentTypeHeader, "application/json; charset=UTF-8"); + request.headers.set(HttpHeaders.acceptHeader, "application/json"); + request.headers.set('Authorization', "${_urlHeader['Authorization']}"); + + HttpClientResponse response = await request.close(); + + if (response.statusCode >= 200 && response.statusCode < 300) { + return true; + } else { + response.transform(utf8.decoder).listen((contents) { + try { + WordPressError err = WordPressError.fromJson(json.decode(contents)); + throw err; + } catch (e) { + throw new WordPressError(message: contents); + } + }); + } + return false; + } + + Future deleteComment({required int id}) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_COMMENTS + '/$id'); + + HttpClient httpClient = new HttpClient(); + HttpClientRequest request = + await httpClient.deleteUrl(Uri.parse(url.toString())); + request.headers + .set(HttpHeaders.contentTypeHeader, "application/json; charset=UTF-8"); + request.headers.set(HttpHeaders.acceptHeader, "application/json"); + request.headers.set('Authorization', "${_urlHeader['Authorization']}"); + + HttpClientResponse response = await request.close(); + + if (response.statusCode >= 200 && response.statusCode < 300) { + return true; + } else { + response.transform(utf8.decoder).listen((contents) { + try { + WordPressError err = WordPressError.fromJson(json.decode(contents)); + throw err; + } catch (e) { + throw new WordPressError(message: contents); + } + }); + } + return false; + } + + Future deleteUser({ + required int id, + required int reassign, + }) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_USERS + '/$id'); + + HttpClient httpClient = new HttpClient(); + HttpClientRequest request = + await httpClient.deleteUrl(Uri.parse(url.toString())); + request.headers + .set(HttpHeaders.contentTypeHeader, "application/json; charset=UTF-8"); + request.headers.set(HttpHeaders.acceptHeader, "application/json"); + request.headers.set('Authorization', "${_urlHeader['Authorization']}"); + + request + .add(utf8.encode(json.encode({"reassign": reassign, "force": true}))); + HttpClientResponse response = await request.close(); + + if (response.statusCode >= 200 && response.statusCode < 300) { + return true; + } else { + response.transform(utf8.decoder).listen((contents) { + try { + WordPressError err = WordPressError.fromJson(json.decode(contents)); + throw err; + } catch (e) { + throw new WordPressError(message: contents); + } + }); + } + return false; + } + +// ===================== +// UPDATE END +// ===================== + +// end yahya - @mymakarim + + /// This is used to create a [Comment] for a [Post]. Before this method can be called, + /// [User] writing the comment needs to be authenticated first by calling + /// [WordPress.authenticateUser]. On success, the [Comment] object is returned containing + /// comment information. + /// + /// In case of an error, a [WordPressError] object is thrown. + Future createComment({required Comment comment}) async { + final StringBuffer url = new StringBuffer(_baseUrl + URL_COMMENTS); + + final response = await http.post( + Uri.parse(url.toString()), + headers: _urlHeader, + body: comment.toJson(), + ); + + if (response.statusCode >= 200 && response.statusCode < 300) { + return Comment.fromJson(json.decode(response.body)); + } else { + try { + WordPressError err = + WordPressError.fromJson(json.decode(response.body)); + throw err; + } catch (e) { + throw new WordPressError(message: response.body); + } + } + } } diff --git a/lib/requests/params_category_list.dart b/lib/requests/params_category_list.dart new file mode 100644 index 0000000..55d99a2 --- /dev/null +++ b/lib/requests/params_category_list.dart @@ -0,0 +1,77 @@ +import 'package:flutter_wordpress/constants.dart'; + +/// This class holds all arguments which can be used to filter Categories when using +/// [WordPress.fetchCategories] method. +/// +/// [List Categories' Arguments](https://developer.wordpress.org/rest-api/reference/categories/#list-categories) +class ParamsCategoryList { + final WordPressContext context; + final int pageNum; + final int perPage; + final String searchQuery; + final List excludeCategoryIDs; + final List includeCategoryIDs; + final Order order; + final CategoryTagOrderBy orderBy; + final bool hideEmpty; + final int? parent; + final int? post; + final String slug; + + ParamsCategoryList({ + this.context = WordPressContext.view, + this.pageNum = 1, + this.perPage = 10, + this.searchQuery = '', + this.excludeCategoryIDs = const [], + this.includeCategoryIDs = const [], + this.order = Order.asc, + this.orderBy = CategoryTagOrderBy.name, + this.hideEmpty = false, + this.parent, + this.post, + this.slug = '', + }); + + Map toMap() { + return { + 'context': '${enumStringToName(this.context.toString())}', + 'page': '${this.pageNum}', + 'per_page': '${this.perPage}', + 'search': '${this.searchQuery}', + 'exclude': '${listToUrlString(this.excludeCategoryIDs)}', + 'include': '${listToUrlString(this.includeCategoryIDs)}', + 'order': '${enumStringToName(this.order.toString())}', + 'orderby': '${enumStringToName(this.orderBy.toString())}', + 'hide_empty': '${this.hideEmpty}', + 'parent': '${this.parent == null ? '' : this.parent}', + 'post': '${this.post == null ? '' : this.post}', + 'slug': '${this.slug}', + }; + } + + ParamsCategoryList copyWith({ + int? pageNum, + int? perPage + }) { + return ParamsCategoryList( + context: context, + order: order, + orderBy: orderBy, + pageNum: pageNum ?? this.pageNum, + perPage: perPage ?? this.perPage, + searchQuery: searchQuery, + slug: slug, + excludeCategoryIDs: excludeCategoryIDs, + hideEmpty: hideEmpty, + includeCategoryIDs: includeCategoryIDs, + parent: parent, + post: post + ); + } + + @override + String toString() { + return constructUrlParams(toMap()); + } +} diff --git a/lib/requests/params_comment_list.dart b/lib/requests/params_comment_list.dart index 7638f70..e9263e3 100644 --- a/lib/requests/params_comment_list.dart +++ b/lib/requests/params_comment_list.dart @@ -16,9 +16,9 @@ class ParamsCommentList { final String beforeDate; final List excludeCommentIDs; final List includeCommentIDs; - final int offset; + final int? offset; final Order order; - final CommentsOrderBy orderBy; + final CommentOrderBy orderBy; final List includeParentIDs; final List excludeParentIDs; final List includePostIDs; @@ -32,18 +32,18 @@ class ParamsCommentList { this.perPage = 10, this.searchQuery = '', this.afterDate = '', - this.includeAuthorIDs, - this.excludeAuthorIDs, + this.includeAuthorIDs = const [], + this.excludeAuthorIDs = const [], this.authorEmail = '', this.beforeDate = '', - this.excludeCommentIDs, - this.includeCommentIDs, + this.excludeCommentIDs = const [], + this.includeCommentIDs = const [], this.offset, this.order = Order.desc, - this.orderBy = CommentsOrderBy.date_gmt, - this.includeParentIDs, - this.excludeParentIDs, - this.includePostIDs, + this.orderBy = CommentOrderBy.date_gmt, + this.includeParentIDs = const [], + this.excludeParentIDs = const [], + this.includePostIDs = const [], this.commentStatus = CommentStatus.approve, this.commentType = CommentType.comment, this.postPassword = '', diff --git a/lib/requests/params_media_list.dart b/lib/requests/params_media_list.dart new file mode 100644 index 0000000..52b760c --- /dev/null +++ b/lib/requests/params_media_list.dart @@ -0,0 +1,79 @@ +import 'package:flutter_wordpress/constants.dart'; + +/// This class holds all arguments which can be used to filter media when using +/// [WordPress.fetchMediaList] method. +/// +/// [List Media Arguments](https://developer.wordpress.org/rest-api/reference/media/#list-media) +class ParamsMediaList { + final WordPressContext context; + final int pageNum; + final int perPage; + final String searchQuery; + final String afterDate; + final List includeAuthorIDs; + final List excludeAuthorIDs; + final String beforeDate; + final List excludeMediaIDs; + final List includeMediaIDs; + final int? offset; + final Order order; + final MediaOrderBy orderBy; + final List includeParentIDs; + final List excludeParentIDs; + final String slug; + final MediaStatus mediaStatus; + final MediaType? mediaType; + final String mimeType; + + ParamsMediaList({ + this.context = WordPressContext.view, + this.pageNum = 1, + this.perPage = 10, + this.searchQuery = '', + this.afterDate = '', + this.includeAuthorIDs = const [], + this.excludeAuthorIDs = const [], + this.beforeDate = '', + this.excludeMediaIDs = const [], + this.includeMediaIDs = const [], + this.offset, + this.order = Order.desc, + this.orderBy = MediaOrderBy.date, + this.excludeParentIDs = const [], + this.includeParentIDs = const [], + this.slug = '', + this.mediaStatus = MediaStatus.inherit, + this.mediaType, + this.mimeType = '', + }); + + Map toMap() { + return { + 'context': '${enumStringToName(this.context.toString())}', + 'page': '${this.pageNum}', + 'per_page': '${this.perPage}', + 'search': '${this.searchQuery}', + 'after': '${this.afterDate}', + 'author': '${listToUrlString(this.includeAuthorIDs)}', + 'author_exclude': '${listToUrlString(this.excludeAuthorIDs)}', + 'before': '${this.beforeDate}', + 'exclude': '${listToUrlString(excludeMediaIDs)}', + 'include': '${listToUrlString(includeMediaIDs)}', + 'offset': '${this.offset == null ? '' : this.offset}', + 'order': '${enumStringToName(this.order.toString())}', + 'orderby': '${enumStringToName(this.orderBy.toString())}', + 'parent': '${listToUrlString(includeParentIDs)}', + 'parent_exclude': '${listToUrlString(excludeParentIDs)}', + 'slug': '${this.slug}', + 'status': '${enumStringToName(this.mediaStatus.toString())}', + 'media_type': + '${this.mediaType == null ? '' : enumStringToName(this.mediaType.toString())}', + 'mime_type': '${this.mimeType}', + }; + } + + @override + String toString() { + return constructUrlParams(toMap()); + } +} diff --git a/lib/requests/params_page_list.dart b/lib/requests/params_page_list.dart new file mode 100644 index 0000000..77b94a4 --- /dev/null +++ b/lib/requests/params_page_list.dart @@ -0,0 +1,75 @@ +import 'package:flutter_wordpress/constants.dart'; + +/// This class holds all arguments which can be used to filter pages when using +/// [WordPress.fetchPages] method. +/// +/// [List Pages' Arguments](https://developer.wordpress.org/rest-api/reference/pages/#list-pages) +class ParamsPageList { + final WordPressContext context; + final int pageNum; + final int perPage; + final String searchQuery; + final String afterDate; + final List includeAuthorIDs; + final List excludeAuthorIDs; + final String beforeDate; + final List excludePageIDs; + final List includePageIDs; + final int? menuOrder; + final int? offset; + final Order order; + final PageOrderBy orderBy; + final List includeParentIDs; + final List excludeParentIDs; + final String slug; + final PostPageStatus pageStatus; + + ParamsPageList({ + this.context = WordPressContext.view, + this.pageNum = 1, + this.perPage = 10, + this.searchQuery = '', + this.afterDate = '', + this.includeAuthorIDs = const [], + this.excludeAuthorIDs = const [], + this.beforeDate = '', + this.excludePageIDs = const [], + this.includePageIDs = const [], + this.menuOrder, + this.offset, + this.order = Order.desc, + this.orderBy = PageOrderBy.date, + this.includeParentIDs = const [], + this.excludeParentIDs = const [], + this.slug = '', + this.pageStatus = PostPageStatus.publish, + }); + + Map toMap() { + return { + 'context': '${enumStringToName(this.context.toString())}', + 'page': '${this.pageNum}', + 'per_page': '${this.perPage}', + 'search': '${this.searchQuery}', + 'after': '${this.afterDate}', + 'author': '${listToUrlString(this.includeAuthorIDs)}', + 'author_exclude': '${listToUrlString(this.excludeAuthorIDs)}', + 'before': '${this.beforeDate}', + 'exclude': '${listToUrlString(excludePageIDs)}', + 'include': '${listToUrlString(includePageIDs)}', + 'menu_order': '${this.menuOrder == null ? '' : this.menuOrder}', + 'offset': '${this.offset == null ? '' : this.offset}', + 'order': '${enumStringToName(this.order.toString())}', + 'orderby': '${enumStringToName(this.orderBy.toString())}', + 'parent': '${listToUrlString(includeParentIDs)}', + 'parent_exclude': '${listToUrlString(excludeParentIDs)}', + 'slug': '${this.slug}', + 'status': '${enumStringToName(this.pageStatus.toString())}', + }; + } + + @override + String toString() { + return constructUrlParams(toMap()); + } +} diff --git a/lib/requests/params_post_list.dart b/lib/requests/params_post_list.dart index 4c589e6..3ada10b 100644 --- a/lib/requests/params_post_list.dart +++ b/lib/requests/params_post_list.dart @@ -15,16 +15,16 @@ class ParamsPostList { final List excludeAuthorIDs; final List includePostIDs; final List excludePostIDs; - final int offset; + final int? offset; final Order order; - final PostsOrderBy orderBy; + final PostOrderBy orderBy; final String slug; - final PostStatus postStatus; + final PostPageStatus postStatus; final List includeCategories; final List excludeCategories; final List includeTags; final List excludeTags; - final bool sticky; + final bool? sticky; ParamsPostList({ this.context = WordPressContext.view, @@ -33,19 +33,19 @@ class ParamsPostList { this.searchQuery = '', this.afterDate = '', this.beforeDate = '', - this.includeAuthorIDs, - this.excludeAuthorIDs, - this.includePostIDs, - this.excludePostIDs, + this.includeAuthorIDs = const [], + this.excludeAuthorIDs = const [], + this.includePostIDs = const [], + this.excludePostIDs = const [], this.offset, this.order = Order.desc, - this.orderBy = PostsOrderBy.date, + this.orderBy = PostOrderBy.date, this.slug = '', - this.postStatus = PostStatus.publish, - this.includeCategories, - this.excludeCategories, - this.includeTags, - this.excludeTags, + this.postStatus = PostPageStatus.publish, + this.includeCategories = const [], + this.excludeCategories = const [], + this.includeTags = const [], + this.excludeTags = const [], this.sticky, }); @@ -74,6 +74,34 @@ class ParamsPostList { }; } +ParamsPostList copyWith({ + int? pageNum, + int? perPage, +}) { + return ParamsPostList( + afterDate: afterDate, + beforeDate: beforeDate, + context: context, + excludeAuthorIDs: excludeAuthorIDs, + excludeCategories: excludeCategories, + excludePostIDs: excludePostIDs, + excludeTags: excludeTags, + includeAuthorIDs: includeAuthorIDs, + includeCategories: includeCategories, + includePostIDs: includePostIDs, + includeTags: includeTags, + offset: offset, + order: order, + orderBy: orderBy, + pageNum: pageNum ?? this.pageNum, + perPage: perPage ?? this.perPage, + postStatus: postStatus, + searchQuery: searchQuery, + slug: slug, + sticky: sticky + ); +} + @override String toString() { return constructUrlParams(toMap()); diff --git a/lib/requests/params_tag_list.dart b/lib/requests/params_tag_list.dart new file mode 100644 index 0000000..d0b9d34 --- /dev/null +++ b/lib/requests/params_tag_list.dart @@ -0,0 +1,54 @@ +import 'package:flutter_wordpress/constants.dart'; + +/// This class holds all arguments which can be used to filter Tags when using +/// [WordPress.fetchTags] method. +/// +/// [List Tags' Arguments](https://developer.wordpress.org/rest-api/reference/tags/#list-tags) +class ParamsTagList { + final WordPressContext context; + final int pageNum; + final int perPage; + final String searchQuery; + final List excludeTagIDs; + final List includeTagIDs; + final Order order; + final CategoryTagOrderBy orderBy; + final bool? hideEmpty; + final int? post; + final String slug; + + ParamsTagList({ + this.context = WordPressContext.view, + this.pageNum = 1, + this.perPage = 10, + this.searchQuery = '', + this.excludeTagIDs = const [], + this.includeTagIDs = const [], + this.order = Order.asc, + this.orderBy = CategoryTagOrderBy.name, + this.hideEmpty, + this.post, + this.slug = '', + }); + + Map toMap() { + return { + 'context': '${enumStringToName(this.context.toString())}', + 'page': '${this.pageNum}', + 'per_page': '${this.perPage}', + 'search': '${this.searchQuery}', + 'exclude': '${listToUrlString(this.excludeTagIDs)}', + 'include': '${listToUrlString(this.includeTagIDs)}', + 'order': '${enumStringToName(this.order.toString())}', + 'orderby': '${enumStringToName(this.orderBy.toString())}', + 'hide_empty': '${this.hideEmpty == null ? '' : this.hideEmpty}', + 'post': '${this.post == null ? '' : this.post}', + 'slug': '${this.slug}', + }; + } + + @override + String toString() { + return constructUrlParams(toMap()); + } +} diff --git a/lib/requests/params_user_list.dart b/lib/requests/params_user_list.dart index 5a778d6..a69ad58 100644 --- a/lib/requests/params_user_list.dart +++ b/lib/requests/params_user_list.dart @@ -11,24 +11,24 @@ class ParamsUserList { final String searchQuery; final List includeUserIDs; final List excludeUserIDs; - final int offset; + final int? offset; final Order order; - final UsersOrderBy orderBy; + final UserOrderBy orderBy; final String slug; - final UserRole role; + final List roles; ParamsUserList({ this.context = WordPressContext.view, this.pageNum = 1, this.perPage = 10, this.searchQuery = '', - this.includeUserIDs, - this.excludeUserIDs, + this.includeUserIDs = const [], + this.excludeUserIDs = const [], this.offset, this.order = Order.asc, - this.orderBy = UsersOrderBy.name, + this.orderBy = UserOrderBy.name, this.slug = '', - this.role, + this.roles = const [], }); Map toMap() { @@ -43,7 +43,7 @@ class ParamsUserList { 'order': '${enumStringToName(this.order.toString())}', 'orderby': '${enumStringToName(this.orderBy.toString())}', 'slug': '${this.slug}', - 'roles': '${this.role == null ? '' : enumStringToName(this.role.toString())}' + 'roles': '${listToUrlString(this.roles)}', }; } @@ -51,4 +51,4 @@ class ParamsUserList { String toString() { return constructUrlParams(toMap()); } -} \ No newline at end of file +} diff --git a/lib/schemas/avatar_urls.dart b/lib/schemas/avatar_urls.dart index 40311b2..deb2566 100644 --- a/lib/schemas/avatar_urls.dart +++ b/lib/schemas/avatar_urls.dart @@ -1,9 +1,13 @@ class AvatarUrls { - String s24; - String s48; - String s96; + String? s24; + String? s48; + String? s96; - AvatarUrls({this.s24, this.s48, this.s96}); + AvatarUrls({ + this.s24, + this.s48, + this.s96, + }); AvatarUrls.fromJson(Map json) { s24 = json['24']; @@ -13,9 +17,11 @@ class AvatarUrls { Map toJson() { final Map data = new Map(); + data['24'] = this.s24; data['48'] = this.s48; data['96'] = this.s96; + return data; } -} \ No newline at end of file +} diff --git a/lib/schemas/capabilities.dart b/lib/schemas/capabilities.dart index b80d894..7d9eb5f 100644 --- a/lib/schemas/capabilities.dart +++ b/lib/schemas/capabilities.dart @@ -1,23 +1,23 @@ class Capabilities { - String manageTerms; - String editTerms; - String deleteTerms; - String assignTerms; - String editPost; - String readPost; - String deletePost; - String editPosts; - String editOthersPosts; - String publishPosts; - String readPrivatePosts; - String read; - String deletePosts; - String deletePrivatePosts; - String deletePublishedPosts; - String deleteOthersPosts; - String editPrivatePosts; - String editPublishedPosts; - String createPosts; + String? manageTerms; + String? editTerms; + String? deleteTerms; + String? assignTerms; + String? editPost; + String? readPost; + String? deletePost; + String? editPosts; + String? editOthersPosts; + String? publishPosts; + String? readPrivatePosts; + String? read; + String? deletePosts; + String? deletePrivatePosts; + String? deletePublishedPosts; + String? deleteOthersPosts; + String? editPrivatePosts; + String? editPublishedPosts; + String? createPosts; Capabilities({ this.manageTerms, @@ -65,6 +65,7 @@ class Capabilities { Map toJson() { final Map data = new Map(); + data['manage_terms'] = this.manageTerms; data['edit_terms'] = this.editTerms; data['delete_terms'] = this.deleteTerms; @@ -84,6 +85,7 @@ class Capabilities { data['edit_private_posts'] = this.editPrivatePosts; data['edit_published_posts'] = this.editPublishedPosts; data['create_posts'] = this.createPosts; + return data; } } diff --git a/lib/schemas/category.dart b/lib/schemas/category.dart index c64d110..a16226f 100644 --- a/lib/schemas/category.dart +++ b/lib/schemas/category.dart @@ -1,28 +1,27 @@ import 'links.dart'; class Category { - int id; - int count; - String description; - String link; - String name; - String slug; - String taxonomy; - int parent; -// List meta; - Links lLinks; + int? id; + int? count; + String? description; + String? link; + String? name; + String? slug; + String? taxonomy; + int? parent; + Links? lLinks; - Category( - {this.id, - this.count, - this.description, - this.link, - this.name, - this.slug, - this.taxonomy, - this.parent, -// this.meta, - this.lLinks}); + Category({ + this.id, + this.count, + this.description, + this.link, + this.name, + this.slug, + this.taxonomy, + this.parent, + this.lLinks, + }); Category.fromJson(Map json) { id = json['id']; @@ -33,17 +32,12 @@ class Category { slug = json['slug']; taxonomy = json['taxonomy']; parent = json['parent']; - /*if (json['meta'] != null) { - meta = new List(); - json['meta'].forEach((v) { - meta.add(new Null.fromJson(v)); - }); - }*/ lLinks = json['_links'] != null ? new Links.fromJson(json['_links']) : null; } Map toJson() { final Map data = new Map(); + data['id'] = this.id; data['count'] = this.count; data['description'] = this.description; @@ -52,13 +46,8 @@ class Category { data['slug'] = this.slug; data['taxonomy'] = this.taxonomy; data['parent'] = this.parent; - /*if (this.meta != null) { - data['meta'] = this.meta.map((v) => v.toJson()).toList(); - }*/ - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } - diff --git a/lib/schemas/comment.dart b/lib/schemas/comment.dart index 309cb19..ead1c90 100644 --- a/lib/schemas/comment.dart +++ b/lib/schemas/comment.dart @@ -1,46 +1,64 @@ -import 'links.dart'; +import 'package:flutter_wordpress/constants.dart'; + import 'avatar_urls.dart'; import 'content.dart'; +import 'links.dart'; +/// A [WordPress Comment](https://developer.wordpress.org/rest-api/reference/comments/) +/// +/// Refer the above link to see which arguments are set based on different +/// context modes ([WordPressContext]). class Comment { - int id; - int post; - int parent; - int author; - String authorName; - String authorEmail; - String authorUrl; - String authorIp; - String authorUserAgent; - String date; - String dateGmt; - Content content; - String link; - String status; - String type; - AvatarUrls authorAvatarUrls; -// List meta; - Links lLinks; - - Comment( - {this.id, - this.post, - this.parent, - this.author, - this.authorName, - this.authorEmail, - this.authorUrl, - this.authorIp, - this.authorUserAgent, - this.date, - this.dateGmt, - this.content, - this.link, - this.status, - this.type, - this.authorAvatarUrls, -// this.meta, - this.lLinks}); + /// ID of the comment. + int? id; + + /// ID of the post on which to comment. + int? post; + + /// ID of the parent comment in case of reply. + /// This should be 0 in case of a new comment. + int? parent; + + /// ID of the author who is going to comment. + int? author; + String? authorName; + String? authorEmail; + String? authorUrl; + String? authorIp; + String? authorUserAgent; + + /// The date the comment was written, in the site's timezone. + String? date; + + /// The date the comment was written, in GMT. + String? dateGmt; + + /// Content of the comment. + Content? content; + String? link; + + /// This can only be set by an editor/administrator. + CommentStatus? status; + + /// This can only be set by an editor/administrator. + CommentType? type; + AvatarUrls? authorAvatarUrls; + Links? lLinks; + + Comment({ + required this.author, + required this.post, + required String content, + this.authorEmail, + this.authorIp, + this.authorName, + this.authorUrl, + this.authorUserAgent, + this.date, + this.dateGmt, + this.parent = 0, + this.status, + }) : content = new Content(rendered: content); Comment.fromJson(Map json) { id = json['id']; @@ -54,26 +72,35 @@ class Comment { authorUserAgent = json['author_user_agent']; date = json['date']; dateGmt = json['date_gmt']; - content = - json['content'] != null ? new Content.fromJson(json['content']) : null; + content = (json['content'] != null + ? new Content.fromJson(json['content']!) + : null)!; link = json['link']; - status = json['status']; - type = json['type']; + if (json['status'] != null) { + CommentStatus.values.forEach((val) { + if (enumStringToName(val.toString()) == json['status']) { + status = val; + return; + } + }); + } + if (json['type'] != null) { + CommentType.values.forEach((val) { + if (enumStringToName(val.toString()) == json['type']) { + type = val; + return; + } + }); + } authorAvatarUrls = json['author_avatar_urls'] != null ? new AvatarUrls.fromJson(json['author_avatar_urls']) : null; - /*if (json['meta'] != null) { - meta = new List(); - json['meta'].forEach((v) { - meta.add(new Null.fromJson(v)); - }); - }*/ lLinks = json['_links'] != null ? new Links.fromJson(json['_links']) : null; } Map toJson() { final Map data = new Map(); - data['id'] = this.id; + data['post'] = this.post; data['parent'] = this.parent; data['author'] = this.author; @@ -84,21 +111,14 @@ class Comment { data['author_user_agent'] = this.authorUserAgent; data['date'] = this.date; data['date_gmt'] = this.dateGmt; - if (this.content != null) { - data['content'] = this.content.toJson(); - } - data['link'] = this.link; - data['status'] = this.status; - data['type'] = this.type; - if (this.authorAvatarUrls != null) { - data['author_avatar_urls'] = this.authorAvatarUrls.toJson(); - } - /*if (this.meta != null) { - data['meta'] = this.meta.map((v) => v.toJson()).toList(); - }*/ - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['content'] = this.content?.toJson(); + data['status'] = enumStringToName(this.status.toString()); + return data; } + + @override + String toString() { + return 'Comment: {id: $id, author: $authorName, post: $post, parent: $parent}'; + } } diff --git a/lib/schemas/comment_hierarchy.dart b/lib/schemas/comment_hierarchy.dart new file mode 100644 index 0000000..a983070 --- /dev/null +++ b/lib/schemas/comment_hierarchy.dart @@ -0,0 +1,20 @@ +import 'comment.dart'; + +/// This class is used to store comments as a hierarchy. +class CommentHierarchy { + /// Parent comment. + final Comment comment; + + /// Replies to the parent comment. + final List? children; + + CommentHierarchy({ + required this.comment, + this.children, + }); + + @override + String toString() { + return '$comment, children: [$children]'; + } +} diff --git a/lib/schemas/content.dart b/lib/schemas/content.dart index abc51ad..5b9b726 100644 --- a/lib/schemas/content.dart +++ b/lib/schemas/content.dart @@ -1,10 +1,10 @@ class Content { - String raw; - String rendered; - bool protected; - int blockVersion; + String? raw; + String? rendered; + bool? protected; + int? blockVersion; - Content({this.raw, this.rendered, this.protected, this.blockVersion}); + Content({this.rendered}); Content.fromJson(Map json) { raw = json['raw']; @@ -15,10 +15,12 @@ class Content { Map toJson() { final Map data = new Map(); + data['raw'] = this.raw; data['rendered'] = this.rendered; data['protected'] = this.protected; data['block_version'] = this.blockVersion; + return data; } } diff --git a/lib/schemas/excerpt.dart b/lib/schemas/excerpt.dart index d873ac0..3eae336 100644 --- a/lib/schemas/excerpt.dart +++ b/lib/schemas/excerpt.dart @@ -1,9 +1,9 @@ class Excerpt { - String raw; - String rendered; - bool protected; + String? raw; + String? rendered; + bool? protected; - Excerpt({this.raw, this.rendered, this.protected}); + Excerpt({this.rendered}); Excerpt.fromJson(Map json) { raw = json['raw']; @@ -13,9 +13,11 @@ class Excerpt { Map toJson() { final Map data = new Map(); + data['raw'] = this.raw; data['rendered'] = this.rendered; data['protected'] = this.protected; + return data; } -} \ No newline at end of file +} diff --git a/lib/schemas/fetch_user_result.dart b/lib/schemas/fetch_user_result.dart new file mode 100644 index 0000000..063fb38 --- /dev/null +++ b/lib/schemas/fetch_user_result.dart @@ -0,0 +1,11 @@ +import 'user.dart'; + +class FetchUsersResult { + List users = const []; + int? totalUsers; + + FetchUsersResult(List users, int totalUsers) { + this.users = users; + this.totalUsers = totalUsers; + } +} diff --git a/lib/schemas/guid.dart b/lib/schemas/guid.dart index 0a9ea1e..31009db 100644 --- a/lib/schemas/guid.dart +++ b/lib/schemas/guid.dart @@ -1,8 +1,6 @@ class Guid { - String rendered; - String raw; - - Guid({this.rendered, this.raw}); + String? rendered; + String? raw; Guid.fromJson(Map json) { rendered = json['rendered']; @@ -11,8 +9,10 @@ class Guid { Map toJson() { final Map data = new Map(); + data['rendered'] = this.rendered; data['raw'] = this.raw; + return data; } -} \ No newline at end of file +} diff --git a/lib/schemas/jwt_response.dart b/lib/schemas/jwt_response.dart index b12f0c0..a2b0cfa 100644 --- a/lib/schemas/jwt_response.dart +++ b/lib/schemas/jwt_response.dart @@ -1,11 +1,15 @@ class JWTResponse { - String token; - String userEmail; - String userNicename; - String userDisplayName; + String? token; + String? userEmail; + String? userNicename; + String? userDisplayName; - JWTResponse( - {this.token, this.userEmail, this.userNicename, this.userDisplayName}); + JWTResponse({ + this.token, + this.userEmail, + this.userNicename, + this.userDisplayName, + }); JWTResponse.fromJson(Map json) { token = json['token']; @@ -16,10 +20,12 @@ class JWTResponse { Map toJson() { final Map data = new Map(); + data['token'] = this.token; data['user_email'] = this.userEmail; data['user_nicename'] = this.userNicename; data['user_display_name'] = this.userDisplayName; + return data; } -} \ No newline at end of file +} diff --git a/lib/schemas/labels.dart b/lib/schemas/labels.dart index 7abb2cf..1ad9e39 100644 --- a/lib/schemas/labels.dart +++ b/lib/schemas/labels.dart @@ -1,45 +1,45 @@ class Labels { - String name; - String singularName; - String searchItems; - String popularItems; - String allItems; - String parentItem; - String parentItemColon; - String addNew; - String addNewItem; - String editItem; - String newItem; - String viewItem; - String viewItems; - String notFound; - String notFoundInTrash; - String archives; - String attributes; - String insertIntoItem; - String uploadedToThisItem; - String featuredImage; - String setFeaturedImage; - String removeFeaturedImage; - String useFeaturedImage; - String filterItemsList; - String itemsListNavigation; - String itemsList; - String itemPublished; - String itemPublishedPrivately; - String itemRevertedToDraft; - String itemScheduled; - String itemUpdated; - String menuName; - String nameAdminBar; - String updateItem; - String newItemName; - String separateItemsWithCommas; - String addOrRemoveItems; - String chooseFromMostUsed; - String noTerms; - String mostUsed; - String backToItems; + String? name; + String? singularName; + String? searchItems; + String? popularItems; + String? allItems; + String? parentItem; + String? parentItemColon; + String? addNew; + String? addNewItem; + String? editItem; + String? newItem; + String? viewItem; + String? viewItems; + String? notFound; + String? notFoundInTrash; + String? archives; + String? attributes; + String? insertIntoItem; + String? uploadedToThisItem; + String? featuredImage; + String? setFeaturedImage; + String? removeFeaturedImage; + String? useFeaturedImage; + String? filterItemsList; + String? itemsListNavigation; + String? itemsList; + String? itemPublished; + String? itemPublishedPrivately; + String? itemRevertedToDraft; + String? itemScheduled; + String? itemUpdated; + String? menuName; + String? nameAdminBar; + String? updateItem; + String? newItemName; + String? separateItemsWithCommas; + String? addOrRemoveItems; + String? chooseFromMostUsed; + String? noTerms; + String? mostUsed; + String? backToItems; Labels({ this.name, @@ -131,6 +131,7 @@ class Labels { Map toJson() { final Map data = new Map(); + data['name'] = this.name; data['singular_name'] = this.singularName; data['search_items'] = this.searchItems; diff --git a/lib/schemas/links.dart b/lib/schemas/links.dart index 0aa0dfc..182de55 100644 --- a/lib/schemas/links.dart +++ b/lib/schemas/links.dart @@ -1,281 +1,229 @@ class Links { - List self; - List collection; - List about; - List author; - List replies; - List archives; - List versionHistory; - List wpPostType; - List wpAttachment; - List wpTerm; - List wpActionPublish; - List wpActionUnfilteredHtml; - List wpActionSticky; - List wpActionAssignAuthor; - List wpActionCreateCategories; - List wpActionAssignCategories; - List wpActionCreateTags; - List wpActionAssignTags; - List wpItems; - List up; - List inReplyTo; - List children; - List curies; - - Links({ - this.self, - this.collection, - this.about, - this.author, - this.replies, - this.archives, - this.versionHistory, - this.wpPostType, - this.wpAttachment, - this.wpTerm, - this.wpActionPublish, - this.wpActionUnfilteredHtml, - this.wpActionSticky, - this.wpActionAssignAuthor, - this.wpActionCreateCategories, - this.wpActionAssignCategories, - this.wpActionCreateTags, - this.wpActionAssignTags, - this.wpItems, - this.up, - this.inReplyTo, - this.children, - this.curies, - }); + List? self; + List? collection; + List? about; + List? author; + List? replies; + List? archives; + List? versionHistory; + List? wpPostType; + List? predecessorVersion; + List? wpFeaturedmedia; + List? wpAttachment; + List? wpTerm; + List? wpActionPublish; + List? wpActionUnfilteredHtml; + List? wpActionSticky; + List? wpActionAssignAuthor; + List? wpActionCreateCategories; + List? wpActionAssignCategories; + List? wpActionCreateTags; + List? wpActionAssignTags; + List? wpItems; + List? up; + List? inReplyTo; + List? children; + List? curies; Links.fromJson(Map json) { if (json['self'] != null) { - self = new List(); + self = []; json['self'].forEach((v) { - self.add(new Self.fromJson(v)); + self?.add(new Self.fromJson(v)); }); } if (json['collection'] != null) { - collection = new List(); + collection = []; json['collection'].forEach((v) { - collection.add(new Collection.fromJson(v)); + collection?.add(new Collection.fromJson(v)); }); } if (json['about'] != null) { - about = new List(); + about = []; json['about'].forEach((v) { - about.add(new About.fromJson(v)); + about?.add(new About.fromJson(v)); }); } if (json['author'] != null) { - author = new List(); + author = []; json['author'].forEach((v) { - author.add(new Author.fromJson(v)); + author?.add(new Author.fromJson(v)); }); } if (json['replies'] != null) { - replies = new List(); + replies = []; json['replies'].forEach((v) { - replies.add(new Replies.fromJson(v)); + replies?.add(new Replies.fromJson(v)); }); } if (json['archives'] != null) { - archives = new List(); + archives = []; json['archives'].forEach((v) { - archives.add(new Archives.fromJson(v)); + archives?.add(new Archives.fromJson(v)); }); } if (json['version-history'] != null) { - versionHistory = new List(); + versionHistory = []; json['version-history'].forEach((v) { - versionHistory.add(new VersionHistory.fromJson(v)); + versionHistory?.add(new VersionHistory.fromJson(v)); }); } if (json['wp:post_type'] != null) { - wpPostType = new List(); + wpPostType = []; json['wp:post_type'].forEach((v) { - wpPostType.add(new WpPostType.fromJson(v)); + wpPostType?.add(new WpPostType.fromJson(v)); + }); + } + if (json['predecessor-version'] != null) { + predecessorVersion = []; + json['predecessor-version'].forEach((v) { + predecessorVersion?.add(new PredecessorVersion.fromJson(v)); + }); + } + if (json['wp:featuredmedia'] != null) { + wpFeaturedmedia = []; + json['wp:featuredmedia'].forEach((v) { + wpFeaturedmedia?.add(new WpFeaturedmedia.fromJson(v)); }); } if (json['wp:attachment'] != null) { - wpAttachment = new List(); + wpAttachment = []; json['wp:attachment'].forEach((v) { - wpAttachment.add(new WpAttachment.fromJson(v)); + wpAttachment?.add(new WpAttachment.fromJson(v)); }); } if (json['wp:term'] != null) { - wpTerm = new List(); + wpTerm = []; json['wp:term'].forEach((v) { - wpTerm.add(new WpTerm.fromJson(v)); + wpTerm?.add(new WpTerm.fromJson(v)); }); } if (json['wp:action-publish'] != null) { - wpActionPublish = new List(); + wpActionPublish = []; json['wp:action-publish'].forEach((v) { - wpActionPublish.add(new WpActionPublish.fromJson(v)); + wpActionPublish?.add(new WpActionPublish.fromJson(v)); }); } if (json['wp:action-unfiltered-html'] != null) { - wpActionUnfilteredHtml = new List(); + wpActionUnfilteredHtml = []; json['wp:action-unfiltered-html'].forEach((v) { - wpActionUnfilteredHtml.add(new WpActionUnfilteredHtml.fromJson(v)); + wpActionUnfilteredHtml?.add(new WpActionUnfilteredHtml.fromJson(v)); }); } if (json['wp:action-sticky'] != null) { - wpActionSticky = new List(); + wpActionSticky = []; json['wp:action-sticky'].forEach((v) { - wpActionSticky.add(new WpActionSticky.fromJson(v)); + wpActionSticky?.add(new WpActionSticky.fromJson(v)); }); } if (json['wp:action-assign-author'] != null) { - wpActionAssignAuthor = new List(); + wpActionAssignAuthor = []; json['wp:action-assign-author'].forEach((v) { - wpActionAssignAuthor.add(new WpActionAssignAuthor.fromJson(v)); + wpActionAssignAuthor?.add(new WpActionAssignAuthor.fromJson(v)); }); } if (json['wp:action-create-categories'] != null) { - wpActionCreateCategories = new List(); + wpActionCreateCategories = []; json['wp:action-create-categories'].forEach((v) { - wpActionCreateCategories.add(new WpActionCreateCategories.fromJson(v)); + wpActionCreateCategories?.add(new WpActionCreateCategories.fromJson(v)); }); } if (json['wp:action-assign-categories'] != null) { - wpActionAssignCategories = new List(); + wpActionAssignCategories = []; json['wp:action-assign-categories'].forEach((v) { - wpActionAssignCategories.add(new WpActionAssignCategories.fromJson(v)); + wpActionAssignCategories?.add(new WpActionAssignCategories.fromJson(v)); }); } if (json['wp:action-create-tags'] != null) { - wpActionCreateTags = new List(); + wpActionCreateTags = []; json['wp:action-create-tags'].forEach((v) { - wpActionCreateTags.add(new WpActionCreateTags.fromJson(v)); + wpActionCreateTags?.add(new WpActionCreateTags.fromJson(v)); }); } if (json['wp:action-assign-tags'] != null) { - wpActionAssignTags = new List(); + wpActionAssignTags = []; json['wp:action-assign-tags'].forEach((v) { - wpActionAssignTags.add(new WpActionAssignTags.fromJson(v)); + wpActionAssignTags?.add(new WpActionAssignTags.fromJson(v)); }); } if (json['wp:items'] != null) { - wpItems = new List(); + wpItems = []; json['wp:items'].forEach((v) { - wpItems.add(new WpItems.fromJson(v)); + wpItems?.add(new WpItems.fromJson(v)); }); } if (json['up'] != null) { - up = new List(); + up = []; json['up'].forEach((v) { - up.add(new Up.fromJson(v)); + up?.add(new Up.fromJson(v)); }); } if (json['in-reply-to'] != null) { - inReplyTo = new List(); + inReplyTo = []; json['in-reply-to'].forEach((v) { - inReplyTo.add(new InReplyTo.fromJson(v)); + inReplyTo?.add(new InReplyTo.fromJson(v)); }); } if (json['children'] != null) { - children = new List(); + children = []; json['children'].forEach((v) { - children.add(new Children.fromJson(v)); + children?.add(new Children.fromJson(v)); }); } if (json['curies'] != null) { - curies = new List(); + curies = []; json['curies'].forEach((v) { - curies.add(new Curies.fromJson(v)); + curies?.add(new Curies.fromJson(v)); }); } } Map toJson() { final Map data = new Map(); - if (this.self != null) { - data['self'] = this.self.map((v) => v.toJson()).toList(); - } - if (this.collection != null) { - data['collection'] = this.collection.map((v) => v.toJson()).toList(); - } - if (this.about != null) { - data['about'] = this.about.map((v) => v.toJson()).toList(); - } - if (this.author != null) { - data['author'] = this.author.map((v) => v.toJson()).toList(); - } - if (this.replies != null) { - data['replies'] = this.replies.map((v) => v.toJson()).toList(); - } - if (this.archives != null) { - data['archives'] = this.archives.map((v) => v.toJson()).toList(); - } - if (this.versionHistory != null) { - data['version-history'] = - this.versionHistory.map((v) => v.toJson()).toList(); - } - if (this.wpPostType != null) { - data['wp:post_type'] = this.wpPostType.map((v) => v.toJson()).toList(); - } - if (this.wpAttachment != null) { - data['wp:attachment'] = this.wpAttachment.map((v) => v.toJson()).toList(); - } - if (this.wpTerm != null) { - data['wp:term'] = this.wpTerm.map((v) => v.toJson()).toList(); - } - if (this.wpActionPublish != null) { - data['wp:action-publish'] = - this.wpActionPublish.map((v) => v.toJson()).toList(); - } - if (this.wpActionUnfilteredHtml != null) { - data['wp:action-unfiltered-html'] = - this.wpActionUnfilteredHtml.map((v) => v.toJson()).toList(); - } - if (this.wpActionSticky != null) { - data['wp:action-sticky'] = - this.wpActionSticky.map((v) => v.toJson()).toList(); - } - if (this.wpActionAssignAuthor != null) { - data['wp:action-assign-author'] = - this.wpActionAssignAuthor.map((v) => v.toJson()).toList(); - } - if (this.wpActionCreateCategories != null) { - data['wp:action-create-categories'] = - this.wpActionCreateCategories.map((v) => v.toJson()).toList(); - } - if (this.wpActionAssignCategories != null) { - data['wp:action-assign-categories'] = - this.wpActionAssignCategories.map((v) => v.toJson()).toList(); - } - if (this.wpActionCreateTags != null) { - data['wp:action-create-tags'] = - this.wpActionCreateTags.map((v) => v.toJson()).toList(); - } - if (this.wpActionAssignTags != null) { - data['wp:action-assign-tags'] = - this.wpActionAssignTags.map((v) => v.toJson()).toList(); - } - if (this.wpItems != null) { - data['wp:items'] = this.wpItems.map((v) => v.toJson()).toList(); - } - if (this.up != null) { - data['up'] = this.up.map((v) => v.toJson()).toList(); - } - if (this.inReplyTo != null) { - data['in-reply-to'] = this.inReplyTo.map((v) => v.toJson()).toList(); - } - if (this.children != null) { - data['children'] = this.children.map((v) => v.toJson()).toList(); - } - if (this.curies != null) { - data['curies'] = this.curies.map((v) => v.toJson()).toList(); - } + + data['self'] = this.self?.map((v) => v.toJson()).toList(); + data['collection'] = this.collection?.map((v) => v.toJson()).toList(); + data['about'] = this.about?.map((v) => v.toJson()).toList(); + data['author'] = this.author?.map((v) => v.toJson()).toList(); + data['replies'] = this.replies?.map((v) => v.toJson()).toList(); + data['archives'] = this.archives?.map((v) => v.toJson()).toList(); + data['version-history'] = + this.versionHistory?.map((v) => v.toJson()).toList(); + data['wp:post_type'] = this.wpPostType?.map((v) => v.toJson()).toList(); + data['predecessor-version'] = + this.predecessorVersion?.map((v) => v.toJson()).toList(); + data['wp:featuredmedia'] = + this.wpFeaturedmedia?.map((v) => v.toJson()).toList(); + data['wp:attachment'] = this.wpAttachment?.map((v) => v.toJson()).toList(); + data['wp:term'] = this.wpTerm?.map((v) => v.toJson()).toList(); + data['wp:action-publish'] = + this.wpActionPublish?.map((v) => v.toJson()).toList(); + data['wp:action-unfiltered-html'] = + this.wpActionUnfilteredHtml?.map((v) => v.toJson()).toList(); + data['wp:action-sticky'] = + this.wpActionSticky?.map((v) => v.toJson()).toList(); + data['wp:action-assign-author'] = + this.wpActionAssignAuthor?.map((v) => v.toJson()).toList(); + data['wp:action-create-categories'] = + this.wpActionCreateCategories?.map((v) => v.toJson()).toList(); + data['wp:action-assign-categories'] = + this.wpActionAssignCategories?.map((v) => v.toJson()).toList(); + data['wp:action-create-tags'] = + this.wpActionCreateTags?.map((v) => v.toJson()).toList(); + data['wp:action-assign-tags'] = + this.wpActionAssignTags?.map((v) => v.toJson()).toList(); + data['wp:items'] = this.wpItems?.map((v) => v.toJson()).toList(); + data['up'] = this.up?.map((v) => v.toJson()).toList(); + data['in-reply-to'] = this.inReplyTo?.map((v) => v.toJson()).toList(); + data['children'] = this.children?.map((v) => v.toJson()).toList(); + data['curies'] = this.curies?.map((v) => v.toJson()).toList(); + return data; } } class Self { - String href; + String? href; Self({this.href}); @@ -285,13 +233,15 @@ class Self { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class Collection { - String href; + String? href; Collection({this.href}); @@ -301,13 +251,15 @@ class Collection { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class About { - String href; + String? href; About({this.href}); @@ -317,16 +269,21 @@ class About { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class Author { - bool embeddable; - String href; + bool? embeddable; + String? href; - Author({this.embeddable, this.href}); + Author({ + this.embeddable, + this.href, + }); Author.fromJson(Map json) { embeddable = json['embeddable']; @@ -335,17 +292,24 @@ class Author { Map toJson() { final Map data = new Map(); - data['embeddable'] = this.embeddable; - data['href'] = this.href; + if (this.embeddable != null) { + data['embeddable'] = this.embeddable; + } + if (this.href != null) { + data['href'] = this.href; + } return data; } } class Replies { - bool embeddable; - String href; + bool? embeddable; + String? href; - Replies({this.embeddable, this.href}); + Replies({ + this.embeddable, + this.href, + }); Replies.fromJson(Map json) { embeddable = json['embeddable']; @@ -354,14 +318,18 @@ class Replies { Map toJson() { final Map data = new Map(); - data['embeddable'] = this.embeddable; - data['href'] = this.href; + if (this.embeddable != null) { + data['embeddable'] = this.embeddable; + } + if (this.href != null) { + data['href'] = this.href; + } return data; } } class Archives { - String href; + String? href; Archives({this.href}); @@ -371,16 +339,21 @@ class Archives { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class VersionHistory { - int count; - String href; + int? count; + String? href; - VersionHistory({this.count, this.href}); + VersionHistory({ + this.count, + this.href, + }); VersionHistory.fromJson(Map json) { count = json['count']; @@ -389,14 +362,18 @@ class VersionHistory { Map toJson() { final Map data = new Map(); - data['count'] = this.count; - data['href'] = this.href; + if (this.count != null) { + data['count'] = this.count; + } + if (this.href != null) { + data['href'] = this.href; + } return data; } } class WpPostType { - String href; + String? href; WpPostType({this.href}); @@ -406,13 +383,68 @@ class WpPostType { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } + return data; + } +} + +class PredecessorVersion { + int? id; + String? href; + + PredecessorVersion({ + this.id, + this.href, + }); + + PredecessorVersion.fromJson(Map json) { + id = json['id']; + href = json['href']; + } + + Map toJson() { + final Map data = new Map(); + + if (this.id != null) { + data['id'] = this.id; + } + if (this.href != null) { + data['href'] = this.href; + } + return data; + } +} + +class WpFeaturedmedia { + bool? embeddable; + String? href; + + WpFeaturedmedia({ + this.embeddable, + this.href, + }); + + WpFeaturedmedia.fromJson(Map json) { + embeddable = json['embeddable']; + href = json['href']; + } + + Map toJson() { + final Map data = new Map(); + if (this.embeddable != null) { + data['embeddable'] = this.embeddable; + } + if (this.href != null) { + data['href'] = this.href; + } return data; } } class WpAttachment { - String href; + String? href; WpAttachment({this.href}); @@ -422,17 +454,23 @@ class WpAttachment { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class WpTerm { - String taxonomy; - bool embeddable; - String href; - - WpTerm({this.taxonomy, this.embeddable, this.href}); + String? taxonomy; + bool? embeddable; + String? href; + + WpTerm({ + this.taxonomy, + this.embeddable, + this.href, + }); WpTerm.fromJson(Map json) { taxonomy = json['taxonomy']; @@ -442,15 +480,21 @@ class WpTerm { Map toJson() { final Map data = new Map(); - data['taxonomy'] = this.taxonomy; - data['embeddable'] = this.embeddable; - data['href'] = this.href; + if (this.taxonomy != null) { + data['taxonomy'] = this.taxonomy; + } + if (this.embeddable != null) { + data['embeddable'] = this.embeddable; + } + if (this.href != null) { + data['href'] = this.href; + } return data; } } class WpActionPublish { - String href; + String? href; WpActionPublish({this.href}); @@ -460,13 +504,15 @@ class WpActionPublish { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class WpActionUnfilteredHtml { - String href; + String? href; WpActionUnfilteredHtml({this.href}); @@ -476,13 +522,15 @@ class WpActionUnfilteredHtml { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class WpActionSticky { - String href; + String? href; WpActionSticky({this.href}); @@ -492,13 +540,15 @@ class WpActionSticky { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class WpActionAssignAuthor { - String href; + String? href; WpActionAssignAuthor({this.href}); @@ -508,13 +558,15 @@ class WpActionAssignAuthor { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class WpActionCreateCategories { - String href; + String? href; WpActionCreateCategories({this.href}); @@ -524,13 +576,15 @@ class WpActionCreateCategories { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class WpActionAssignCategories { - String href; + String? href; WpActionAssignCategories({this.href}); @@ -540,13 +594,15 @@ class WpActionAssignCategories { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class WpActionCreateTags { - String href; + String? href; WpActionCreateTags({this.href}); @@ -556,13 +612,15 @@ class WpActionCreateTags { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class WpActionAssignTags { - String href; + String? href; WpActionAssignTags({this.href}); @@ -572,13 +630,15 @@ class WpActionAssignTags { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class WpItems { - String href; + String? href; WpItems({this.href}); @@ -588,17 +648,23 @@ class WpItems { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class Up { - bool embeddable; - String postType; - String href; - - Up({this.embeddable, this.postType, this.href}); + bool? embeddable; + String? postType; + String? href; + + Up({ + this.embeddable, + this.postType, + this.href, + }); Up.fromJson(Map json) { embeddable = json['embeddable']; @@ -608,19 +674,27 @@ class Up { Map toJson() { final Map data = new Map(); - data['embeddable'] = this.embeddable; - data['post_type'] = this.postType; - data['href'] = this.href; + if (this.embeddable != null) { + data['embeddable'] = this.embeddable; + } + if (this.postType != null) { + data['post_type'] = this.postType; + } + if (this.href != null) { + data['href'] = this.href; + } return data; } } - class InReplyTo { - bool embeddable; - String href; + bool? embeddable; + String? href; - InReplyTo({this.embeddable, this.href}); + InReplyTo({ + this.embeddable, + this.href, + }); InReplyTo.fromJson(Map json) { embeddable = json['embeddable']; @@ -629,14 +703,18 @@ class InReplyTo { Map toJson() { final Map data = new Map(); - data['embeddable'] = this.embeddable; - data['href'] = this.href; + if (this.embeddable != null) { + data['embeddable'] = this.embeddable; + } + if (this.href != null) { + data['href'] = this.href; + } return data; } } class Children { - String href; + String? href; Children({this.href}); @@ -646,17 +724,23 @@ class Children { Map toJson() { final Map data = new Map(); - data['href'] = this.href; + if (this.href != null) { + data['href'] = this.href; + } return data; } } class Curies { - String name; - String href; - bool templated; - - Curies({this.name, this.href, this.templated}); + String? name; + String? href; + bool? templated; + + Curies({ + this.name, + this.href, + this.templated, + }); Curies.fromJson(Map json) { name = json['name']; @@ -666,9 +750,15 @@ class Curies { Map toJson() { final Map data = new Map(); - data['name'] = this.name; - data['href'] = this.href; - data['templated'] = this.templated; + if (this.name != null) { + data['name'] = this.name; + } + if (this.href != null) { + data['href'] = this.href; + } + if (this.templated != null) { + data['templated'] = this.templated; + } return data; } } diff --git a/lib/schemas/media.dart b/lib/schemas/media.dart index becfee4..293a5d0 100644 --- a/lib/schemas/media.dart +++ b/lib/schemas/media.dart @@ -1,64 +1,63 @@ -import 'links.dart'; import 'guid.dart'; +import 'links.dart'; import 'title.dart'; class Media { - int id; - String date; - String dateGmt; - Guid guid; - String modified; - String modifiedGmt; - String slug; - String status; - String type; - String link; - Title title; - int author; - String commentStatus; - String pingStatus; - String template; -// List meta; - String permalinkTemplate; - String generatedSlug; - Description description; - Caption caption; - String altText; - String mediaType; - String mimeType; - MediaDetails mediaDetails; - Null post; - String sourceUrl; - Links lLinks; - - Media( - {this.id, - this.date, - this.dateGmt, - this.guid, - this.modified, - this.modifiedGmt, - this.slug, - this.status, - this.type, - this.link, - this.title, - this.author, - this.commentStatus, - this.pingStatus, - this.template, -// this.meta, - this.permalinkTemplate, - this.generatedSlug, - this.description, - this.caption, - this.altText, - this.mediaType, - this.mimeType, - this.mediaDetails, - this.post, - this.sourceUrl, - this.lLinks}); + int? id; + String? date; + String? dateGmt; + Guid? guid; + String? modified; + String? modifiedGmt; + String? slug; + String? status; + String? type; + String? link; + Title? title; + int? author; + String? commentStatus; + String? pingStatus; + String? template; + String? permalinkTemplate; + String? generatedSlug; + Description? description; + Caption? caption; + String? altText; + String? mediaType; + String? mimeType; + MediaDetails? mediaDetails; + int? post; + String? sourceUrl; + Links? lLinks; + + Media({ + this.id, + this.date, + this.dateGmt, + this.guid, + this.modified, + this.modifiedGmt, + this.slug, + this.status, + this.type, + this.link, + this.title, + this.author, + this.commentStatus, + this.pingStatus, + this.template, + this.permalinkTemplate, + this.generatedSlug, + this.description, + this.caption, + this.altText, + this.mediaType, + this.mimeType, + this.mediaDetails, + this.post, + this.sourceUrl, + this.lLinks, + }); Media.fromJson(Map json) { id = json['id']; @@ -76,19 +75,13 @@ class Media { commentStatus = json['comment_status']; pingStatus = json['ping_status']; template = json['template']; - /*if (json['meta'] != null) { - meta = new List(); - json['meta'].forEach((v) { - meta.add(new Null.fromJson(v)); - }); - }*/ permalinkTemplate = json['permalink_template']; generatedSlug = json['generated_slug']; description = json['description'] != null ? new Description.fromJson(json['description']) : null; caption = - json['caption'] != null ? new Caption.fromJson(json['caption']) : null; + json['caption'] != null ? new Caption.fromJson(json['caption']) : null; altText = json['alt_text']; mediaType = json['media_type']; mimeType = json['mime_type']; @@ -102,56 +95,46 @@ class Media { Map toJson() { final Map data = new Map(); + data['id'] = this.id; data['date'] = this.date; data['date_gmt'] = this.dateGmt; - if (this.guid != null) { - data['guid'] = this.guid.toJson(); - } + data['guid'] = this.guid?.toJson(); data['modified'] = this.modified; data['modified_gmt'] = this.modifiedGmt; data['slug'] = this.slug; data['status'] = this.status; data['type'] = this.type; data['link'] = this.link; - if (this.title != null) { - data['title'] = this.title.toJson(); - } + data['title'] = this.title?.toJson(); data['author'] = this.author; data['comment_status'] = this.commentStatus; data['ping_status'] = this.pingStatus; data['template'] = this.template; - /*if (this.meta != null) { - data['meta'] = this.meta.map((v) => v.toJson()).toList(); - }*/ data['permalink_template'] = this.permalinkTemplate; data['generated_slug'] = this.generatedSlug; - if (this.description != null) { - data['description'] = this.description.toJson(); - } - if (this.caption != null) { - data['caption'] = this.caption.toJson(); - } + data['description'] = this.description?.toJson(); + data['caption'] = this.caption?.toJson(); data['alt_text'] = this.altText; data['media_type'] = this.mediaType; data['mime_type'] = this.mimeType; - if (this.mediaDetails != null) { - data['media_details'] = this.mediaDetails.toJson(); - } + data['media_details'] = this.mediaDetails?.toJson(); data['post'] = this.post; data['source_url'] = this.sourceUrl; - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } class Description { - String raw; - String rendered; + String? raw; + String? rendered; - Description({this.raw, this.rendered}); + Description({ + this.raw, + this.rendered, + }); Description.fromJson(Map json) { raw = json['raw']; @@ -160,17 +143,22 @@ class Description { Map toJson() { final Map data = new Map(); + data['raw'] = this.raw; data['rendered'] = this.rendered; + return data; } } class Caption { - String raw; - String rendered; + String? raw; + String? rendered; - Caption({this.raw, this.rendered}); + Caption({ + this.raw, + this.rendered, + }); Caption.fromJson(Map json) { raw = json['raw']; @@ -179,21 +167,28 @@ class Caption { Map toJson() { final Map data = new Map(); + data['raw'] = this.raw; data['rendered'] = this.rendered; + return data; } } class MediaDetails { - int width; - int height; - String file; - Sizes sizes; - ImageMeta imageMeta; - - MediaDetails( - {this.width, this.height, this.file, this.sizes, this.imageMeta}); + int? width; + int? height; + String? file; + Sizes? sizes; + ImageMeta? imageMeta; + + MediaDetails({ + this.width, + this.height, + this.file, + this.sizes, + this.imageMeta, + }); MediaDetails.fromJson(Map json) { width = json['width']; @@ -207,71 +202,78 @@ class MediaDetails { Map toJson() { final Map data = new Map(); + data['width'] = this.width; data['height'] = this.height; data['file'] = this.file; - if (this.sizes != null) { - data['sizes'] = this.sizes.toJson(); - } - if (this.imageMeta != null) { - data['image_meta'] = this.imageMeta.toJson(); - } + data['sizes'] = this.sizes?.toJson(); + data['image_meta'] = this.imageMeta?.toJson(); + return data; } } class Sizes { - Thumbnail thumbnail; - Medium medium; - MediumLarge mediumLarge; - Large large; - Full full; - - Sizes({this.thumbnail, this.medium, this.mediumLarge, this.large, this.full}); + Thumbnail? thumbnail; + Medium? medium; + MediumLarge? mediumLarge; + Large? large; + PostThumbnail? postThumbnail; + Full? full; + + Sizes({ + this.thumbnail, + this.medium, + this.mediumLarge, + this.postThumbnail, + this.large, + this.full, + }); Sizes.fromJson(Map json) { thumbnail = json['thumbnail'] != null ? new Thumbnail.fromJson(json['thumbnail']) : null; medium = - json['medium'] != null ? new Medium.fromJson(json['medium']) : null; + json['medium'] != null ? new Medium.fromJson(json['medium']) : null; mediumLarge = json['medium_large'] != null ? new MediumLarge.fromJson(json['medium_large']) : null; large = json['large'] != null ? new Large.fromJson(json['large']) : null; + postThumbnail = json['post-thumbnail'] != null + ? new PostThumbnail.fromJson(json['post-thumbnail']) + : null; full = json['full'] != null ? new Full.fromJson(json['full']) : null; } Map toJson() { final Map data = new Map(); - if (this.thumbnail != null) { - data['thumbnail'] = this.thumbnail.toJson(); - } - if (this.medium != null) { - data['medium'] = this.medium.toJson(); - } - if (this.mediumLarge != null) { - data['medium_large'] = this.mediumLarge.toJson(); - } - if (this.large != null) { - data['large'] = this.large.toJson(); - } - if (this.full != null) { - data['full'] = this.full.toJson(); - } + + data['thumbnail'] = this.thumbnail?.toJson(); + data['medium'] = this.medium?.toJson(); + data['medium_large'] = this.mediumLarge?.toJson(); + data['large'] = this.large?.toJson(); + data['post-thumbnail'] = this.postThumbnail?.toJson(); + data['full'] = this.full?.toJson(); + return data; } } class Thumbnail { - String file; - int width; - int height; - String mimeType; - String sourceUrl; - - Thumbnail( - {this.file, this.width, this.height, this.mimeType, this.sourceUrl}); + String? file; + int? width; + int? height; + String? mimeType; + String? sourceUrl; + + Thumbnail({ + this.file, + this.width, + this.height, + this.mimeType, + this.sourceUrl, + }); Thumbnail.fromJson(Map json) { file = json['file']; @@ -283,23 +285,31 @@ class Thumbnail { Map toJson() { final Map data = new Map(); + data['file'] = this.file; data['width'] = this.width; data['height'] = this.height; data['mime_type'] = this.mimeType; data['source_url'] = this.sourceUrl; + return data; } } class Medium { - String file; - int width; - int height; - String mimeType; - String sourceUrl; - - Medium({this.file, this.width, this.height, this.mimeType, this.sourceUrl}); + String? file; + int? width; + int? height; + String? mimeType; + String? sourceUrl; + + Medium({ + this.file, + this.width, + this.height, + this.mimeType, + this.sourceUrl, + }); Medium.fromJson(Map json) { file = json['file']; @@ -311,24 +321,31 @@ class Medium { Map toJson() { final Map data = new Map(); + data['file'] = this.file; data['width'] = this.width; data['height'] = this.height; data['mime_type'] = this.mimeType; data['source_url'] = this.sourceUrl; + return data; } } class MediumLarge { - String file; - int width; - int height; - String mimeType; - String sourceUrl; - - MediumLarge( - {this.file, this.width, this.height, this.mimeType, this.sourceUrl}); + String? file; + int? width; + int? height; + String? mimeType; + String? sourceUrl; + + MediumLarge({ + this.file, + this.width, + this.height, + this.mimeType, + this.sourceUrl, + }); MediumLarge.fromJson(Map json) { file = json['file']; @@ -340,23 +357,31 @@ class MediumLarge { Map toJson() { final Map data = new Map(); + data['file'] = this.file; data['width'] = this.width; data['height'] = this.height; data['mime_type'] = this.mimeType; data['source_url'] = this.sourceUrl; + return data; } } class Large { - String file; - int width; - int height; - String mimeType; - String sourceUrl; - - Large({this.file, this.width, this.height, this.mimeType, this.sourceUrl}); + String? file; + int? width; + int? height; + String? mimeType; + String? sourceUrl; + + Large({ + this.file, + this.width, + this.height, + this.mimeType, + this.sourceUrl, + }); Large.fromJson(Map json) { file = json['file']; @@ -368,23 +393,67 @@ class Large { Map toJson() { final Map data = new Map(); + data['file'] = this.file; data['width'] = this.width; data['height'] = this.height; data['mime_type'] = this.mimeType; data['source_url'] = this.sourceUrl; + return data; } } -class Full { - String file; - int width; - int height; - String mimeType; - String sourceUrl; +class PostThumbnail { + String? file; + int? width; + int? height; + String? mimeType; + String? sourceUrl; + + PostThumbnail({ + this.file, + this.width, + this.height, + this.mimeType, + this.sourceUrl, + }); + + PostThumbnail.fromJson(Map json) { + file = json['file']; + width = json['width']; + height = json['height']; + mimeType = json['mime_type']; + sourceUrl = json['source_url']; + } + + Map toJson() { + final Map data = new Map(); + + data['file'] = this.file; + data['width'] = this.width; + data['height'] = this.height; + data['mime_type'] = this.mimeType; + data['source_url'] = this.sourceUrl; - Full({this.file, this.width, this.height, this.mimeType, this.sourceUrl}); + return data; + } +} + +class Full { + String? file; + int? width; + int? height; + String? mimeType; + String? sourceUrl; + + Full({ + this.file, + this.width, + this.height, + this.mimeType, + this.sourceUrl, + }); Full.fromJson(Map json) { file = json['file']; @@ -396,42 +465,43 @@ class Full { Map toJson() { final Map data = new Map(); + data['file'] = this.file; data['width'] = this.width; data['height'] = this.height; data['mime_type'] = this.mimeType; data['source_url'] = this.sourceUrl; + return data; } } class ImageMeta { - String aperture; - String credit; - String camera; - String caption; - String createdTimestamp; - String copyright; - String focalLength; - String iso; - String shutterSpeed; - String title; - String orientation; - List keywords; - - ImageMeta( - {this.aperture, - this.credit, - this.camera, - this.caption, - this.createdTimestamp, - this.copyright, - this.focalLength, - this.iso, - this.shutterSpeed, - this.title, - this.orientation, - this.keywords}); + String? aperture; + String? credit; + String? camera; + String? caption; + String? createdTimestamp; + String? copyright; + String? focalLength; + String? iso; + String? shutterSpeed; + String? title; + String? orientation; + + ImageMeta({ + this.aperture, + this.credit, + this.camera, + this.caption, + this.createdTimestamp, + this.copyright, + this.focalLength, + this.iso, + this.shutterSpeed, + this.title, + this.orientation, + }); ImageMeta.fromJson(Map json) { aperture = json['aperture']; @@ -444,12 +514,12 @@ class ImageMeta { iso = json['iso']; shutterSpeed = json['shutter_speed']; title = json['title']; - orientation = json['orientation']; - keywords = json['keywords']; + orientation = json['orientation'].toString(); } Map toJson() { final Map data = new Map(); + data['aperture'] = this.aperture; data['credit'] = this.credit; data['camera'] = this.camera; @@ -461,8 +531,7 @@ class ImageMeta { data['shutter_speed'] = this.shutterSpeed; data['title'] = this.title; data['orientation'] = this.orientation; - data['keywords'] = this.keywords; + return data; } } - diff --git a/lib/schemas/page.dart b/lib/schemas/page.dart index 53977b8..cb9ca85 100644 --- a/lib/schemas/page.dart +++ b/lib/schemas/page.dart @@ -1,62 +1,61 @@ -import 'links.dart'; import 'content.dart'; +import 'excerpt.dart'; import 'guid.dart'; +import 'links.dart'; import 'title.dart'; -import 'excerpt.dart'; class Page { - int id; - String date; - String dateGmt; - Guid guid; - String modified; - String modifiedGmt; - String password; - String slug; - String status; - String type; - String link; - Title title; - Content content; - Excerpt excerpt; - int author; - int featuredMedia; - int parent; - int menuOrder; - String commentStatus; - String pingStatus; - String template; -// List meta; - String permalinkTemplate; - String generatedSlug; - Links lLinks; + int? id; + String? date; + String? dateGmt; + Guid? guid; + String? modified; + String? modifiedGmt; + String? password; + String? slug; + String? status; + String? type; + String? link; + Title? title; + Content? content; + Excerpt? excerpt; + int? author; + int? featuredMedia; + int? parent; + int? menuOrder; + String? commentStatus; + String? pingStatus; + String? template; + String? permalinkTemplate; + String? generatedSlug; + Links? lLinks; - Page( - {this.id, - this.date, - this.dateGmt, - this.guid, - this.modified, - this.modifiedGmt, - this.password, - this.slug, - this.status, - this.type, - this.link, - this.title, - this.content, - this.excerpt, - this.author, - this.featuredMedia, - this.parent, - this.menuOrder, - this.commentStatus, - this.pingStatus, - this.template, -// this.meta, - this.permalinkTemplate, - this.generatedSlug, - this.lLinks}); + Page({ + this.id, + this.date, + this.dateGmt, + this.guid, + this.modified, + this.modifiedGmt, + this.password, + this.slug, + this.status, + this.type, + this.link, + this.title, + this.content, + this.excerpt, + this.author, + this.featuredMedia, + this.parent, + this.menuOrder, + this.commentStatus, + this.pingStatus, + this.template, + this.permalinkTemplate, + this.generatedSlug, + this.lLinks, + }); Page.fromJson(Map json) { id = json['id']; @@ -72,9 +71,9 @@ class Page { link = json['link']; title = json['title'] != null ? new Title.fromJson(json['title']) : null; content = - json['content'] != null ? new Content.fromJson(json['content']) : null; + json['content'] != null ? new Content.fromJson(json['content']) : null; excerpt = - json['excerpt'] != null ? new Excerpt.fromJson(json['excerpt']) : null; + json['excerpt'] != null ? new Excerpt.fromJson(json['excerpt']) : null; author = json['author']; featuredMedia = json['featured_media']; parent = json['parent']; @@ -82,12 +81,6 @@ class Page { commentStatus = json['comment_status']; pingStatus = json['ping_status']; template = json['template']; - /*if (json['meta'] != null) { - meta = new List(); - json['meta'].forEach((v) { - meta.add(new Null.fromJson(v)); - }); - }*/ permalinkTemplate = json['permalink_template']; generatedSlug = json['generated_slug']; lLinks = json['_links'] != null ? new Links.fromJson(json['_links']) : null; @@ -95,12 +88,11 @@ class Page { Map toJson() { final Map data = new Map(); + data['id'] = this.id; data['date'] = this.date; data['date_gmt'] = this.dateGmt; - if (this.guid != null) { - data['guid'] = this.guid.toJson(); - } + data['guid'] = this.guid?.toJson(); data['modified'] = this.modified; data['modified_gmt'] = this.modifiedGmt; data['password'] = this.password; @@ -108,15 +100,9 @@ class Page { data['status'] = this.status; data['type'] = this.type; data['link'] = this.link; - if (this.title != null) { - data['title'] = this.title.toJson(); - } - if (this.content != null) { - data['content'] = this.content.toJson(); - } - if (this.excerpt != null) { - data['excerpt'] = this.excerpt.toJson(); - } + data['title'] = this.title?.toJson(); + data['content'] = this.content?.toJson(); + data['excerpt'] = this.excerpt?.toJson(); data['author'] = this.author; data['featured_media'] = this.featuredMedia; data['parent'] = this.parent; @@ -124,16 +110,10 @@ class Page { data['comment_status'] = this.commentStatus; data['ping_status'] = this.pingStatus; data['template'] = this.template; - /*if (this.meta != null) { - data['meta'] = this.meta.map((v) => v.toJson()).toList(); - }*/ data['permalink_template'] = this.permalinkTemplate; data['generated_slug'] = this.generatedSlug; - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } - - diff --git a/lib/schemas/post.dart b/lib/schemas/post.dart index 2f77373..0ecd0b2 100644 --- a/lib/schemas/post.dart +++ b/lib/schemas/post.dart @@ -1,68 +1,127 @@ -library flutter_wordpress; +import 'package:flutter_wordpress/constants.dart'; -import 'links.dart'; +import 'category.dart'; +import 'comment.dart'; +import 'comment_hierarchy.dart'; import 'content.dart'; +import 'excerpt.dart'; import 'guid.dart'; +import 'links.dart'; +import 'media.dart'; +import 'tag.dart'; import 'title.dart'; -import 'excerpt.dart'; +import 'user.dart'; +/// A [WordPress Post](https://developer.wordpress.org/rest-api/reference/posts/) +/// +/// Refer the above link to see which arguments are set based on different context modes. +/// ([WordPressContext]). class Post { - int id; - String date; - String dateGmt; - Guid guid; - String modified; - String modifiedGmt; - String password; - String slug; - String status; - String type; - String link; - Title title; - Content content; - Excerpt excerpt; - int author; - int featuredMedia; - String commentStatus; - String pingStatus; - bool sticky; - String template; - String format; -// List meta; - List categories; - List tags; - String permalinkTemplate; - String generatedSlug; - Links lLinks; - - Post( - {this.id, - this.date, - this.dateGmt, - this.guid, - this.modified, - this.modifiedGmt, - this.password, - this.slug, - this.status, - this.type, - this.link, - this.title, - this.content, - this.excerpt, - this.author, - this.featuredMedia, - this.commentStatus, - this.pingStatus, - this.sticky, - this.template, - this.format, -// this.meta, - this.categories, - this.tags, - this.permalinkTemplate, - this.generatedSlug, - this.lLinks}); + /// ID of the post + int? id; + + /// The date the post was published, in the site's Timezone. + String? date; + + /// The date the post was published, in GMT. + String? dateGmt; + Guid? guid; + String? modified; + String? modifiedGmt; + + /// Password for the post in case it needs to be password protected. + String? password; + + /// An alphanumeric identifier unique to each post. + String? slug; + + /// The state in which the post should be created (draft, publish etc.) + PostPageStatus? status; + String? type; + String? link; + + /// Post title + Title? title; + + /// Post content + Content? content; + + /// Post excerpt + Excerpt? excerpt; + + /// ID of the post author. Refer [User]. + int? authorID; + + int? featuredMediaID; + + /// Whether the post allows commenting. + PostCommentStatus? commentStatus; + + /// Whether the post can be pinged. + PostPingStatus? pingStatus; + + /// Whether the post needs to sticky i.e. a Featured post. + bool? sticky; + String? template; + + /// The format of the post. + PostFormat? format; + + /// List of IDs of categories this post belongs to. + List? categoryIDs; + + /// List of IDs of tags this post should have. + List? tagIDs; + String? permalinkTemplate; + String? generatedSlug; + Links? lLinks; + + /// The [User] object denoting the author of the post. + User? author; + + /// A list of comments for the post. + List? comments; + + /// A list of comments for the post, where each + /// [CommentHierarchy] object is a direct comment to the post, with + /// [CommentHierarchy.children] containing replies to that comment. + List? commentsHierarchy; + + /// A list of categories assigned to the post. + List? categories; + + /// A list of tags assigned to the post. + List? tags; + + /// A list of attachments contained in the post. + List? attachments; + + /// The featured Media of the post. + Media? featuredMedia; + + Post({ + this.date, + this.dateGmt, + this.password, + this.slug, + this.status = PostPageStatus.publish, + required String title, + required String content, + required String excerpt, + required this.authorID, + String? featuredMedia, + this.featuredMediaID, + this.commentStatus = PostCommentStatus.open, + this.pingStatus = PostPingStatus.open, + this.sticky, + this.template, + this.format = PostFormat.standard, + this.categoryIDs, + this.tagIDs, + }) : this.title = new Title(rendered: title), + this.featuredMedia = new Media(sourceUrl: featuredMedia), + this.content = new Content(rendered: content), + this.excerpt = new Excerpt(rendered: excerpt); Post.fromJson(Map json) { id = json['id']; @@ -73,29 +132,52 @@ class Post { modifiedGmt = json['modified_gmt']; password = json['password']; slug = json['slug']; - status = json['status']; + if (json['status'] != null) { + PostPageStatus.values.forEach((val) { + if (enumStringToName(val.toString()) == json['status']) { + status = val; + return; + } + }); + } type = json['type']; link = json['link']; title = json['title'] != null ? new Title.fromJson(json['title']) : null; content = - json['content'] != null ? new Content.fromJson(json['content']) : null; + json['content'] != null ? new Content.fromJson(json['content']) : null; excerpt = - json['excerpt'] != null ? new Excerpt.fromJson(json['excerpt']) : null; - author = json['author']; - featuredMedia = json['featured_media']; - commentStatus = json['comment_status']; - pingStatus = json['ping_status']; + json['excerpt'] != null ? new Excerpt.fromJson(json['excerpt']) : null; + authorID = json['author']; + featuredMediaID = json['featured_media']; + if (json['comment_status'] != null) { + PostCommentStatus.values.forEach((val) { + if (enumStringToName(val.toString()) == json['comment_status']) { + commentStatus = val; + return; + } + }); + } + if (json['ping_status'] != null) { + PostPingStatus.values.forEach((val) { + if (enumStringToName(val.toString()) == json['ping_status']) { + pingStatus = val; + return; + } + }); + } sticky = json['sticky']; template = json['template']; - format = json['format']; - /*if (json['meta'] != null) { - meta = new List(); - json['meta'].forEach((v) { - meta.add(new Null.fromJson(v)); + if (json['format'] != null) { + PostFormat.values.forEach((val) { + if (enumStringToName(val.toString()) == json['format']) { + format = val; + return; + } }); - }*/ - categories = json['categories'].cast(); - tags = json['tags'].cast(); + } + categoryIDs = + json['categories'] != null ? json['categories'].cast() : null; + tagIDs = json['tags'] != null ? json['tags'].cast() : null; permalinkTemplate = json['permalink_template']; generatedSlug = json['generated_slug']; lLinks = json['_links'] != null ? new Links.fromJson(json['_links']) : null; @@ -103,49 +185,31 @@ class Post { Map toJson() { final Map data = new Map(); - data['id'] = this.id; + data['date'] = this.date; data['date_gmt'] = this.dateGmt; - if (this.guid != null) { - data['guid'] = this.guid.toJson(); - } - data['modified'] = this.modified; - data['modified_gmt'] = this.modifiedGmt; data['password'] = this.password; data['slug'] = this.slug; - data['status'] = this.status; - data['type'] = this.type; - data['link'] = this.link; - if (this.title != null) { - data['title'] = this.title.toJson(); - } - if (this.content != null) { - data['content'] = this.content.toJson(); - } - if (this.excerpt != null) { - data['excerpt'] = this.excerpt.toJson(); - } - data['author'] = this.author; - data['featured_media'] = this.featuredMedia; - data['comment_status'] = this.commentStatus; - data['ping_status'] = this.pingStatus; + data['status'] = enumStringToName(this.status.toString()); + data['title'] = this.title?.toJson(); + data['content'] = this.content?.toJson(); + data['excerpt'] = this.excerpt?.toJson(); + data['author'] = this.authorID; + data['featured_media'] = this.featuredMediaID; + data['comment_status'] = enumStringToName(this.commentStatus.toString()); + data['ping_status'] = enumStringToName(this.pingStatus.toString()); data['sticky'] = this.sticky; data['template'] = this.template; - data['format'] = this.format; - /*if (this.meta != null) { - data['meta'] = this.meta.map((v) => v.toJson()).toList(); - }*/ - data['categories'] = this.categories; - data['tags'] = this.tags; - data['permalink_template'] = this.permalinkTemplate; - data['generated_slug'] = this.generatedSlug; - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['format'] = enumStringToName(this.format.toString()); + data['categories'] = listToUrlString(this.categoryIDs ?? []); + data['tags'] = listToUrlString(this.tagIDs ?? []); + return data; } + @override + String toString() { + return 'Post: { id: $id, title: ${title?.rendered}, ' + 'author: {id: $authorID, name: ${author?.name}}}'; + } } - - - diff --git a/lib/schemas/post_statuses.dart b/lib/schemas/post_statuses.dart index ebadb34..0ff5bd2 100644 --- a/lib/schemas/post_statuses.dart +++ b/lib/schemas/post_statuses.dart @@ -1,77 +1,69 @@ import 'links.dart'; class PostStatuses { - Publish publish; - Future future; - Draft draft; - Pending pending; - Private private; - Trash trash; - - PostStatuses( - {this.publish, - this.future, - this.draft, - this.pending, - this.private, - this.trash}); + Publish? publish; + Future? future; + Draft? draft; + Pending? pending; + Private? private; + Trash? trash; + + PostStatuses({ + this.publish, + this.future, + this.draft, + this.pending, + this.private, + this.trash, + }); PostStatuses.fromJson(Map json) { publish = - json['publish'] != null ? new Publish.fromJson(json['publish']) : null; + json['publish'] != null ? new Publish.fromJson(json['publish']) : null; future = - json['future'] != null ? new Future.fromJson(json['future']) : null; + json['future'] != null ? new Future.fromJson(json['future']) : null; draft = json['draft'] != null ? new Draft.fromJson(json['draft']) : null; pending = - json['pending'] != null ? new Pending.fromJson(json['pending']) : null; + json['pending'] != null ? new Pending.fromJson(json['pending']) : null; private = - json['private'] != null ? new Private.fromJson(json['private']) : null; + json['private'] != null ? new Private.fromJson(json['private']) : null; trash = json['trash'] != null ? new Trash.fromJson(json['trash']) : null; } Map toJson() { final Map data = new Map(); - if (this.publish != null) { - data['publish'] = this.publish.toJson(); - } - if (this.future != null) { - data['future'] = this.future.toJson(); - } - if (this.draft != null) { - data['draft'] = this.draft.toJson(); - } - if (this.pending != null) { - data['pending'] = this.pending.toJson(); - } - if (this.private != null) { - data['private'] = this.private.toJson(); - } - if (this.trash != null) { - data['trash'] = this.trash.toJson(); - } + + data['publish'] = this.publish?.toJson(); + data['future'] = this.future?.toJson(); + data['draft'] = this.draft?.toJson(); + data['pending'] = this.pending?.toJson(); + data['private'] = this.private?.toJson(); + data['trash'] = this.trash?.toJson(); + return data; } } class Publish { - String name; - bool private; - bool protected; - bool public; - bool queryable; - bool showInList; - String slug; - Links lLinks; - - Publish( - {this.name, - this.private, - this.protected, - this.public, - this.queryable, - this.showInList, - this.slug, - this.lLinks}); + String? name; + bool? private; + bool? protected; + bool? public; + bool? queryable; + bool? showInList; + String? slug; + Links? lLinks; + + Publish({ + this.name, + this.private, + this.protected, + this.public, + this.queryable, + this.showInList, + this.slug, + this.lLinks, + }); Publish.fromJson(Map json) { name = json['name']; @@ -86,6 +78,7 @@ class Publish { Map toJson() { final Map data = new Map(); + data['name'] = this.name; data['private'] = this.private; data['protected'] = this.protected; @@ -93,32 +86,32 @@ class Publish { data['queryable'] = this.queryable; data['show_in_list'] = this.showInList; data['slug'] = this.slug; - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } class Future { - String name; - bool private; - bool protected; - bool public; - bool queryable; - bool showInList; - String slug; - Links lLinks; - - Future( - {this.name, - this.private, - this.protected, - this.public, - this.queryable, - this.showInList, - this.slug, - this.lLinks}); + String? name; + bool? private; + bool? protected; + bool? public; + bool? queryable; + bool? showInList; + String? slug; + Links? lLinks; + + Future({ + this.name, + this.private, + this.protected, + this.public, + this.queryable, + this.showInList, + this.slug, + this.lLinks, + }); Future.fromJson(Map json) { name = json['name']; @@ -133,6 +126,7 @@ class Future { Map toJson() { final Map data = new Map(); + data['name'] = this.name; data['private'] = this.private; data['protected'] = this.protected; @@ -140,32 +134,32 @@ class Future { data['queryable'] = this.queryable; data['show_in_list'] = this.showInList; data['slug'] = this.slug; - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } class Draft { - String name; - bool private; - bool protected; - bool public; - bool queryable; - bool showInList; - String slug; - Links lLinks; - - Draft( - {this.name, - this.private, - this.protected, - this.public, - this.queryable, - this.showInList, - this.slug, - this.lLinks}); + String? name; + bool? private; + bool? protected; + bool? public; + bool? queryable; + bool? showInList; + String? slug; + Links? lLinks; + + Draft({ + this.name, + this.private, + this.protected, + this.public, + this.queryable, + this.showInList, + this.slug, + this.lLinks, + }); Draft.fromJson(Map json) { name = json['name']; @@ -180,6 +174,7 @@ class Draft { Map toJson() { final Map data = new Map(); + data['name'] = this.name; data['private'] = this.private; data['protected'] = this.protected; @@ -187,32 +182,32 @@ class Draft { data['queryable'] = this.queryable; data['show_in_list'] = this.showInList; data['slug'] = this.slug; - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } class Pending { - String name; - bool private; - bool protected; - bool public; - bool queryable; - bool showInList; - String slug; - Links lLinks; - - Pending( - {this.name, - this.private, - this.protected, - this.public, - this.queryable, - this.showInList, - this.slug, - this.lLinks}); + String? name; + bool? private; + bool? protected; + bool? public; + bool? queryable; + bool? showInList; + String? slug; + Links? lLinks; + + Pending({ + this.name, + this.private, + this.protected, + this.public, + this.queryable, + this.showInList, + this.slug, + this.lLinks, + }); Pending.fromJson(Map json) { name = json['name']; @@ -227,6 +222,7 @@ class Pending { Map toJson() { final Map data = new Map(); + data['name'] = this.name; data['private'] = this.private; data['protected'] = this.protected; @@ -234,32 +230,32 @@ class Pending { data['queryable'] = this.queryable; data['show_in_list'] = this.showInList; data['slug'] = this.slug; - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } class Private { - String name; - bool private; - bool protected; - bool public; - bool queryable; - bool showInList; - String slug; - Links lLinks; - - Private( - {this.name, - this.private, - this.protected, - this.public, - this.queryable, - this.showInList, - this.slug, - this.lLinks}); + String? name; + bool? private; + bool? protected; + bool? public; + bool? queryable; + bool? showInList; + String? slug; + Links? lLinks; + + Private({ + this.name, + this.private, + this.protected, + this.public, + this.queryable, + this.showInList, + this.slug, + this.lLinks, + }); Private.fromJson(Map json) { name = json['name']; @@ -274,6 +270,7 @@ class Private { Map toJson() { final Map data = new Map(); + data['name'] = this.name; data['private'] = this.private; data['protected'] = this.protected; @@ -281,32 +278,32 @@ class Private { data['queryable'] = this.queryable; data['show_in_list'] = this.showInList; data['slug'] = this.slug; - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } class Trash { - String name; - bool private; - bool protected; - bool public; - bool queryable; - bool showInList; - String slug; - Links lLinks; - - Trash( - {this.name, - this.private, - this.protected, - this.public, - this.queryable, - this.showInList, - this.slug, - this.lLinks}); + String? name; + bool? private; + bool? protected; + bool? public; + bool? queryable; + bool? showInList; + String? slug; + Links? lLinks; + + Trash({ + this.name, + this.private, + this.protected, + this.public, + this.queryable, + this.showInList, + this.slug, + this.lLinks, + }); Trash.fromJson(Map json) { name = json['name']; @@ -321,6 +318,7 @@ class Trash { Map toJson() { final Map data = new Map(); + data['name'] = this.name; data['private'] = this.private; data['protected'] = this.protected; @@ -328,9 +326,8 @@ class Trash { data['queryable'] = this.queryable; data['show_in_list'] = this.showInList; data['slug'] = this.slug; - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } diff --git a/lib/schemas/post_types.dart b/lib/schemas/post_types.dart index 9fa752f..400af3f 100644 --- a/lib/schemas/post_types.dart +++ b/lib/schemas/post_types.dart @@ -1,18 +1,25 @@ -import 'links.dart'; -import 'labels.dart'; import 'capabilities.dart'; +import 'labels.dart'; +import 'links.dart'; class PostTypes { - PostTypePost post; - PostTypePage page; - Attachment attachment; - WpBlock wpBlock; + PostTypePost? post; + PostTypePage? page; + Attachment? attachment; + WpBlock? wpBlock; - PostTypes({this.post, this.page, this.attachment, this.wpBlock}); + PostTypes({ + this.post, + this.page, + this.attachment, + this.wpBlock, + }); PostTypes.fromJson(Map json) { - post = json['post'] != null ? new PostTypePost.fromJson(json['post']) : null; - page = json['page'] != null ? new PostTypePage.fromJson(json['page']) : null; + post = + json['post'] != null ? new PostTypePost.fromJson(json['post']) : null; + page = + json['page'] != null ? new PostTypePage.fromJson(json['page']) : null; attachment = json['attachment'] != null ? new Attachment.fromJson(json['attachment']) : null; @@ -23,47 +30,42 @@ class PostTypes { Map toJson() { final Map data = new Map(); - if (this.post != null) { - data['post'] = this.post.toJson(); - } - if (this.page != null) { - data['page'] = this.page.toJson(); - } - if (this.attachment != null) { - data['attachment'] = this.attachment.toJson(); - } - if (this.wpBlock != null) { - data['wp_block'] = this.wpBlock.toJson(); - } + + data['post'] = this.post?.toJson(); + data['page'] = this.page?.toJson(); + data['attachment'] = this.attachment?.toJson(); + data['wp_block'] = this.wpBlock?.toJson(); + return data; } } class PostTypePost { - Capabilities capabilities; - String description; - bool hierarchical; - bool viewable; - Labels labels; - String name; - String slug; - Supports supports; - List taxonomies; - String restBase; - Links lLinks; - - PostTypePost( - {this.capabilities, - this.description, - this.hierarchical, - this.viewable, - this.labels, - this.name, - this.slug, - this.supports, - this.taxonomies, - this.restBase, - this.lLinks}); + Capabilities? capabilities; + String? description; + bool? hierarchical; + bool? viewable; + Labels? labels; + String? name; + String? slug; + Supports? supports; + List? taxonomies; + String? restBase; + Links? lLinks; + + PostTypePost({ + this.capabilities, + this.description, + this.hierarchical, + this.viewable, + this.labels, + this.name, + this.slug, + this.supports, + this.taxonomies, + this.restBase, + this.lLinks, + }); PostTypePost.fromJson(Map json) { capabilities = json['capabilities'] != null @@ -86,52 +88,47 @@ class PostTypePost { Map toJson() { final Map data = new Map(); - if (this.capabilities != null) { - data['capabilities'] = this.capabilities.toJson(); - } + + data['capabilities'] = this.capabilities?.toJson(); data['description'] = this.description; data['hierarchical'] = this.hierarchical; data['viewable'] = this.viewable; - if (this.labels != null) { - data['labels'] = this.labels.toJson(); - } + data['labels'] = this.labels?.toJson(); data['name'] = this.name; data['slug'] = this.slug; - if (this.supports != null) { - data['supports'] = this.supports.toJson(); - } + data['supports'] = this.supports?.toJson(); data['taxonomies'] = this.taxonomies; data['rest_base'] = this.restBase; - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } class Supports { - bool title; - bool editor; - bool author; - bool thumbnail; - bool excerpt; - bool trackbacks; - bool customFields; - bool comments; - bool revisions; - bool postFormats; - - Supports( - {this.title, - this.editor, - this.author, - this.thumbnail, - this.excerpt, - this.trackbacks, - this.customFields, - this.comments, - this.revisions, - this.postFormats}); + bool? title; + bool? editor; + bool? author; + bool? thumbnail; + bool? excerpt; + bool? trackbacks; + bool? customFields; + bool? comments; + bool? revisions; + bool? postFormats; + + Supports({ + this.title, + this.editor, + this.author, + this.thumbnail, + this.excerpt, + this.trackbacks, + this.customFields, + this.comments, + this.revisions, + this.postFormats, + }); Supports.fromJson(Map json) { title = json['title']; @@ -148,6 +145,7 @@ class Supports { Map toJson() { final Map data = new Map(); + data['title'] = this.title; data['editor'] = this.editor; data['author'] = this.author; @@ -158,35 +156,37 @@ class Supports { data['comments'] = this.comments; data['revisions'] = this.revisions; data['post-formats'] = this.postFormats; + return data; } } class PostTypePage { - Capabilities capabilities; - String description; - bool hierarchical; - bool viewable; - Labels labels; - String name; - String slug; - Supports supports; - List taxonomies; - String restBase; - Links lLinks; - - PostTypePage( - {this.capabilities, - this.description, - this.hierarchical, - this.viewable, - this.labels, - this.name, - this.slug, - this.supports, - this.taxonomies, - this.restBase, - this.lLinks}); + Capabilities? capabilities; + String? description; + bool? hierarchical; + bool? viewable; + Labels? labels; + String? name; + String? slug; + Supports? supports; + List? taxonomies; + String? restBase; + Links? lLinks; + + PostTypePage({ + this.capabilities, + this.description, + this.hierarchical, + this.viewable, + this.labels, + this.name, + this.slug, + this.supports, + this.taxonomies, + this.restBase, + this.lLinks, + }); PostTypePage.fromJson(Map json) { capabilities = json['capabilities'] != null @@ -209,54 +209,49 @@ class PostTypePage { Map toJson() { final Map data = new Map(); - if (this.capabilities != null) { - data['capabilities'] = this.capabilities.toJson(); - } + + data['capabilities'] = this.capabilities?.toJson(); data['description'] = this.description; data['hierarchical'] = this.hierarchical; data['viewable'] = this.viewable; - if (this.labels != null) { - data['labels'] = this.labels.toJson(); - } + data['labels'] = this.labels?.toJson(); data['name'] = this.name; data['slug'] = this.slug; - if (this.supports != null) { - data['supports'] = this.supports.toJson(); - } + data['supports'] = this.supports?.toJson(); data['taxonomies'] = this.taxonomies; data['rest_base'] = this.restBase; - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } class Attachment { - Capabilities capabilities; - String description; - bool hierarchical; - bool viewable; - Labels labels; - String name; - String slug; - Supports supports; - List taxonomies; - String restBase; - Links lLinks; - - Attachment( - {this.capabilities, - this.description, - this.hierarchical, - this.viewable, - this.labels, - this.name, - this.slug, - this.supports, - this.taxonomies, - this.restBase, - this.lLinks}); + Capabilities? capabilities; + String? description; + bool? hierarchical; + bool? viewable; + Labels? labels; + String? name; + String? slug; + Supports? supports; + List? taxonomies; + String? restBase; + Links? lLinks; + + Attachment({ + this.capabilities, + this.description, + this.hierarchical, + this.viewable, + this.labels, + this.name, + this.slug, + this.supports, + this.taxonomies, + this.restBase, + this.lLinks, + }); Attachment.fromJson(Map json) { capabilities = json['capabilities'] != null @@ -279,54 +274,49 @@ class Attachment { Map toJson() { final Map data = new Map(); - if (this.capabilities != null) { - data['capabilities'] = this.capabilities.toJson(); - } + + data['capabilities'] = this.capabilities?.toJson(); data['description'] = this.description; data['hierarchical'] = this.hierarchical; data['viewable'] = this.viewable; - if (this.labels != null) { - data['labels'] = this.labels.toJson(); - } + data['labels'] = this.labels?.toJson(); data['name'] = this.name; data['slug'] = this.slug; - if (this.supports != null) { - data['supports'] = this.supports.toJson(); - } + data['supports'] = this.supports?.toJson(); data['taxonomies'] = this.taxonomies; data['rest_base'] = this.restBase; - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } class WpBlock { - Capabilities capabilities; - String description; - bool hierarchical; - bool viewable; - Labels labels; - String name; - String slug; - Supports supports; - List taxonomies; - String restBase; - Links lLinks; - - WpBlock( - {this.capabilities, - this.description, - this.hierarchical, - this.viewable, - this.labels, - this.name, - this.slug, - this.supports, - this.taxonomies, - this.restBase, - this.lLinks}); + Capabilities? capabilities; + String? description; + bool? hierarchical; + bool? viewable; + Labels? labels; + String? name; + String? slug; + Supports? supports; + List? taxonomies; + String? restBase; + Links? lLinks; + + WpBlock({ + this.capabilities, + this.description, + this.hierarchical, + this.viewable, + this.labels, + this.name, + this.slug, + this.supports, + this.taxonomies, + this.restBase, + this.lLinks, + }); WpBlock.fromJson(Map json) { capabilities = json['capabilities'] != null @@ -349,25 +339,19 @@ class WpBlock { Map toJson() { final Map data = new Map(); - if (this.capabilities != null) { - data['capabilities'] = this.capabilities.toJson(); - } + + data['capabilities'] = this.capabilities?.toJson(); data['description'] = this.description; data['hierarchical'] = this.hierarchical; data['viewable'] = this.viewable; - if (this.labels != null) { - data['labels'] = this.labels.toJson(); - } + data['labels'] = this.labels?.toJson(); data['name'] = this.name; data['slug'] = this.slug; - if (this.supports != null) { - data['supports'] = this.supports.toJson(); - } + data['supports'] = this.supports?.toJson(); data['taxonomies'] = this.taxonomies; data['rest_base'] = this.restBase; - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } diff --git a/lib/schemas/settings.dart b/lib/schemas/settings.dart index 1eff782..5f2b7cf 100644 --- a/lib/schemas/settings.dart +++ b/lib/schemas/settings.dart @@ -1,36 +1,37 @@ class Settings { - String title; - String description; - String url; - String email; - String timezone; - String dateFormat; - String timeFormat; - int startOfWeek; - String language; - bool useSmilies; - int defaultCategory; - String defaultPostFormat; - int postsPerPage; - String defaultPingStatus; - String defaultCommentStatus; + String? title; + String? description; + String? url; + String? email; + String? timezone; + String? dateFormat; + String? timeFormat; + int? startOfWeek; + String? language; + bool? useSmilies; + int? defaultCategory; + String? defaultPostFormat; + int? postsPerPage; + String? defaultPingStatus; + String? defaultCommentStatus; - Settings( - {this.title, - this.description, - this.url, - this.email, - this.timezone, - this.dateFormat, - this.timeFormat, - this.startOfWeek, - this.language, - this.useSmilies, - this.defaultCategory, - this.defaultPostFormat, - this.postsPerPage, - this.defaultPingStatus, - this.defaultCommentStatus}); + Settings({ + this.title, + this.description, + this.url, + this.email, + this.timezone, + this.dateFormat, + this.timeFormat, + this.startOfWeek, + this.language, + this.useSmilies, + this.defaultCategory, + this.defaultPostFormat, + this.postsPerPage, + this.defaultPingStatus, + this.defaultCommentStatus, + }); Settings.fromJson(Map json) { title = json['title']; @@ -52,6 +53,7 @@ class Settings { Map toJson() { final Map data = new Map(); + data['title'] = this.title; data['description'] = this.description; data['url'] = this.url; @@ -67,6 +69,7 @@ class Settings { data['posts_per_page'] = this.postsPerPage; data['default_ping_status'] = this.defaultPingStatus; data['default_comment_status'] = this.defaultCommentStatus; + return data; } } diff --git a/lib/schemas/tag.dart b/lib/schemas/tag.dart index 08a6f1b..4eeaad2 100644 --- a/lib/schemas/tag.dart +++ b/lib/schemas/tag.dart @@ -1,26 +1,25 @@ import 'links.dart'; class Tag { - int id; - int count; - String description; - String link; - String name; - String slug; - String taxonomy; -// List meta; - Links lLinks; + int? id; + int? count; + String? description; + String? link; + String? name; + String? slug; + String? taxonomy; + Links? lLinks; - Tag( - {this.id, - this.count, - this.description, - this.link, - this.name, - this.slug, - this.taxonomy, -// this.meta, - this.lLinks}); + Tag({ + this.id, + this.count, + this.description, + this.link, + this.name, + this.slug, + this.taxonomy, + this.lLinks, + }); Tag.fromJson(Map json) { id = json['id']; @@ -30,17 +29,12 @@ class Tag { name = json['name']; slug = json['slug']; taxonomy = json['taxonomy']; - /*if (json['meta'] != null) { - meta = new List(); - json['meta'].forEach((v) { - meta.add(new Null.fromJson(v)); - }); - }*/ lLinks = json['_links'] != null ? new Links.fromJson(json['_links']) : null; } Map toJson() { final Map data = new Map(); + data['id'] = this.id; data['count'] = this.count; data['description'] = this.description; @@ -48,13 +42,8 @@ class Tag { data['name'] = this.name; data['slug'] = this.slug; data['taxonomy'] = this.taxonomy; - /*if (this.meta != null) { - data['meta'] = this.meta.map((v) => v.toJson()).toList(); - }*/ - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['_links'] = this.lLinks?.toJson(); + return data; } } - diff --git a/lib/schemas/taxonomies.dart b/lib/schemas/taxonomies.dart index 24eda66..202e728 100644 --- a/lib/schemas/taxonomies.dart +++ b/lib/schemas/taxonomies.dart @@ -1,12 +1,15 @@ -import 'links.dart'; -import 'labels.dart'; import 'capabilities.dart'; +import 'labels.dart'; +import 'links.dart'; class Taxonomies { - TaxonomyCategory category; - TaxonomyPostTag postTag; + TaxonomyCategory? category; + TaxonomyPostTag? postTag; - Taxonomies({this.category, this.postTag}); + Taxonomies({ + this.category, + this.postTag, + }); Taxonomies.fromJson(Map json) { category = json['category'] != null @@ -19,41 +22,40 @@ class Taxonomies { Map toJson() { final Map data = new Map(); - if (this.category != null) { - data['category'] = this.category.toJson(); - } - if (this.postTag != null) { - data['post_tag'] = this.postTag.toJson(); - } + + data['category'] = this.category?.toJson(); + data['post_tag'] = this.postTag?.toJson(); + return data; } } class TaxonomyCategory { - String name; - String slug; - Capabilities capabilities; - String description; - Labels labels; - List types; - bool showCloud; - bool hierarchical; - String restBase; - Visibility visibility; - Links lLinks; - - TaxonomyCategory( - {this.name, - this.slug, - this.capabilities, - this.description, - this.labels, - this.types, - this.showCloud, - this.hierarchical, - this.restBase, - this.visibility, - this.lLinks}); + String? name; + String? slug; + Capabilities? capabilities; + String? description; + Labels? labels; + List? types; + bool? showCloud; + bool? hierarchical; + String? restBase; + Visibility? visibility; + Links? lLinks; + + TaxonomyCategory({ + this.name, + this.slug, + this.capabilities, + this.description, + this.labels, + this.types, + this.showCloud, + this.hierarchical, + this.restBase, + this.visibility, + this.lLinks, + }); TaxonomyCategory.fromJson(Map json) { name = json['name']; @@ -63,7 +65,7 @@ class TaxonomyCategory { : null; description = json['description']; labels = - json['labels'] != null ? new Labels.fromJson(json['labels']) : null; + json['labels'] != null ? new Labels.fromJson(json['labels']) : null; types = json['types'].cast(); showCloud = json['show_cloud']; hierarchical = json['hierarchical']; @@ -76,45 +78,39 @@ class TaxonomyCategory { Map toJson() { final Map data = new Map(); + data['name'] = this.name; data['slug'] = this.slug; - if (this.capabilities != null) { - data['capabilities'] = this.capabilities.toJson(); - } + data['capabilities'] = this.capabilities?.toJson(); data['description'] = this.description; - if (this.labels != null) { - data['labels'] = this.labels.toJson(); - } + data['labels'] = this.labels?.toJson(); data['types'] = this.types; data['show_cloud'] = this.showCloud; data['hierarchical'] = this.hierarchical; data['rest_base'] = this.restBase; - if (this.visibility != null) { - data['visibility'] = this.visibility.toJson(); - } - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['visibility'] = this.visibility?.toJson(); + data['_links'] = this.lLinks?.toJson(); + return data; } } - class Visibility { - bool public; - bool publiclyQueryable; - bool showAdminColumn; - bool showInNavMenus; - bool showInQuickEdit; - bool showUi; - - Visibility( - {this.public, - this.publiclyQueryable, - this.showAdminColumn, - this.showInNavMenus, - this.showInQuickEdit, - this.showUi}); + bool? public; + bool? publiclyQueryable; + bool? showAdminColumn; + bool? showInNavMenus; + bool? showInQuickEdit; + bool? showUi; + + Visibility({ + this.public, + this.publiclyQueryable, + this.showAdminColumn, + this.showInNavMenus, + this.showInQuickEdit, + this.showUi, + }); Visibility.fromJson(Map json) { public = json['public']; @@ -127,41 +123,44 @@ class Visibility { Map toJson() { final Map data = new Map(); + data['public'] = this.public; data['publicly_queryable'] = this.publiclyQueryable; data['show_admin_column'] = this.showAdminColumn; data['show_in_nav_menus'] = this.showInNavMenus; data['show_in_quick_edit'] = this.showInQuickEdit; data['show_ui'] = this.showUi; + return data; } } class TaxonomyPostTag { - String name; - String slug; - Capabilities capabilities; - String description; - Labels labels; - List types; - bool showCloud; - bool hierarchical; - String restBase; - Visibility visibility; - Links lLinks; - - TaxonomyPostTag( - {this.name, - this.slug, - this.capabilities, - this.description, - this.labels, - this.types, - this.showCloud, - this.hierarchical, - this.restBase, - this.visibility, - this.lLinks}); + String? name; + String? slug; + Capabilities? capabilities; + String? description; + Labels? labels; + List? types; + bool? showCloud; + bool? hierarchical; + String? restBase; + Visibility? visibility; + Links? lLinks; + + TaxonomyPostTag({ + this.name, + this.slug, + this.capabilities, + this.description, + this.labels, + this.types, + this.showCloud, + this.hierarchical, + this.restBase, + this.visibility, + this.lLinks, + }); TaxonomyPostTag.fromJson(Map json) { name = json['name']; @@ -171,7 +170,7 @@ class TaxonomyPostTag { : null; description = json['description']; labels = - json['labels'] != null ? new Labels.fromJson(json['labels']) : null; + json['labels'] != null ? new Labels.fromJson(json['labels']) : null; types = json['types'].cast(); showCloud = json['show_cloud']; hierarchical = json['hierarchical']; @@ -184,26 +183,19 @@ class TaxonomyPostTag { Map toJson() { final Map data = new Map(); + data['name'] = this.name; data['slug'] = this.slug; - if (this.capabilities != null) { - data['capabilities'] = this.capabilities.toJson(); - } + data['capabilities'] = this.capabilities?.toJson(); + data['labels'] = this.labels?.toJson(); data['description'] = this.description; - if (this.labels != null) { - data['labels'] = this.labels.toJson(); - } data['types'] = this.types; data['show_cloud'] = this.showCloud; data['hierarchical'] = this.hierarchical; data['rest_base'] = this.restBase; - if (this.visibility != null) { - data['visibility'] = this.visibility.toJson(); - } - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['visibility'] = this.visibility?.toJson(); + data['_links'] = this.lLinks?.toJson(); + return data; } } - diff --git a/lib/schemas/title.dart b/lib/schemas/title.dart index 02bb4ac..bc7f083 100644 --- a/lib/schemas/title.dart +++ b/lib/schemas/title.dart @@ -1,8 +1,8 @@ class Title { - String raw; - String rendered; + String? raw; + String? rendered; - Title({this.raw, this.rendered}); + Title({this.rendered}); Title.fromJson(Map json) { raw = json['raw']; @@ -11,8 +11,10 @@ class Title { Map toJson() { final Map data = new Map(); + data['raw'] = this.raw; data['rendered'] = this.rendered; + return data; } -} \ No newline at end of file +} diff --git a/lib/schemas/user.dart b/lib/schemas/user.dart index 12a750d..30895ad 100644 --- a/lib/schemas/user.dart +++ b/lib/schemas/user.dart @@ -1,47 +1,52 @@ -import 'links.dart'; import 'avatar_urls.dart'; +import 'links.dart'; class User { - int id; - String username; - String name; - String firstName; - String lastName; - String email; - String url; - String description; - String link; - String locale; - String nickname; - String slug; - List roles; - String registeredDate; - UserCapabilities capabilities; - UserExtraCapabilities extraCapabilities; - AvatarUrls avatarUrls; -// List meta; - Links lLinks; + int? id; + String? username; + String? name; + String? firstName; + String? lastName; + String? email; + String? url; + String? description; + String? link; + String? locale; + String? nickname; + String? slug; + List? roles; + String? registeredDate; + UserCapabilities? capabilities; + UserExtraCapabilities? extraCapabilities; + AvatarUrls? avatarUrls; + Map? meta; + Links? lLinks; +// yahya - @mymakarim + String? password; +// end yahya - @mymakarim - User( - {this.id, - this.username, - this.name, - this.firstName, - this.lastName, - this.email, - this.url, - this.description, - this.link, - this.locale, - this.nickname, - this.slug, - this.roles, - this.registeredDate, - this.capabilities, - this.extraCapabilities, - this.avatarUrls, -// this.meta, - this.lLinks}); + User({ + this.id, + this.username, + this.name, + this.firstName, + this.lastName, + this.email, + this.url, + this.description, + this.link, + this.locale, + this.nickname, + this.slug, + this.roles, + this.registeredDate, + this.capabilities, + this.extraCapabilities, + this.avatarUrls, + this.meta, + this.lLinks, + this.password, + }); User.fromJson(Map json) { id = json['id']; @@ -67,17 +72,19 @@ class User { avatarUrls = json['avatar_urls'] != null ? new AvatarUrls.fromJson(json['avatar_urls']) : null; - /*if (json['meta'] != null) { - meta = new List(); - json['meta'].forEach((v) { - meta.add(new Null.fromJson(v)); + + if (json['meta'] != null && json['meta'].length > 0) { + meta = new Map(); + json['meta'].forEach((k, v) { + meta![k] = v; }); - }*/ + } lLinks = json['_links'] != null ? new Links.fromJson(json['_links']) : null; } Map toJson() { final Map data = new Map(); + data['id'] = this.id; data['username'] = this.username; data['name'] = this.name; @@ -92,21 +99,13 @@ class User { data['slug'] = this.slug; data['roles'] = this.roles; data['registered_date'] = this.registeredDate; - if (this.capabilities != null) { - data['capabilities'] = this.capabilities.toJson(); - } - if (this.extraCapabilities != null) { - data['extra_capabilities'] = this.extraCapabilities.toJson(); - } - if (this.avatarUrls != null) { - data['avatar_urls'] = this.avatarUrls.toJson(); - } - /*if (this.meta != null) { - data['meta'] = this.meta.map((v) => v.toJson()).toList(); - }*/ - if (this.lLinks != null) { - data['_links'] = this.lLinks.toJson(); - } + data['capabilities'] = this.capabilities?.toJson(); + data['extra_capabilities'] = this.extraCapabilities?.toJson(); + data['avatar_urls'] = this.avatarUrls?.toJson(); + data['meta'] = this.meta; + data['_links'] = this.lLinks?.toJson(); + data['password'] = this.password; + return data; } @@ -117,132 +116,133 @@ class User { } class UserCapabilities { - bool switchThemes; - bool editThemes; - bool activatePlugins; - bool editPlugins; - bool editUsers; - bool editFiles; - bool manageOptions; - bool moderateComments; - bool manageCategories; - bool manageLinks; - bool uploadFiles; - bool import; - bool unfilteredHtml; - bool editPosts; - bool editOthersPosts; - bool editPublishedPosts; - bool publishPosts; - bool editPages; - bool read; - bool level10; - bool level9; - bool level8; - bool level7; - bool level6; - bool level5; - bool level4; - bool level3; - bool level2; - bool level1; - bool level0; - bool editOthersPages; - bool editPublishedPages; - bool publishPages; - bool deletePages; - bool deleteOthersPages; - bool deletePublishedPages; - bool deletePosts; - bool deleteOthersPosts; - bool deletePublishedPosts; - bool deletePrivatePosts; - bool editPrivatePosts; - bool readPrivatePosts; - bool deletePrivatePages; - bool editPrivatePages; - bool readPrivatePages; - bool deleteUsers; - bool createUsers; - bool unfilteredUpload; - bool editDashboard; - bool updatePlugins; - bool deletePlugins; - bool installPlugins; - bool updateThemes; - bool installThemes; - bool updateCore; - bool listUsers; - bool removeUsers; - bool promoteUsers; - bool editThemeOptions; - bool deleteThemes; - bool export; - bool administrator; + bool? switchThemes; + bool? editThemes; + bool? activatePlugins; + bool? editPlugins; + bool? editUsers; + bool? editFiles; + bool? manageOptions; + bool? moderateComments; + bool? manageCategories; + bool? manageLinks; + bool? uploadFiles; + bool? import; + bool? unfilteredHtml; + bool? editPosts; + bool? editOthersPosts; + bool? editPublishedPosts; + bool? publishPosts; + bool? editPages; + bool? read; + bool? level10; + bool? level9; + bool? level8; + bool? level7; + bool? level6; + bool? level5; + bool? level4; + bool? level3; + bool? level2; + bool? level1; + bool? level0; + bool? editOthersPages; + bool? editPublishedPages; + bool? publishPages; + bool? deletePages; + bool? deleteOthersPages; + bool? deletePublishedPages; + bool? deletePosts; + bool? deleteOthersPosts; + bool? deletePublishedPosts; + bool? deletePrivatePosts; + bool? editPrivatePosts; + bool? readPrivatePosts; + bool? deletePrivatePages; + bool? editPrivatePages; + bool? readPrivatePages; + bool? deleteUsers; + bool? createUsers; + bool? unfilteredUpload; + bool? editDashboard; + bool? updatePlugins; + bool? deletePlugins; + bool? installPlugins; + bool? updateThemes; + bool? installThemes; + bool? updateCore; + bool? listUsers; + bool? removeUsers; + bool? promoteUsers; + bool? editThemeOptions; + bool? deleteThemes; + bool? export; + bool? administrator; - UserCapabilities( - {this.switchThemes, - this.editThemes, - this.activatePlugins, - this.editPlugins, - this.editUsers, - this.editFiles, - this.manageOptions, - this.moderateComments, - this.manageCategories, - this.manageLinks, - this.uploadFiles, - this.import, - this.unfilteredHtml, - this.editPosts, - this.editOthersPosts, - this.editPublishedPosts, - this.publishPosts, - this.editPages, - this.read, - this.level10, - this.level9, - this.level8, - this.level7, - this.level6, - this.level5, - this.level4, - this.level3, - this.level2, - this.level1, - this.level0, - this.editOthersPages, - this.editPublishedPages, - this.publishPages, - this.deletePages, - this.deleteOthersPages, - this.deletePublishedPages, - this.deletePosts, - this.deleteOthersPosts, - this.deletePublishedPosts, - this.deletePrivatePosts, - this.editPrivatePosts, - this.readPrivatePosts, - this.deletePrivatePages, - this.editPrivatePages, - this.readPrivatePages, - this.deleteUsers, - this.createUsers, - this.unfilteredUpload, - this.editDashboard, - this.updatePlugins, - this.deletePlugins, - this.installPlugins, - this.updateThemes, - this.installThemes, - this.updateCore, - this.listUsers, - this.removeUsers, - this.promoteUsers, - this.editThemeOptions, - this.deleteThemes, - this.export, - this.administrator}); + UserCapabilities({ + this.switchThemes, + this.editThemes, + this.activatePlugins, + this.editPlugins, + this.editUsers, + this.editFiles, + this.manageOptions, + this.moderateComments, + this.manageCategories, + this.manageLinks, + this.uploadFiles, + this.import, + this.unfilteredHtml, + this.editPosts, + this.editOthersPosts, + this.editPublishedPosts, + this.publishPosts, + this.editPages, + this.read, + this.level10, + this.level9, + this.level8, + this.level7, + this.level6, + this.level5, + this.level4, + this.level3, + this.level2, + this.level1, + this.level0, + this.editOthersPages, + this.editPublishedPages, + this.publishPages, + this.deletePages, + this.deleteOthersPages, + this.deletePublishedPages, + this.deletePosts, + this.deleteOthersPosts, + this.deletePublishedPosts, + this.deletePrivatePosts, + this.editPrivatePosts, + this.readPrivatePosts, + this.deletePrivatePages, + this.editPrivatePages, + this.readPrivatePages, + this.deleteUsers, + this.createUsers, + this.unfilteredUpload, + this.editDashboard, + this.updatePlugins, + this.deletePlugins, + this.installPlugins, + this.updateThemes, + this.installThemes, + this.updateCore, + this.listUsers, + this.removeUsers, + this.promoteUsers, + this.editThemeOptions, + this.deleteThemes, + this.export, + this.administrator, + }); UserCapabilities.fromJson(Map json) { switchThemes = json['switch_themes']; @@ -311,6 +311,7 @@ class UserCapabilities { Map toJson() { final Map data = new Map(); + data['switch_themes'] = this.switchThemes; data['edit_themes'] = this.editThemes; data['activate_plugins'] = this.activatePlugins; @@ -373,12 +374,13 @@ class UserCapabilities { data['delete_themes'] = this.deleteThemes; data['export'] = this.export; data['administrator'] = this.administrator; + return data; } } class UserExtraCapabilities { - bool administrator; + bool? administrator; UserExtraCapabilities({this.administrator}); @@ -388,7 +390,9 @@ class UserExtraCapabilities { Map toJson() { final Map data = new Map(); + data['administrator'] = this.administrator; + return data; } } diff --git a/lib/schemas/wordpress_error.dart b/lib/schemas/wordpress_error.dart index 1b7ce6e..0c30de2 100644 --- a/lib/schemas/wordpress_error.dart +++ b/lib/schemas/wordpress_error.dart @@ -1,10 +1,14 @@ /// All API related errors are thrown as an object of this class. class WordPressError { - String code; - String message; - Data data; + String? code; + String? message; + Data? data; - WordPressError({this.code, this.message, this.data}); + WordPressError({ + this.code, + this.message, + this.data, + }); WordPressError.fromJson(Map json) { code = json['code']; @@ -14,22 +18,22 @@ class WordPressError { Map toJson() { final Map data = new Map(); + data['code'] = this.code; data['message'] = this.message; - if (this.data != null) { - data['data'] = this.data.toJson(); - } + data['data'] = this.data?.toJson(); + return data; } @override String toString() { - return 'WordPress Error! code: $code, message: $message, status: ${data == null ? null : data.status}'; + return 'WordPress Error! code: $code, message: $message, status: ${data == null ? null : data?.status}'; } } class Data { - int status; + int? status; Data({this.status}); @@ -39,7 +43,9 @@ class Data { Map toJson() { final Map data = new Map(); + data['status'] = this.status; + return data; } } diff --git a/pubspec.lock b/pubspec.lock index d7fcc4e..b33ac9e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,5 +1,5 @@ # Generated by pub -# See https://www.dartlang.org/tools/pub/glossary#lockfile +# See https://dart.dev/tools/pub/glossary#lockfile packages: async: dependency: transitive @@ -7,140 +7,76 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.4" + version: "2.8.2" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.2" + version: "1.2.0" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.11" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" + version: "1.15.0" http: dependency: "direct main" description: name: http url: "https://pub.dartlang.org" source: hosted - version: "0.12.0+1" + version: "0.13.4" http_parser: dependency: transitive description: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "3.1.3" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.3+1" + version: "4.0.0" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" + version: "1.3.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.6.2" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" + version: "1.8.0" source_span: dependency: transitive description: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.4.1" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.9.3" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "1.6.8" + version: "1.8.1" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.1" + version: "1.2.0" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.1.6" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.8" + version: "1.3.0" sdks: - dart: ">=2.0.0 <3.0.0" + dart: ">=2.14.0 <3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index b03316a..1b43618 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,56 +1,17 @@ name: flutter_wordpress -description: Flutter Wordpress API -version: 0.1.1 +description: This library uses WordPress REST-API-V2 to provide a way for your application to + interact with your WordPress website. +version: 0.3.0-nullsafety.0 authors: -- Sachin Ganesh -- Suraj Shettigar -homepage: https://github.com/SachinGanesh/flutter_wordpress + - Sachin Ganesh + - Suraj Shettigar + - Harm-Jan Roskam + - Yahya Makarim + - Oladapo Adeola Omonayajo +homepage: https://github.com/dreamsoftin/flutter_wordpress environment: - sdk: ">=2.0.0-dev.68.0 <3.0.0" + sdk: '>=2.12.0-29.7.beta <3.0.0' dependencies: - flutter: - sdk: flutter - http: ^0.12.0+1 - -dev_dependencies: - flutter_test: - sdk: flutter - -# For information on the generic Dart part of this file, see the -# following page: https://www.dartlang.org/tools/pub/pubspec - -# The following section is specific to Flutter. -flutter: - - # To add assets to your package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.io/assets-and-images/#from-packages - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.io/assets-and-images/#resolution-aware. - - # To add custom fonts to your package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.io/custom-fonts/#from-packages + http: ^0.13.4 diff --git a/test/flutter_wordpress_test.dart b/test/flutter_wordpress_test.dart deleted file mode 100644 index 3315ca4..0000000 --- a/test/flutter_wordpress_test.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; - -import 'package:flutter_wordpress/flutter_wordpress.dart'; - -void main() { - test('adds one to input values', () { - }); -}