Initial build.
This commit is contained in:
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
*.js
|
||||||
|
*.map
|
||||||
|
*.css
|
||||||
|
ogre-schema.zip
|
||||||
|
/ogre-schema
|
||||||
|
composer.phar
|
||||||
|
/vendor/
|
||||||
|
/lib/*
|
||||||
|
/node_modules/
|
||||||
32
.vscode/ftp-sync.json
vendored
Normal file
32
.vscode/ftp-sync.json
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"remotePath": "./public_html/wp-content/plugins/ogre-schema/",
|
||||||
|
"host": "dev.ogre.me",
|
||||||
|
"username": "dev4ogre",
|
||||||
|
"password": "0M1$6O@J5j?)",
|
||||||
|
"port": 22,
|
||||||
|
"secure": true,
|
||||||
|
"protocol": "sftp",
|
||||||
|
"uploadOnSave": true,
|
||||||
|
"passive": false,
|
||||||
|
"debug": false,
|
||||||
|
"privateKeyPath": null,
|
||||||
|
"passphrase": null,
|
||||||
|
"agent": null,
|
||||||
|
"allow": [],
|
||||||
|
"ignore": [
|
||||||
|
"\\.vscode",
|
||||||
|
"\\.git",
|
||||||
|
"\\.DS_Store",
|
||||||
|
"\\.gitignore",
|
||||||
|
"\\Makefile",
|
||||||
|
"\\ogre-schema.zip"
|
||||||
|
],
|
||||||
|
"generatedFiles": {
|
||||||
|
"extensionsToInclude": [
|
||||||
|
".js",
|
||||||
|
".css",
|
||||||
|
".map"
|
||||||
|
],
|
||||||
|
"path": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"java.project.sourcePaths": [
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
||||||
25
.vscode/tasks.json
vendored
Normal file
25
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Package",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make",
|
||||||
|
"group": "build",
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "silent",
|
||||||
|
"panel": "shared",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Compile",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "make compile",
|
||||||
|
"group": "build",
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "silent",
|
||||||
|
"panel": "shared",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
38
Makefile
Normal file
38
Makefile
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
PACKAGE = ogre-schema
|
||||||
|
|
||||||
|
COMPOSER = composer
|
||||||
|
|
||||||
|
all: $(PACKAGE).zip
|
||||||
|
|
||||||
|
$(PACKAGE).zip: clean composer dir copy zip
|
||||||
|
|
||||||
|
composer:
|
||||||
|
$(COMPOSER) update
|
||||||
|
|
||||||
|
dir:
|
||||||
|
mkdir ./$(PACKAGE)
|
||||||
|
|
||||||
|
copy:
|
||||||
|
cp -RT ./acf-json ./$(PACKAGE)/acf-json
|
||||||
|
cp -RT ./data ./$(PACKAGE)/data
|
||||||
|
cp -RT ./includes ./$(PACKAGE)/includes
|
||||||
|
cp -RT ./lang ./$(PACKAGE)/lang
|
||||||
|
cp -RT ./lib ./$(PACKAGE)/lib
|
||||||
|
cp -RT ./vendor ./$(PACKAGE)/vendor
|
||||||
|
cp -f ./* ./$(PACKAGE) || true
|
||||||
|
|
||||||
|
rm ./$(PACKAGE)/composer.json
|
||||||
|
rm ./$(PACKAGE)/composer.lock
|
||||||
|
rm ./$(PACKAGE)/Makefile
|
||||||
|
rm ./$(PACKAGE)/$(PACKAGE).zip || true
|
||||||
|
|
||||||
|
zip:
|
||||||
|
zip -r ./$(PACKAGE).zip ./$(PACKAGE)
|
||||||
|
rm -r ./$(PACKAGE) || true
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -r ./$(PACKAGE) || true
|
||||||
|
rm ./$(PACKAGE).zip || true
|
||||||
|
for file in $(SASS_SCSS) ; do \
|
||||||
|
rm ./assets/css/$${file}.css || true ; \
|
||||||
|
done
|
||||||
2020
acf-json/schema.json
Normal file
2020
acf-json/schema.json
Normal file
File diff suppressed because it is too large
Load Diff
77
acf-json/settings.json
Normal file
77
acf-json/settings.json
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
{
|
||||||
|
"key": "group_5c62eb4b1bf8b",
|
||||||
|
"title": "Post Settings",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"key": "field_5c62eb66b90a5",
|
||||||
|
"label": "Enable schema on individual posts?",
|
||||||
|
"name": "schema_setting_post_enable",
|
||||||
|
"type": "true_false",
|
||||||
|
"instructions": "",
|
||||||
|
"required": 0,
|
||||||
|
"conditional_logic": 0,
|
||||||
|
"wrapper": {
|
||||||
|
"width": "",
|
||||||
|
"class": "",
|
||||||
|
"id": ""
|
||||||
|
},
|
||||||
|
"message": "",
|
||||||
|
"default_value": 0,
|
||||||
|
"ui": 1,
|
||||||
|
"ui_on_text": "",
|
||||||
|
"ui_off_text": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "field_5c62eb9db90a6",
|
||||||
|
"label": "Enabled Post Types",
|
||||||
|
"name": "schema_setting_post_type",
|
||||||
|
"type": "checkbox",
|
||||||
|
"instructions": "",
|
||||||
|
"required": 0,
|
||||||
|
"conditional_logic": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"field": "field_5c62eb66b90a5",
|
||||||
|
"operator": "==",
|
||||||
|
"value": "1"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"wrapper": {
|
||||||
|
"width": "",
|
||||||
|
"class": "",
|
||||||
|
"id": ""
|
||||||
|
},
|
||||||
|
"choices": {
|
||||||
|
"post": "Posts",
|
||||||
|
"page": "Pages",
|
||||||
|
"attachment": "Media"
|
||||||
|
},
|
||||||
|
"allow_custom": 0,
|
||||||
|
"default_value": [
|
||||||
|
"page"
|
||||||
|
],
|
||||||
|
"layout": "vertical",
|
||||||
|
"toggle": 0,
|
||||||
|
"return_format": "value",
|
||||||
|
"save_custom": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"location": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"param": "options_page",
|
||||||
|
"operator": "==",
|
||||||
|
"value": "ogreschema"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"menu_order": 10,
|
||||||
|
"position": "normal",
|
||||||
|
"style": "seamless",
|
||||||
|
"label_placement": "top",
|
||||||
|
"instruction_placement": "label",
|
||||||
|
"hide_on_screen": "",
|
||||||
|
"active": true,
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
27
composer.json
Normal file
27
composer.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "cleverogre/ogreschema",
|
||||||
|
"description": "Output schema site-wide for your website.",
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "composer",
|
||||||
|
"url": "https://wpackagist.org",
|
||||||
|
"only": [
|
||||||
|
"wpackagist-plugin/*",
|
||||||
|
"wpackagist-theme/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"magicoli/wp-package-updater-lib": "^0.1.9"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"allow-plugins": {
|
||||||
|
"composer/installers": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"post-update-cmd": [
|
||||||
|
"php vendor/magicoli/wp-package-updater-lib/install.php"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
53
composer.lock
generated
Normal file
53
composer.lock
generated
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"_readme": [
|
||||||
|
"This file locks the dependencies of your project to a known state",
|
||||||
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
|
"This file is @generated automatically"
|
||||||
|
],
|
||||||
|
"content-hash": "62a6a51cbea614094e050f847730af97",
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "magicoli/wp-package-updater-lib",
|
||||||
|
"version": "v0.1.10",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/magicoli/wp-package-updater-lib.git",
|
||||||
|
"reference": "e822132741c08d054fb97f249b1143c220f30e6f"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/magicoli/wp-package-updater-lib/zipball/e822132741c08d054fb97f249b1143c220f30e6f",
|
||||||
|
"reference": "e822132741c08d054fb97f249b1143c220f30e6f",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"froger-me/wp-plugin-update-server": "*"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"AGPL-3.0-or-later"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Magiiic"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Composer package for wp-package-updater library.",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/magicoli/wp-package-updater-lib/issues",
|
||||||
|
"source": "https://github.com/magicoli/wp-package-updater-lib/tree/v0.1.10"
|
||||||
|
},
|
||||||
|
"time": "2023-06-09T12:42:28+00:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"packages-dev": [],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"stability-flags": [],
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": [],
|
||||||
|
"platform-dev": [],
|
||||||
|
"plugin-api-version": "2.6.0"
|
||||||
|
}
|
||||||
177
data/business-type.json
Normal file
177
data/business-type.json
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
{
|
||||||
|
"None": "None",
|
||||||
|
"AnimalShelter": "Animal Shelter",
|
||||||
|
"ArchiveOrganization": "Archive Organization",
|
||||||
|
"Automotive Business": {
|
||||||
|
"AutomotiveBusiness": "Automotive Business",
|
||||||
|
"AutoBodyShop": "Auto Body Shop",
|
||||||
|
"AutoDealer": "Auto Dealer",
|
||||||
|
"AutoPartsStore": "Auto Parts Store",
|
||||||
|
"AutoRental": "Auto Rental",
|
||||||
|
"AutoRepair": "Auto Repair",
|
||||||
|
"AutoWash": "Auto Wash",
|
||||||
|
"GasStation": "Gas Station",
|
||||||
|
"MotorcycleDealer": "Motorcycle Dealer",
|
||||||
|
"MotorcycleRepair": "Motorcycle Repair"
|
||||||
|
},
|
||||||
|
"ChildCare": "Child Care",
|
||||||
|
"Dentist": "Dentist",
|
||||||
|
"DryCleaningOrLaundry": "Dry Cleaning Or Laundry",
|
||||||
|
"Emergency Service": {
|
||||||
|
"EmergencyService": "Emergency Service",
|
||||||
|
"FireStation": "FireStation",
|
||||||
|
"Hospital": "Hospital",
|
||||||
|
"PoliceStation": "PoliceStation"
|
||||||
|
},
|
||||||
|
"EmploymentAgency": "Employment Agency",
|
||||||
|
"Entertainment Business": {
|
||||||
|
"EntertainmentBusiness": "Entertainment Business",
|
||||||
|
"AdultEntertainment": "Adult Entertainment",
|
||||||
|
"AmusementPark": "Amusement Park",
|
||||||
|
"ArtGallery": "Art Gallery",
|
||||||
|
"Casino": "Casino",
|
||||||
|
"ComedyClub": "Comedy Club",
|
||||||
|
"MovieTheater": "Movie Theater",
|
||||||
|
"NightClub": "Night Club"
|
||||||
|
},
|
||||||
|
"Financial Service": {
|
||||||
|
"FinancialService": "Financial Service",
|
||||||
|
"AccountingService": "Accounting Service",
|
||||||
|
"AutomatedTeller": "Automated Teller",
|
||||||
|
"BankOrCreditUnion": "Bank or Credit Union",
|
||||||
|
"InsuranceAgency": "Insurance Agency"
|
||||||
|
},
|
||||||
|
"Food Establishment": {
|
||||||
|
"FoodEstablishment": "Food Establishment",
|
||||||
|
"Bakery": "Bakery",
|
||||||
|
"BarOrPub": "Bar or Pub",
|
||||||
|
"Brewery": "Brewery",
|
||||||
|
"CafeOrCoffeeShop": "Cafe or Coffee Shop",
|
||||||
|
"Distillery": "Distillery",
|
||||||
|
"FastFoodRestaurant": "Fast Food Restaurant",
|
||||||
|
"IceCreamShop": "Ice Cream Shop",
|
||||||
|
"Restaurant": "Restaurant",
|
||||||
|
"Winery": "Winery"
|
||||||
|
},
|
||||||
|
"Government Office": {
|
||||||
|
"GovernmentOffice": "Government Office",
|
||||||
|
"PostOffice": "Post Office"
|
||||||
|
},
|
||||||
|
"Health and Beauty Business": {
|
||||||
|
"HealthAndBeautyBusiness": "Health And Beauty Business",
|
||||||
|
"BeautySalon": "Beauty Salon",
|
||||||
|
"DaySpa": "Day Spa",
|
||||||
|
"HairSalon": "Hair Salon",
|
||||||
|
"HealthClub": "Health Club",
|
||||||
|
"NailSalon": "Nail Salon",
|
||||||
|
"TattooParlor": "Tattoo Parlor"
|
||||||
|
},
|
||||||
|
"Home and Construction Business": {
|
||||||
|
"HomeAndConstructionBusiness": "Home And Construction Business",
|
||||||
|
"Electrician": "Electrician",
|
||||||
|
"GeneralContractor": "General Contractor",
|
||||||
|
"HVACBusiness": "HVAC Business",
|
||||||
|
"HousePainter": "House Painter",
|
||||||
|
"Locksmith": "Locksmith",
|
||||||
|
"MovingCompany": "Moving Company",
|
||||||
|
"Plumber": "Plumber",
|
||||||
|
"RoofingContractor": "Roofing Contractor"
|
||||||
|
},
|
||||||
|
"InternetCafe": "Internet Cafe",
|
||||||
|
"Legal Service": {
|
||||||
|
"LegalService": "Legal Services",
|
||||||
|
"Attorney": "Attorney",
|
||||||
|
"Notary": "Notary"
|
||||||
|
},
|
||||||
|
"Library": "Library",
|
||||||
|
"Lodging Business": {
|
||||||
|
"LodgingBusiness": "Lodging Business",
|
||||||
|
"BedAndBreakfast": "Bed and Breakfast",
|
||||||
|
"Campground": "Campground",
|
||||||
|
"Hostel": "Hostel",
|
||||||
|
"Hotel": "Hotel",
|
||||||
|
"Motel": "Motel",
|
||||||
|
"Resort": "Resort"
|
||||||
|
},
|
||||||
|
"Medical Business": {
|
||||||
|
"MedicalBusiness": "Medical Business",
|
||||||
|
"CommunityHealth": "Community Health",
|
||||||
|
"Dentist": "Dentist",
|
||||||
|
"Dermatology": "Dermatology",
|
||||||
|
"DietNutrition": "Diet Nutrition",
|
||||||
|
"Emergency": "Emergency",
|
||||||
|
"Geriatric": "Geriatric",
|
||||||
|
"Gynecologic": "Gynecologic",
|
||||||
|
"MedicalClinic": "Medical Clinic",
|
||||||
|
"Midwifery": "Midwifery",
|
||||||
|
"Nursing": "Nursing",
|
||||||
|
"Obstetric": "Obstetric",
|
||||||
|
"Oncologic": "Oncologic",
|
||||||
|
"Optician": "Optician",
|
||||||
|
"Optometric": "Optometric",
|
||||||
|
"Otolaryngologic": "Otolaryngologic",
|
||||||
|
"Pediatric": "Pediatric",
|
||||||
|
"Pharmacy": "Pharmacy",
|
||||||
|
"Physician": "Physician",
|
||||||
|
"Physiotherapy": "Physiotherapy",
|
||||||
|
"PlasticSurgery": "Plastic Surgery",
|
||||||
|
"Podiatric": "Podiatric",
|
||||||
|
"PrimaryCare": "Primary Care",
|
||||||
|
"Psychiatric": "Psychiatric",
|
||||||
|
"PublicHealth": "Public Health"
|
||||||
|
},
|
||||||
|
"ProfessionalService": "Professional Service",
|
||||||
|
"RadioStation": "Radio Station",
|
||||||
|
"RealEstateAgent": "Real Estate Agent",
|
||||||
|
"RecyclingCenter": "Recycling Center",
|
||||||
|
"SelfStorage": "Self Storage",
|
||||||
|
"ShoppingCenter": "Shopping Center",
|
||||||
|
"Sports Activity Location": {
|
||||||
|
"SportsActivityLocation": "Sports Activity Location",
|
||||||
|
"BowlingAlley": "Bowling Alley",
|
||||||
|
"ExerciseGym": "Exercise Gym",
|
||||||
|
"GolfCourse": "Golf Course",
|
||||||
|
"HealthClub": "Health Club",
|
||||||
|
"PublicSwimmingPool": "Public Swimming Pool",
|
||||||
|
"SkiResort": "Ski Resort",
|
||||||
|
"SportsClub": "Sports Club",
|
||||||
|
"StadiumOrArena": "Stadium or Arena",
|
||||||
|
"TennisComplex": "Tennis Complex"
|
||||||
|
},
|
||||||
|
"Store": {
|
||||||
|
"Store": "Store",
|
||||||
|
"AutoPartsStore": "Auto Parts Store",
|
||||||
|
"BikeStore": "Bike Store",
|
||||||
|
"BookStore": "Book Store",
|
||||||
|
"ClothingStore": "Clothing Store",
|
||||||
|
"ComputerStore": "Computer Store",
|
||||||
|
"ConvenienceStore": "Convenience Store",
|
||||||
|
"DepartmentStore": "Department Store",
|
||||||
|
"ElectronicsStore": "Electronics Store",
|
||||||
|
"Florist": "Florist",
|
||||||
|
"FurnitureStore": "Furniture Store",
|
||||||
|
"GardenStore": "Garden Store",
|
||||||
|
"GroceryStore": "Grocery Store",
|
||||||
|
"HardwareStore": "Hardware Store",
|
||||||
|
"HobbyShop": "Hobby Shop",
|
||||||
|
"HomeGoodsStore": "Home Goods Store",
|
||||||
|
"JewelryStore": "Jewelry Store",
|
||||||
|
"LiquorStore": "Liquor Store",
|
||||||
|
"MensClothingStore": "Mens Clothing Store",
|
||||||
|
"MobilePhoneStore": "Mobile Phone Store",
|
||||||
|
"MovieRentalStore": "Movie Rental Store",
|
||||||
|
"MusicStore": "Music Store",
|
||||||
|
"OfficeEquipmentStore": "Office Equipment Store",
|
||||||
|
"OutletStore": "Outlet Store",
|
||||||
|
"PawnShop": "Pawn Shop",
|
||||||
|
"PetStore": "Pet Store",
|
||||||
|
"ShoeStore": "Shoe Store",
|
||||||
|
"SportingGoodsStore": "Sporting Goods Store",
|
||||||
|
"TireShop": "Tire Shop",
|
||||||
|
"ToyStore": "Toy Store",
|
||||||
|
"WholesaleStore": "Wholesale Store"
|
||||||
|
},
|
||||||
|
"TelevisionStation": "Television Station",
|
||||||
|
"TouristInformationCenter": "Tourist Information Center",
|
||||||
|
"TravelAgency": "Travel Agency"
|
||||||
|
}
|
||||||
46
data/organization-type.json
Normal file
46
data/organization-type.json
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"Airline": "Airline",
|
||||||
|
"Consortium": "Consortium",
|
||||||
|
"Corporation": "Corporation",
|
||||||
|
"Educational Organization": {
|
||||||
|
"EducationalOrganization": "Educational Organization",
|
||||||
|
"CollegeOrUniversity": "College or University",
|
||||||
|
"ElementarySchool": "Elementary School",
|
||||||
|
"HighSchool": "High School",
|
||||||
|
"MiddleSchool": "Middle School",
|
||||||
|
"Preschool": "Preschool",
|
||||||
|
"School": "School"
|
||||||
|
},
|
||||||
|
"FundingScheme": "Funding Scheme",
|
||||||
|
"GovernmentOrganization": "Government Organization",
|
||||||
|
"LibrarySystem": "Library System",
|
||||||
|
"LocalBusiness": "Local Business",
|
||||||
|
"Medical Organization": {
|
||||||
|
"MedicalOrganization": "Medical Organization",
|
||||||
|
"Dentist": "Dentist",
|
||||||
|
"DiagnosticLab": "Diagnostic Lab",
|
||||||
|
"Hospital": "Hospital",
|
||||||
|
"MedicalClinic": "Medical Clinic",
|
||||||
|
"Pharmacy": "Pharmacy",
|
||||||
|
"Physician": "Physician",
|
||||||
|
"VeterinaryCare": "Veterinary Care"
|
||||||
|
},
|
||||||
|
"NGO": "NGO",
|
||||||
|
"NewsMediaOrganization": "News Media Organization",
|
||||||
|
"Performing Group": {
|
||||||
|
"PerformingGroup": "Performing Group",
|
||||||
|
"DanceGroup": "Dance Group",
|
||||||
|
"MusicGroup": "Music Group",
|
||||||
|
"TheaterGroup": "Theater Group"
|
||||||
|
},
|
||||||
|
"Project": {
|
||||||
|
"Project": "Project",
|
||||||
|
"FundingAgency": "Funding Agency",
|
||||||
|
"ResearchProject": "Research Project"
|
||||||
|
},
|
||||||
|
"Sports Organization": {
|
||||||
|
"SportsOrganization": "Sports Organization",
|
||||||
|
"SportsTeam": "Sports Team"
|
||||||
|
},
|
||||||
|
"WorkersUnion": "Workers Union"
|
||||||
|
}
|
||||||
239
includes/abstract-plugin-base.php
Normal file
239
includes/abstract-plugin-base.php
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package CleverOgre
|
||||||
|
* @subpackage OgreSchema
|
||||||
|
* @version 0.1.0
|
||||||
|
* @since 0.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OgreSchema;
|
||||||
|
|
||||||
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
abstract class PluginBase {
|
||||||
|
use Singleton;
|
||||||
|
|
||||||
|
const REQUIREMENT_NONE = 0x01;
|
||||||
|
const REQUIREMENT_PLUGIN = 0x02;
|
||||||
|
const REQUIREMENT_CLASS = 0x04;
|
||||||
|
|
||||||
|
protected string $file;
|
||||||
|
protected array $requirements;
|
||||||
|
protected array $files;
|
||||||
|
private array $plugin_data;
|
||||||
|
|
||||||
|
public function __construct(string $file = __FILE__) {
|
||||||
|
$this->file = $file;
|
||||||
|
$this->requirements = [];
|
||||||
|
$this->files = [];
|
||||||
|
$this->plugin_data = [];
|
||||||
|
|
||||||
|
// Load composer packages
|
||||||
|
$this->setup_composer();
|
||||||
|
|
||||||
|
// Setup Plugin Updates
|
||||||
|
$this->setup_updater();
|
||||||
|
|
||||||
|
// Set Text Domain
|
||||||
|
load_plugin_textdomain($this->get_textdomain(), false, plugin_basename(dirname($this->file)) . '/lang');
|
||||||
|
|
||||||
|
// Requirements Check
|
||||||
|
add_action('plugins_loaded', [$this, 'check_requirements'], 1, 0);
|
||||||
|
|
||||||
|
$this->enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin Initialization
|
||||||
|
|
||||||
|
protected function enable() {
|
||||||
|
add_action('plugins_loaded', [$this, 'load'], 10, 0);
|
||||||
|
add_filter('acf/settings/load_json', [$this, 'register_acf_json'], 10, 1);
|
||||||
|
}
|
||||||
|
protected function disable() {
|
||||||
|
remove_action('plugins_loaded', [$this, 'load'], 10, 0);
|
||||||
|
remove_filter('acf/settings/load_json', [$this, 'register_acf_json'], 10, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load() {
|
||||||
|
$this->load_files();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function register_acf_json(array $paths):array {
|
||||||
|
$path = $this->get_path() . 'acf-json';
|
||||||
|
if (!in_array($path, $paths)) $paths[] = $path;
|
||||||
|
return $paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
|
||||||
|
protected function setup_composer() {
|
||||||
|
require_once($this->get_path() . 'vendor/autoload.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setup_updater() {
|
||||||
|
global $wppul_plugin_file, $wppul_server, $wppul_license_required;
|
||||||
|
$wppul_plugin_file = $this->get_file();
|
||||||
|
$wppul_server = 'https://plugins.cleverogre.com';
|
||||||
|
$wppul_license_required = false;
|
||||||
|
if (!class_exists('Puc_v4_Factory')) require_once($this->get_path() . 'lib/wp-package-updater-lib/plugin-update-checker/plugin-update-checker.php');
|
||||||
|
require_once($this->get_path() . 'lib/wp-package-updater-lib/package-updater.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requirements
|
||||||
|
|
||||||
|
protected function add_requirement(string $key, array $data) {
|
||||||
|
$this->requirements[$key] = wp_parse_args($data, [
|
||||||
|
'name' => '',
|
||||||
|
'url' => '',
|
||||||
|
'type' => self::REQUIREMENT_NONE,
|
||||||
|
'plugin' => '',
|
||||||
|
'class' => '',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function check_requirements() {
|
||||||
|
$invalid = false;
|
||||||
|
foreach ($this->requirements as $key => $data) {
|
||||||
|
if ($data['type'] & self::REQUIREMENT_NONE) continue;
|
||||||
|
if ($data['type'] & self::REQUIREMENT_PLUGIN && !empty($data['plugin']) && function_exists('is_plugin_active') && is_plugin_active($data['plugin'])) continue;
|
||||||
|
if ($data['type'] & self::REQUIREMENT_CLASS && !empty($data['class']) && class_exists($data['class'])) continue;
|
||||||
|
|
||||||
|
$this->add_requirement_notice($data);
|
||||||
|
$invalid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!!$invalid) $this->disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function add_requirement_notice($data) {
|
||||||
|
add_action('admin_notices', function () use ($data) {
|
||||||
|
$message = sprintf(
|
||||||
|
__('In order to use the %1$s plugin, it is required that you install and activate the %3$s plugin. You can do this on the <a href="%2$s">plugins</a> page when logged in as an administrator. To download this plugin, visit the <a href="%4$s" target="_blank">%3$s website</a>.', $this->get_textdomain()),
|
||||||
|
$this->get_title(),
|
||||||
|
esc_url(admin_url('plugins.php')),
|
||||||
|
esc_html($data['name']),
|
||||||
|
esc_url($data['url'])
|
||||||
|
);
|
||||||
|
printf('<div class="%s"><p>%s</p></div>', esc_attr('notice notice-error'), wpautop(wp_kses_post($message)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin Files
|
||||||
|
|
||||||
|
protected function add_file(string $relpath):bool {
|
||||||
|
if (!is_string($relpath) || empty($relpath)) return false;
|
||||||
|
$this->files[] = $relpath;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
protected function add_files(array $relpaths):bool {
|
||||||
|
$valid = true;
|
||||||
|
foreach ($relpaths as $relpath) {
|
||||||
|
if (!$this->add_file($relpath)) $valid = false;
|
||||||
|
}
|
||||||
|
return $valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function load_files():bool {
|
||||||
|
if (empty($this->files)) return false;
|
||||||
|
$valid = true;
|
||||||
|
foreach ($this->files as $relpath) {
|
||||||
|
$path = rtrim($this->get_path(), '/') . '/' . ltrim($relpath, '/');
|
||||||
|
if (!file_exists($path)) $valid = false;
|
||||||
|
else include_once($path);
|
||||||
|
}
|
||||||
|
return $valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin Data Accessors
|
||||||
|
|
||||||
|
private function get_data(string $key):string {
|
||||||
|
if (!function_exists('get_plugin_data')) require_once(ABSPATH . 'wp-admin/includes/plugin.php');
|
||||||
|
if (!is_array($this->plugin_data) || empty($this->plugin_data)) {
|
||||||
|
$this->plugin_data = get_plugin_data($this->file);
|
||||||
|
}
|
||||||
|
if (!array_key_exists($key, $this->plugin_data)) return '';
|
||||||
|
return $this->plugin_data[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_textdomain():string {
|
||||||
|
return $this->get_data('TextDomain');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_id():string {
|
||||||
|
return $this->get_textdomain();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_version():string {
|
||||||
|
return $this->get_data('Version');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_title():string {
|
||||||
|
return __($this->get_data('Name'), $this->get_textdomain());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_description():string {
|
||||||
|
return __($this->get_data('Description'), $this->get_textdomain());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin File Path Calculations
|
||||||
|
|
||||||
|
public function get_file():string {
|
||||||
|
return $this->file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_path(string $file = ''):string {
|
||||||
|
if (empty($file)) $file = $this->file;
|
||||||
|
return trailingslashit(dirname($file));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_dir(string $file = ''):string {
|
||||||
|
$dir = $this->get_path($file);
|
||||||
|
$count = 0;
|
||||||
|
|
||||||
|
// Sanitize for Win32 installs
|
||||||
|
$dir = str_replace('\\', '/', $dir);
|
||||||
|
|
||||||
|
// If file is in plugins folder
|
||||||
|
$wp_plugin_dir = str_replace('\\', '/', WP_PLUGIN_DIR);
|
||||||
|
$dir = str_replace($wp_plugin_dir, plugins_url(), $dir, $count);
|
||||||
|
|
||||||
|
if ($count < 1) {
|
||||||
|
// If file is in wp-content folder
|
||||||
|
$wp_content_dir = str_replace('\\', '/', WP_CONTENT_DIR);
|
||||||
|
$dir = str_replace($wp_content_dir, content_url(), $dir, $count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($count < 1) {
|
||||||
|
// If file is in ??? folder
|
||||||
|
$wp_dir = str_replace('\\', '/', ABSPATH);
|
||||||
|
$dir = str_replace($wp_dir, site_url('/'), $dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_hook(string $file = ''):string {
|
||||||
|
if (empty($file)) $file = $this->file;
|
||||||
|
return basename(dirname($file)) . '/' . basename($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_url(string $file = ''):string {
|
||||||
|
if (empty($file)) $file = $this->file;
|
||||||
|
return plugin_dir_url($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static Translation Functions
|
||||||
|
|
||||||
|
public static function __(string $text):string {
|
||||||
|
return __($text, self::instance()->get_textdomain());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function esc_html__(string $text):string {
|
||||||
|
return esc_html__($text, self::instance()->get_textdomain());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function esc_attr__(string $text):string {
|
||||||
|
return esc_attr__($text, self::instance()->get_textdomain());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
261
includes/class-data.php
Normal file
261
includes/class-data.php
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package CleverOgre
|
||||||
|
* @subpackage OgreSchema
|
||||||
|
* @version 0.1.0
|
||||||
|
* @since 0.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OgreSchema;
|
||||||
|
|
||||||
|
if (!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class Data {
|
||||||
|
|
||||||
|
public const SCHEMA_TYPES = ['business', 'person', 'product', 'event', 'organization', 'website', 'custom'];
|
||||||
|
|
||||||
|
public static function get_schema():array {
|
||||||
|
if (Settings::has_post_types() && is_singular(Settings::get_post_types())) {
|
||||||
|
$schema_object = self::get_schema_object(get_the_ID());
|
||||||
|
if (!empty($schema_object)) return $schema_object;
|
||||||
|
}
|
||||||
|
return self::get_schema_object();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function has_schema():bool {
|
||||||
|
return !empty(self::get_schema());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get_schema_object(string|int $id = 'option'):array {
|
||||||
|
$cache_key = sprintf('ogreschema/get_schema_object_%s', strval($id));
|
||||||
|
if (is_array($cache = wp_cache_get($cache_key))) return $cache;
|
||||||
|
|
||||||
|
$schema_type = get_field('schema_type', $id);
|
||||||
|
if (!in_array($schema_type, self::SCHEMA_TYPES)) return [];
|
||||||
|
|
||||||
|
$acf_object = get_field('schema_' . $schema_type, $id);
|
||||||
|
$schema_object = array();
|
||||||
|
|
||||||
|
switch ($schema_type) {
|
||||||
|
|
||||||
|
case 'business':
|
||||||
|
case 'organization':
|
||||||
|
if (isset($acf_object['type']) && !empty($acf_object['type']) && strtolower($acf_object['type']) != 'none') {
|
||||||
|
$schema_object['@type'] = $acf_object['type']; // type field with capitals but without spaces
|
||||||
|
} else if ($schema_type == 'business') {
|
||||||
|
$schema_object['@type'] = 'LocalBusiness';
|
||||||
|
} else if ($schema_type == 'organization') {
|
||||||
|
$schema_object['@type'] = 'Organization';
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($acf_object['name']) && !empty($acf_object['name'])) $schema_object['name'] = $acf_object['name'];
|
||||||
|
|
||||||
|
if (isset($acf_object['urls']) && !empty($acf_object['urls']) && is_array($acf_object['urls'])) {
|
||||||
|
$schema_object['sameAs'] = array();
|
||||||
|
foreach ($acf_object['urls'] as $row) {
|
||||||
|
$schema_object['sameAs'][] = $row['url'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($acf_object['logo']) && !empty($acf_object['logo']) && isset($acf_object['logo']['url']) && !empty($acf_object['logo']['url'])) $schema_object['logo'] = $acf_object['logo']['url'];
|
||||||
|
if (isset($acf_object['image']) && !empty($acf_object['image']) && isset($acf_object['image']['url']) && !empty($acf_object['image']['url'])) $schema_object['image'] = $acf_object['image']['url'];
|
||||||
|
|
||||||
|
if (isset($acf_object['description']) && !empty($acf_object['description'])) $schema_object['description'] = $acf_object['description'];
|
||||||
|
|
||||||
|
if (isset($acf_object['address']) || isset($acf_object['city']) || isset($acf_object['state']) || isset($acf_object['postal_code']) || isset($acf_object['country'])) {
|
||||||
|
$schema_object['address'] = array('@type' => 'PostalAddress');
|
||||||
|
if (isset($acf_object['address']) && !empty($acf_object['address'])) $schema_object['address']['streetAddress'] = $acf_object['address'];
|
||||||
|
if (isset($acf_object['po_box']) && !empty($acf_object['po_box'])) $schema_object['address']['postOfficeBoxNumber'] = $acf_object['po_box'];
|
||||||
|
if (isset($acf_object['city']) && !empty($acf_object['city'])) $schema_object['address']['addressLocality'] = $acf_object['city'];
|
||||||
|
if (isset($acf_object['state']) && !empty($acf_object['state'])) $schema_object['address']['addressRegion'] = $acf_object['state'];
|
||||||
|
if (isset($acf_object['postal_code']) && !empty($acf_object['postal_code'])) $schema_object['address']['postalCode'] = $acf_object['postal_code'];
|
||||||
|
if (isset($acf_object['country']) && !empty($acf_object['country'])) $schema_object['address']['addressCountry'] = $acf_object['country'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($acf_object['location']) && is_array($acf_object['location']) && !empty($acf_object['location'])) {
|
||||||
|
$schema_object['geo'] = array(
|
||||||
|
'@type' => 'GeoCoordinates',
|
||||||
|
'latitude' => $acf_object['location']['lat'],
|
||||||
|
'longitude' => $acf_object['location']['lng'],
|
||||||
|
);
|
||||||
|
$schema_object['hasMap'] = 'https://www.google.com/maps/place/' . urlencode($acf_object['location']['address']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($acf_object['hours']) && !empty($acf_object['hours']) && is_array($acf_object['hours'])) {
|
||||||
|
$schema_object['openingHours'] = self::build_hours($acf_object['hours']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($acf_object['price']) && is_numeric($acf_object['price']) && intval($acf_object['price']) >= 1 && intval($acf_object['price']) <= 5) {
|
||||||
|
$schema_object['priceRange'] = str_repeat('$', intval($acf_object['price']));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($acf_object['phone']) && !empty($acf_object['phone'])) {
|
||||||
|
$contact = array(
|
||||||
|
'@type' => 'ContactPoint',
|
||||||
|
'telephone' => $acf_object['phone'],
|
||||||
|
);
|
||||||
|
if (isset($acf_object['contact_type']) && !empty($acf_object['contact_type']) && strtolower($acf_object['contact_type']) != 'none') $contact['contactType'] = $acf_object['contact_type'];
|
||||||
|
if (isset($acf_object['contact_option']) && !empty($acf_object['contact_option']) && strtolower($acf_object['contact_option']) != 'none') $contact['contactOption'] = $acf_object['contact_option'];
|
||||||
|
|
||||||
|
$schema_object['contactPoint'] = $contact;
|
||||||
|
$schema_object['telephone'] = $acf_object['phone'];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'person':
|
||||||
|
$schema_object['@type'] = 'person';
|
||||||
|
|
||||||
|
if (isset($acf_object['name']) && !empty($acf_object['name'])) $schema_object['name'] = $acf_object['name'];
|
||||||
|
if (isset($acf_object['job_title']) && !empty($acf_object['job_title'])) $schema_object['jobTitle'] = $acf_object['job_title'];
|
||||||
|
|
||||||
|
if (isset($acf_object['address']) || isset($acf_object['po_box']) || isset($acf_object['city']) || isset($acf_object['state']) || isset($acf_object['postal_code']) || isset($acf_object['country'])) {
|
||||||
|
$schema_object['address'] = array('@type' => 'PostalAddress');
|
||||||
|
if (isset($acf_object['address']) && !empty($acf_object['address'])) $schema_object['address']['streetAddress'] = $acf_object['address'];
|
||||||
|
if (isset($acf_object['po_box']) && !empty($acf_object['po_box'])) $schema_object['address']['postOfficeBoxNumber'] = $acf_object['po_box'];
|
||||||
|
if (isset($acf_object['city']) && !empty($acf_object['city'])) $schema_object['address']['addressLocality'] = $acf_object['city'];
|
||||||
|
if (isset($acf_object['state']) && !empty($acf_object['state'])) $schema_object['address']['addressRegion'] = $acf_object['state'];
|
||||||
|
if (isset($acf_object['postal_code']) && !empty($acf_object['postal_code'])) $schema_object['address']['postalCode'] = $acf_object['postal_code'];
|
||||||
|
if (isset($acf_object['country']) && !empty($acf_object['country'])) $schema_object['address']['addressCountry'] = $acf_object['country'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($acf_object['email']) && !empty($acf_object['email']) && is_email($acf_object['email'])) $schema_object['email'] = $acf_object['email'];
|
||||||
|
if (isset($acf_object['phone']) && !empty($acf_object['phone'])) $schema_object['telephone'] = $acf_object['phone'];
|
||||||
|
if (isset($acf_object['birth_date']) && !empty($acf_object['birth_date'])) $schema_object['birthDate'] = $acf_object['birth_date'];
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'product':
|
||||||
|
$schema_object['@type'] = 'product';
|
||||||
|
|
||||||
|
if (isset($acf_object['brand']) && !empty($acf_object['brand'])) $schema_object['brand'] = $acf_object['brand'];
|
||||||
|
if (isset($acf_object['name']) && !empty($acf_object['name'])) $schema_object['name'] = $acf_object['name'];
|
||||||
|
if (isset($acf_object['description']) && !empty($acf_object['description'])) $schema_object['description'] = $acf_object['description'];
|
||||||
|
|
||||||
|
if (isset($acf_object['image']) && !empty($acf_object['image']) && isset($acf_object['image']['url']) && !empty($acf_object['image']['url'])) $schema_object['image'] = $acf_object['image']['url'];
|
||||||
|
|
||||||
|
if (isset($acf_object['rating_value']) && !empty($acf_object['rating_value'])) {
|
||||||
|
$schema_object['aggregateRating'] = array(
|
||||||
|
'@type' => 'aggregateRating',
|
||||||
|
'ratingValue' => $acf_object['rating_value'],
|
||||||
|
);
|
||||||
|
if (isset($acf_object['review_count']) && $acf_object['review_count'] > 0) $schema_object['aggregateRating']['reviewCount'] = $acf_object['review_count'];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'event':
|
||||||
|
if (isset($acf_object['type']) && !empty($acf_object['type']) && strtolower($acf_object['type']) != 'none') {
|
||||||
|
$schema_object['@type'] = $acf_object['type']; // type field with capitals but without spaces
|
||||||
|
} else {
|
||||||
|
$schema_object['@type'] = 'Event';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($acf_object['name']) && !empty($acf_object['name'])) $schema_object['name'] = $acf_object['name'];
|
||||||
|
if (isset($acf_object['description']) && !empty($acf_object['description'])) $schema_object['description'] = $acf_object['description'];
|
||||||
|
if (isset($acf_object['date_start']) && !empty($acf_object['date_start'])) $schema_object['startDate'] = $acf_object['date_start'];
|
||||||
|
if (isset($acf_object['date_end']) && !empty($acf_object['date_end'])) $schema_object['endDate'] = $acf_object['date_end'];
|
||||||
|
|
||||||
|
if (isset($acf_object['venue_name']) || isset($acf_object['address'])) {
|
||||||
|
$location = array('@type' => 'Place');
|
||||||
|
|
||||||
|
if (isset($acf_object['venue_name']) && !empty($acf_object['venue_name'])) $location['name'] = $acf_object['venue_name'];
|
||||||
|
if (isset($acf_object['venue_url']) && !empty($acf_object['venue_url'])) $location['sameAs'] = $acf_object['venue_url'];
|
||||||
|
|
||||||
|
if (isset($acf_object['address']) && !empty($acf_object['address'])) {
|
||||||
|
$location['address'] = array(
|
||||||
|
'@type' => 'PostalAddress',
|
||||||
|
'streetAddress' => $acf_object['address'],
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isset($acf_object['city']) && !empty($acf_object['city'])) $location['address']['addressLocality'] = $acf_object['city'];
|
||||||
|
if (isset($acf_object['state']) && !empty($acf_object['state'])) $location['address']['addressRegion'] = $acf_object['state'];
|
||||||
|
if (isset($acf_object['postal_code']) && !empty($acf_object['postal_code'])) $location['address']['postalCode'] = $acf_object['postal_code'];
|
||||||
|
if (isset($acf_object['country']) && !empty($acf_object['country'])) $location['address']['addressCountry'] = $acf_object['country'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($location) > 1) $schema_object['location'] = $location;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($acf_object['offer_description']) || isset($acf_object['offer_url']) || isset($acf_object['offer_price'])) {
|
||||||
|
$offer = array('@type' => 'Offer');
|
||||||
|
|
||||||
|
if (isset($acf_object['offer_description']) && !empty($acf_object['offer_description'])) $offer['description'] = $acf_object['offer_description'];
|
||||||
|
if (isset($acf_object['offer_url']) && !empty($acf_object['offer_url'])) $offer['url'] = $acf_object['offer_url'];
|
||||||
|
if (isset($acf_object['offer_price']) && !empty($acf_object['offer_price'])) $offer['price'] = $acf_object['offer_price'];
|
||||||
|
|
||||||
|
if (count($offer) > 1) $schema_object['offer'] = $offer;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'website':
|
||||||
|
$schema_object['@type'] = 'WebSite';
|
||||||
|
|
||||||
|
if (isset($acf_object['name']) && !empty($acf_object['name'])) $schema_object['name'] = $acf_object['name'];
|
||||||
|
if (isset($acf_object['name_alternate']) && !empty($acf_object['name_alternate'])) $schema_object['alternateName'] = $acf_object['name_alternate'];
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'custom':
|
||||||
|
if (isset($acf_object['fields']) && !empty($acf_object['fields'])) {
|
||||||
|
foreach ($acf_object['fields'] as $field) {
|
||||||
|
if (!isset($field['key']) || empty($field['key'])) continue;
|
||||||
|
|
||||||
|
switch ($field['type']) {
|
||||||
|
case 'array':
|
||||||
|
$schema_object[$field['key']] = array();
|
||||||
|
foreach ($field['array'] as $array_item) {
|
||||||
|
if (!isset($array_item['value']) || empty($array_item['value'])) continue;
|
||||||
|
$schema_object[$field['key']][] = $array_item['value'];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'object':
|
||||||
|
$schema_object[$field['key']] = array();
|
||||||
|
foreach ($field['object'] as $object_item) {
|
||||||
|
if (!isset($object_item['key']) || empty($object_item['key'])) continue;
|
||||||
|
$schema_object[$field['key']][$object_item['key']] = $object_item['value'];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$schema_object[$field['key']] = $field['value'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($schema_object)) return [];
|
||||||
|
|
||||||
|
// Global Settings
|
||||||
|
if (!isset($schema_object['url'])) $schema_object['url'] = get_site_url();
|
||||||
|
if (!isset($schema_object['@context'])) $schema_object['@context'] = 'http://www.schema.org';
|
||||||
|
|
||||||
|
$schema_object = apply_filters('ogreschema/get_schema_object', $schema_object, $id);
|
||||||
|
|
||||||
|
// Set Cache
|
||||||
|
wp_cache_set($cache_key, $schema_object, 'ogre_schema');
|
||||||
|
return $schema_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function build_hours($hours_object) {
|
||||||
|
$hours = '';
|
||||||
|
foreach ($hours_object as $row) {
|
||||||
|
if (!isset($row['day']) || empty($row['day'])) continue;
|
||||||
|
if ($hours != '') $hours .= ', ';
|
||||||
|
$hours .= $row['day'];
|
||||||
|
if (isset($row['open']) && isset($row['close']) && !empty($row['open']) && !empty($row['close'])) {
|
||||||
|
$hours .= ' ' . $row['open'] . '-' . $row['close'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $hours;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
60
includes/class-fields.php
Normal file
60
includes/class-fields.php
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package CleverOgre
|
||||||
|
* @subpackage OgreSchema
|
||||||
|
* @version 0.1.0
|
||||||
|
* @since 0.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OgreSchema;
|
||||||
|
|
||||||
|
if (!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class Fields {
|
||||||
|
use Singleton;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
add_filter('acf/get_field_group', [$this, 'assign_post_type_locations'], 10, 1);
|
||||||
|
add_filter('acf/load_field/key=field_5c62eb9db90a6', [$this, 'load_post_types'], 10, 1);
|
||||||
|
add_filter('acf/load_field/key=field_5a05e86e18797', [$this, 'load_business_types'], 10, 1);
|
||||||
|
add_filter('acf/load_field/key=field_5a09f1e06f181', [$this, 'load_organization_types'], 10, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function assign_post_type_locations(array $group):array {
|
||||||
|
if ($group['key'] !== 'group_5a05f48ad5e1a' || !Settings::has_post_types()) return $group;
|
||||||
|
foreach (Settings::get_post_types() as $post_type) {
|
||||||
|
if (is_null(get_post_type_object($post_type))) continue;
|
||||||
|
$group['location'][] = [[
|
||||||
|
'param' => 'post_type',
|
||||||
|
'operator' => '==',
|
||||||
|
'value' => $post_type,
|
||||||
|
]];
|
||||||
|
}
|
||||||
|
return $group;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load_post_types(array $field):array {
|
||||||
|
$field['choices'] = wp_list_pluck(get_post_types(['public' => true], 'objects'), 'label', 'name');
|
||||||
|
return $field;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load_business_types(array $field):array {
|
||||||
|
$field['choices'] = $this->get_json_data('data/business-type.json');
|
||||||
|
return $field;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load_organization_types(array $field):array {
|
||||||
|
$field['choices'] = $this->get_json_data('data/organization-type.json');
|
||||||
|
return $field;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function get_json_data(string $relpath):array {
|
||||||
|
$path = Plugin::instance()->get_path() . ltrim($relpath, '/');
|
||||||
|
if (!str_ends_with($path, '.json') || !file_exists($path)) return [];
|
||||||
|
$data = json_decode(file_get_contents($path), true);
|
||||||
|
return is_array($data) ? $data : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Fields::instance();
|
||||||
31
includes/class-output.php
Normal file
31
includes/class-output.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package CleverOgre
|
||||||
|
* @subpackage OgreSchema
|
||||||
|
* @version 0.1.0
|
||||||
|
* @since 0.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OgreSchema;
|
||||||
|
|
||||||
|
if (!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class Output {
|
||||||
|
use Singleton;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
add_action('wp_footer', [$this, 'render']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add JSON to Footer
|
||||||
|
public function render() {
|
||||||
|
if (!Data::has_schema()) return;
|
||||||
|
printf(
|
||||||
|
'<script type="application/ld+json">%s</script>',
|
||||||
|
json_encode(Data::get_schema()) // NOTE: esc_js()?
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Output::instance();
|
||||||
72
includes/class-settings.php
Normal file
72
includes/class-settings.php
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package CleverOgre
|
||||||
|
* @subpackage OgreSchema
|
||||||
|
* @version 0.1.0
|
||||||
|
* @since 0.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OgreSchema;
|
||||||
|
|
||||||
|
if (!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class Settings {
|
||||||
|
use Singleton;
|
||||||
|
|
||||||
|
private const PARENT_SLUG = 'options-general.php';
|
||||||
|
|
||||||
|
private array $page = [];
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
add_action('admin_menu', [$this, 'admin_menu'], 20);
|
||||||
|
add_filter('plugin_action_links_' . plugin_basename(Plugin::instance()->get_file()), [$this, 'plugin_action_links'], 10, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add Schema Page to Theme Options
|
||||||
|
public function admin_menu():void {
|
||||||
|
if (!function_exists('acf_add_options_sub_page')) return;
|
||||||
|
$this->page = acf_add_options_sub_page([
|
||||||
|
'page_title' => Plugin::__('Schema Metadata'),
|
||||||
|
'menu_title' => Plugin::__('Schema'),
|
||||||
|
'parent_slug' => self::PARENT_SLUG,
|
||||||
|
'menu_slug' => Plugin::instance()->get_id(),
|
||||||
|
'update_button' => Plugin::__('Save'),
|
||||||
|
'updated_message' => Plugin::__('Schema Updated'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add plugin link
|
||||||
|
public function plugin_action_links(array $links):array {
|
||||||
|
array_unshift($links, sprintf(
|
||||||
|
'<a href="%s">%s</a>',
|
||||||
|
esc_url($this->get_url()),
|
||||||
|
Plugin::esc_html__('Settings')
|
||||||
|
));
|
||||||
|
return $links;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function get_menu_slug():string {
|
||||||
|
if (empty($this->page) || !isset($this->page['menu_slug'])) return '';
|
||||||
|
return (string)$this->page['menu_slug'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_url():string {
|
||||||
|
return add_query_arg(array_filter([
|
||||||
|
'page' => $this->get_menu_slug(),
|
||||||
|
]), admin_url(self::PARENT_SLUG));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Settings Accessors
|
||||||
|
|
||||||
|
public static function get_post_types():array {
|
||||||
|
if (get_field('schema_setting_post_enable', 'option') !== true) return [];
|
||||||
|
return is_array($post_types = get_field('schema_setting_post_type', 'option')) ? $post_types : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function has_post_types():bool {
|
||||||
|
return !empty(self::get_post_types());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::instance();
|
||||||
2
includes/index.php
Normal file
2
includes/index.php
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?php
|
||||||
|
// Silence is golden
|
||||||
60
includes/integration/class-wordpress-seo.php
Normal file
60
includes/integration/class-wordpress-seo.php
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package CleverOgre
|
||||||
|
* @subpackage OgreSchema
|
||||||
|
* @version 0.1.0
|
||||||
|
* @since 0.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OgreSchema\Integration;
|
||||||
|
|
||||||
|
if (!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
use OgreSchema\Singleton;
|
||||||
|
use OgreSchema\Data;
|
||||||
|
|
||||||
|
class YoastSEO {
|
||||||
|
use Singleton;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
add_filter('wpseo_json_ld_output', [$this, 'disable_wpseo'], 10, 2);
|
||||||
|
add_filter('ogreschema/get_schema_object', [$this, 'append_schema_data'], 10, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable Yoast JSON Output
|
||||||
|
public function disable_wpseo($data, $context) {
|
||||||
|
return !Data::has_schema() ? $data : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append unset data from Yoast
|
||||||
|
public function append_schema_data(array $schema_object, string|int $id):array {
|
||||||
|
$wpseo_schema = $this->get_wpseo_schema();
|
||||||
|
if (empty($wpseo_schema)) return $schema_object;
|
||||||
|
foreach ($wpseo_schema as $key => $value) {
|
||||||
|
if (isset($schema_object[$key]) && !empty($schema_object[$key])) continue;
|
||||||
|
$schema_object[$key] = $value;
|
||||||
|
}
|
||||||
|
return $schema_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override filter and get Yoast JSON data
|
||||||
|
private function get_wpseo_schema():array {
|
||||||
|
remove_filter('wpseo_json_ld_output', [$this, 'disable_wpseo'], 10, 2);
|
||||||
|
ob_start();
|
||||||
|
do_action('wpseo_json_ld');
|
||||||
|
$html = ob_get_clean();
|
||||||
|
add_filter('wpseo_json_ld_output', [$this, 'disable_wpseo'], 10, 2);
|
||||||
|
|
||||||
|
if (empty($html) || !preg_match_all('/<script[^>]*>(.+)<\/script>/m', $html, $matches)) return [];
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
foreach ($matches[1] as $json_str) {
|
||||||
|
$json_data = json_decode($json_str, true);
|
||||||
|
if (!is_null($json_data) && is_array($json_data)) $data = array_merge($data, $json_data);
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
YoastSEO::instance();
|
||||||
2
includes/integration/index.php
Normal file
2
includes/integration/index.php
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<?php
|
||||||
|
// Silence is golden
|
||||||
27
includes/trait-singleton.php
Normal file
27
includes/trait-singleton.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @package CleverOgre
|
||||||
|
* @subpackage OgreSchema
|
||||||
|
* @version 0.1.0
|
||||||
|
* @since 0.1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OgreSchema;
|
||||||
|
|
||||||
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
trait Singleton {
|
||||||
|
|
||||||
|
private static $instances = [];
|
||||||
|
private static $instance_classes = [];
|
||||||
|
final public static function instance() {
|
||||||
|
$class = get_called_class();
|
||||||
|
if (in_array($class, self::$instance_classes)) return self::$instances[array_search($class, self::$instance_classes)];
|
||||||
|
|
||||||
|
self::$instances[] = new $class();
|
||||||
|
self::$instance_classes[] = $class;
|
||||||
|
|
||||||
|
return self::$instances[count(self::$instances) - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
54
ogre-schema.php
Normal file
54
ogre-schema.php
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Plugin Name: OgreSchema
|
||||||
|
* Plugin URI: https://plugins.cleverogre.com/plugin/ogreschema/
|
||||||
|
* Description: Output schema site-wide for your website.
|
||||||
|
* Version: 0.1.0
|
||||||
|
* Requires at Least: 6.0
|
||||||
|
* Requires PHP: 8.0
|
||||||
|
* Author: CleverOgre
|
||||||
|
* Author URI: https://cleverogre.com/
|
||||||
|
* License: GPLv3 or later
|
||||||
|
* License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
* Text Domain: ogreschema
|
||||||
|
* Domain Path: /lang
|
||||||
|
* Update URI: https://plugins.cleverogre.com/plugin/ogreschema/
|
||||||
|
* Icon1x: https://plugins.cleverogre.com/plugin/ogreschema/?asset=icon-sm
|
||||||
|
* Icon2x: https://plugins.cleverogre.com/plugin/ogreschema/?asset=icon
|
||||||
|
* BannerHigh: https://plugins.cleverogre.com/plugin/ogreschema/?asset=banner
|
||||||
|
* BannerLow: https://plugins.cleverogre.com/plugin/ogreschema/?asset=banner-sm
|
||||||
|
* Copyright: © 2024 CleverOgre, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OgreSchema;
|
||||||
|
|
||||||
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
// Load Base Requirements
|
||||||
|
include_once(__DIR__ . '/includes/trait-singleton.php');
|
||||||
|
include_once(__DIR__ . '/includes/abstract-plugin-base.php');
|
||||||
|
|
||||||
|
class Plugin extends PluginBase {
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct(__FILE__);
|
||||||
|
|
||||||
|
$this->add_requirement('advanced-custom-fields', [
|
||||||
|
'name' => __('Advanced Custom Fields PRO', $this->get_textdomain()),
|
||||||
|
'url' => 'https://www.advancedcustomfields.com/',
|
||||||
|
'type' => self::REQUIREMENT_PLUGIN,
|
||||||
|
'plugin' => 'advanced-custom-fields-pro/acf.php',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->add_files([
|
||||||
|
'includes/class-data.php',
|
||||||
|
'includes/class-settings.php',
|
||||||
|
'includes/class-fields.php',
|
||||||
|
'includes/class-output.php',
|
||||||
|
'includes/integration/class-wordpress-seo.php',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin::instance();
|
||||||
12
package.json
Normal file
12
package.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "ogre-schema",
|
||||||
|
"title": "OgreSchema",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"author": "CleverOgre",
|
||||||
|
"license": "GPL-3.0+",
|
||||||
|
"keywords": [],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.4",
|
||||||
|
"npm": ">=1.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
56
phpcs.xml
Normal file
56
phpcs.xml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<ruleset name="SomewhereWarm-cs">
|
||||||
|
<description>SomewhereWarm Coding Standards</description>
|
||||||
|
|
||||||
|
<!-- Exclude paths -->
|
||||||
|
<exclude-pattern>tests/</exclude-pattern>
|
||||||
|
<exclude-pattern>*/node_modules/*</exclude-pattern>
|
||||||
|
<exclude-pattern>*/assets/*</exclude-pattern>
|
||||||
|
<exclude-pattern>*/src/*</exclude-pattern>
|
||||||
|
<exclude-pattern>*/vendor/*</exclude-pattern>
|
||||||
|
|
||||||
|
<!-- Configs -->
|
||||||
|
<config name="minimum_supported_wp_version" value="4.7" />
|
||||||
|
<config name="testVersion" value="5.6-" />
|
||||||
|
|
||||||
|
<!-- Rules -->
|
||||||
|
<rule ref="WooCommerce-Core">
|
||||||
|
<exclude name="Core.Commenting.CommentTags.AuthorTag" />
|
||||||
|
<exclude name="WordPress.PHP.DontExtract" />
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<rule ref="WordPress-Extra">
|
||||||
|
<exclude name="Generic.Commenting.DocComment.SpacingAfter" />
|
||||||
|
<exclude name="Generic.Files.LineEndings.InvalidEOLChar" />
|
||||||
|
<exclude name="Generic.Functions.FunctionCallArgumentSpacing.SpaceBeforeComma" />
|
||||||
|
<exclude name="Generic.WhiteSpace" />
|
||||||
|
<exclude name="PEAR.Functions.FunctionCallSignature" />
|
||||||
|
<exclude name="Squiz.Commenting" />
|
||||||
|
<exclude name="Squiz.PHP.DisallowSizeFunctionsInLoops.Found" />
|
||||||
|
<exclude name="Squiz.WhiteSpace" />
|
||||||
|
<exclude name="WordPress.Arrays" />
|
||||||
|
<exclude name="WordPress.Files.FileName" />
|
||||||
|
<exclude name="WordPress.NamingConventions" />
|
||||||
|
<exclude name="WordPress.Security.ValidatedSanitizedInput.MissingUnslash" />
|
||||||
|
<exclude name="WordPress.WP.I18n.NonSingularStringLiteralText" />
|
||||||
|
<exclude name="WordPress.WhiteSpace" />
|
||||||
|
<exclude name="WordPress.Security.EscapeOutput" />
|
||||||
|
<exclude name="Squiz.PHP.EmbeddedPhp" />
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<rule ref="PHPCompatibility">
|
||||||
|
<exclude-pattern>tests/</exclude-pattern>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
<rule ref="WordPress.Security.EscapeOutput">
|
||||||
|
<properties>
|
||||||
|
<!-- e.g. body_class, the_content, the_excerpt -->
|
||||||
|
<property name="customAutoEscapedFunctions" type="array" value="0=>woocommerce_wp_select,1=>wcs_help_tip,2=>admin_url,3=>wc_price"/>
|
||||||
|
<!-- e.g. esc_attr, esc_html, esc_url-->
|
||||||
|
<property name="customEscapingFunctions" type="array" value="0=>wcs_json_encode,1=>htmlspecialchars,2=>wp_kses_allow_underscores"/>
|
||||||
|
<!-- e.g. _deprecated_argument, printf, _e-->
|
||||||
|
<property name="customPrintingFunctions" type="array" value=""/>
|
||||||
|
</properties>
|
||||||
|
</rule>
|
||||||
|
|
||||||
|
</ruleset>
|
||||||
34
readme.txt
Normal file
34
readme.txt
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
=== OgreSchema ===
|
||||||
|
Contributors: ogrecooper
|
||||||
|
Donate link: https://cleverogre.com/
|
||||||
|
Tags: gravityforms, feed, jobs, resume, application
|
||||||
|
Requires at least: 6.0.0
|
||||||
|
Tested up to: 6.4.3
|
||||||
|
Stable tag: 0.1.0
|
||||||
|
License: GPLv2 or later
|
||||||
|
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||||
|
|
||||||
|
Output schema site-wide for your website.
|
||||||
|
|
||||||
|
== Description ==
|
||||||
|
|
||||||
|
Output schema site-wide for your website. Requires OgreCore plugin.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
* [OgreCore](https://plugins.cleverogre.com/plugin/ogrecore/)
|
||||||
|
|
||||||
|
== Installation ==
|
||||||
|
|
||||||
|
1. Upload the plugin files to the `/wp-content/plugins/ogre-schema` directory and ensure that it is active.
|
||||||
|
2. Activate the plugin through the 'Plugins' screen in WordPress.
|
||||||
|
|
||||||
|
== FAQ ==
|
||||||
|
|
||||||
|
= What is this plugin? =
|
||||||
|
|
||||||
|
If you do know what plugin you have downloaded, please contact [CleverOgre](team@cleverogre.com) for more information. This plugin is only developed for a small, private audience.
|
||||||
|
|
||||||
|
== Changelog ==
|
||||||
|
|
||||||
|
= 0.1.0 - 2024-06-06 =
|
||||||
|
* Initial build of OgreSchema plugin. Ported from OgreCore.
|
||||||
Reference in New Issue
Block a user