Created
June 29, 2019 14:41
-
-
Save Neophen/e8a96d2bc6b298b46550dec1d3b633b1 to your computer and use it in GitHub Desktop.
A json workshop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Statamic\Addons\CoopenhagenForms; | |
use Statamic\API\Entry; | |
use Statamic\API\Config; | |
use Statamic\API\Request; | |
use Statamic\API\Content; | |
use Statamic\API\Fieldset; | |
use Statamic\API\Collection; | |
use Statamic\Extend\Controller; | |
use Stringy\StaticStringy as Stringy; | |
class CoopenhagenFormsController extends Controller | |
{ | |
/** | |
* The fieldset being used for the content. | |
* | |
* @var \Statamic\Contracts\CP\Fieldset | |
*/ | |
private $fieldset; | |
private $optionalFields; | |
public function getCreate() | |
{ | |
if (!\Auth::check()) { | |
return response()->json(['message' => 'Unauthorized, please login.'], 401)->send(); | |
} | |
if (!\Statamic\API\User::getCurrent()->hasRole('editor')) { | |
return response()->json(['message' => 'Forbidden, you do not have the correct permissions to do this.'], 403)->send(); | |
} | |
$this->validate(request(), [ | |
'fieldset' => 'required', | |
]); | |
$fieldsetName = request('fieldset'); | |
if (!Fieldset::exists($fieldsetName)) { | |
return response()->json(['message' => "Fieldset '{$fieldsetName}' not found."], 404)->send(); | |
} | |
$fieldset = Fieldset::get($fieldsetName)->inlinedFields(); | |
$fields = $this->getFields($fieldset); | |
return $fields; | |
} | |
public function getEdit() | |
{ | |
if (!\Auth::check()) { | |
return response()->json(['message' => 'Unauthorized, please login.'], 401)->send(); | |
} | |
if (!\Statamic\API\User::getCurrent()->hasRole('editor')) { | |
return response()->json(['message' => 'Forbidden, you do not have the correct permissions to do this.'], 403)->send(); | |
} | |
$this->validate(request(), [ | |
'fieldset' => 'required', | |
'id' => 'required', | |
]); | |
$fieldsetName = request('fieldset'); | |
if (!Fieldset::exists($fieldsetName)) { | |
return response()->json(['message' => "Fieldset '{$fieldsetName}' not found."], 404)->send(); | |
} | |
$entryId = request('id'); | |
if (!Entry::exists($entryId)) { | |
return response()->json(['message' => "Entry '{$entryId}' not found."], 404)->send(); | |
} | |
$fieldset = Fieldset::get($fieldsetName)->inlinedFields(); | |
$fields = $this->getFields($fieldset); | |
$fieldsWithValues = $this->addValuesToFields($fields, $entryId); | |
return $fieldsWithValues; | |
} | |
public function postCreate() | |
{ | |
if (!\Auth::check()) { | |
return response()->json(['message' => 'Unauthorized, please login.'], 401)->send(); | |
} | |
if (!\Statamic\API\User::getCurrent()->hasRole('editor')) { | |
return response()->json(['message' => 'Forbidden, you do not have the correct permissions to do this.'], 403)->send(); | |
} | |
$this->validate(request(), [ | |
'collection' => 'required', | |
'fieldset' => 'required', | |
]); | |
$fields = Request::except(['_token']); | |
$collection = $fields['collection']; | |
$fieldsetName = $fields['fieldset']; | |
$visible = filter_var(request('visible'), FILTER_VALIDATE_BOOLEAN); | |
if (!Fieldset::exists($fieldsetName)) { | |
return response()->json(['message' => "Fieldset '{$fieldsetName}' not found."], 404)->send(); | |
} | |
$fieldset = Fieldset::get($fieldsetName)->inlinedFields(); | |
$fieldsetWithLocales = $this->getFields($fieldset); | |
$timestamp = time(); | |
$tempFieldset = Fieldset::create("temp-{$timestamp}", $fieldsetWithLocales); | |
$rules = $this->getValidator($tempFieldset); | |
$this->validate(request(), $rules); | |
// $tempFieldset->delete(); | |
$entry = $this->createEntry($fields, $collection, $visible); | |
return $entry->toArray(); | |
} | |
public function postEdit() | |
{ | |
if (!\Auth::check()) { | |
return response()->json(['message' => 'Unauthorized, please login.'], 401)->send(); | |
} | |
if (!\Statamic\API\User::getCurrent()->hasRole('editor')) { | |
return response()->json(['message' => 'Forbidden, you do not have the correct permissions to do this.'], 403)->send(); | |
} | |
$this->validate(request(), [ | |
'fieldset' => 'required', | |
'id' => 'required', | |
]); | |
$fields = Request::except(['_token']); | |
$fieldsetName = $fields['fieldset']; | |
$entryId = $fields['id']; | |
if (!Fieldset::exists($fieldsetName)) { | |
return response()->json(['message' => "Fieldset '{$fieldsetName}' not found."], 404)->send(); | |
} | |
$this->fieldset = Fieldset::get($fieldsetName); | |
$fieldset = $this->fieldset->inlinedFields(); | |
$fieldsetWithLocales = $this->getFields($fieldset); | |
$timestamp = time(); | |
$tempFieldset = Fieldset::create("temp-{$timestamp}", $fieldsetWithLocales); | |
$rules = $this->getValidator($tempFieldset); | |
$this->validate(request(), $rules); | |
// $tempFieldset->delete(); | |
$entry = $this->updateEntry($fields, $entryId); | |
return $entry->toArray(); | |
} | |
private function getFields(array $fields) | |
{ | |
$default = Config::getDefaultLocale(); | |
$defaultFullLocale = Config::getFullLocale($default); | |
$defaultLang = locale_get_display_language($defaultFullLocale, 'en'); | |
$allFields = []; | |
foreach ($fields as $key => $value) { | |
$allFields["{$key}_{$default}"] = $value; | |
$otherLocales = Config::getOtherLocales(); | |
if (array_has($value, 'localizable') && $value['localizable']) { | |
foreach ($otherLocales as $locale) { | |
//adding language to the field display | |
$fullLocale = Config::getFullLocale($locale); | |
$language = locale_get_display_language($fullLocale, 'en'); | |
$valWithLang = $value; | |
$valWithLang['display'] = "{$value['display']} in {$language}"; | |
//removing required | |
if (array_has($valWithLang, 'validate')) { | |
$removedFirst = str_replace('required|', '', $valWithLang['validate']); | |
$removedSecond = str_replace('required', '', $removedFirst); | |
$valWithLang['validate'] = $removedSecond; | |
} | |
$valWithLang['display'] = "{$value['display']} in {$language}"; | |
$allFields["{$key}_{$locale}"] = $valWithLang; | |
//add default as well | |
$valWithDefaultLang = $value; | |
$valWithDefaultLang['display'] = "{$value['display']} in {$defaultLang}"; | |
$allFields["{$key}_{$default}"] = $valWithDefaultLang; | |
} | |
} | |
} | |
// TODO: steped forms for locales. | |
// $otherLocales = Config::getOtherLocales(); | |
// foreach ($otherLocales as $locale) { | |
// foreach ($fieldset as $key => $value) { | |
// if (array_has($value, 'localizable') && $value['localizable']) { | |
// $allFields["{$key}_{$locale}"] = $value; | |
// } | |
// } | |
// } | |
return $allFields; | |
} | |
private function addValuesToFields(array $fields, string $entryId) | |
{ | |
$entryData = $this->getLocaleData($entryId); | |
$fieldsWithValues = $fields; | |
foreach ($fieldsWithValues as $key => $value) { | |
// where field names will always be something_lt or something_en | |
$fieldTitle = substr($key, 0, -3); | |
$locale = substr($key, -2); | |
if (array_has($entryData[$locale], $fieldTitle)) { | |
$fieldValue = $entryData[$locale][$fieldTitle]; | |
$value['value'] = $fieldValue; | |
$fieldsWithValues[$key] = $value; | |
} | |
} | |
return $fieldsWithValues; | |
} | |
private function getLocaleData(string $entryId) | |
{ | |
$entry = Entry::find($entryId); | |
$entryDataByLocale = []; | |
$locales = Config::getLocales(); | |
foreach ($locales as $locale) { | |
$entryDataByLocale[$locale] = $entry->dataForLocale($locale); | |
} | |
return $entryDataByLocale; | |
} | |
private function createEntry(array $fields, string $collectionHandle, bool $visible) | |
{ | |
$fieldsInLocales = $this->segrateFieldsByLocale($fields); | |
$defaultLocale = Config::getDefaultLocale(); | |
// TODO: first chech if has slug, then title, then sluggard or first field of type text. | |
$slug = Stringy::slugify($fieldsInLocales[$defaultLocale]['title']); | |
$collection = Collection::whereHandle($collectionHandle); | |
$defaultData = array_filter($fieldsInLocales[$defaultLocale]); | |
$factory = Entry::create($slug) | |
->collection($collection->path()) | |
->published($visible) | |
->with($defaultData); | |
$factory->set('last_edited_by', \Statamic\API\User::getCurrent()->email()); | |
$content = $factory->get(); | |
$content->ensureId(); | |
$content->save(); | |
$locales = Config::getOtherLocales(); | |
foreach ($locales as $locale) { | |
$localeSlug = $slug; | |
if (array_has($fieldsInLocales[$locale], 'title')) { | |
$localeSlug = Stringy::slugify($fieldsInLocales[$defaultLocale]['title']); | |
} | |
$data = array_merge(['slug' => $localeSlug], array_filter($fieldsInLocales[$locale])); | |
$content->dataForLocale('en', $data)->save(); | |
} | |
return $content; | |
} | |
private function updateEntry(array $fields, string $entryId) | |
{ | |
$fieldsInLocales = $this->segrateFieldsByLocale($fields); | |
$defaultLocale = Config::getDefaultLocale(); | |
$content = Content::find($entryId); | |
$slug = $content->slug(); | |
// here is the key to filtering out data! | |
$optionalFields = array_keys(array_filter($this->fieldset->inlinedFields(), [$this, 'getIsOptional'])); | |
$defaultData = $this->cleanDataFromOptionalFields($content->data(), $fieldsInLocales[$defaultLocale], $optionalFields); | |
$content->slug($slug); | |
$content->data($defaultData); | |
$content->ensureId(); | |
$content->set('last_edited_by', \Statamic\API\User::getCurrent()->email()); | |
$content->save(); | |
$locales = Config::getOtherLocales(); | |
foreach ($locales as $locale) { | |
$localeSlug = $slug; | |
if (array_has($fieldsInLocales[$locale], 'title')) { | |
$localeSlug = Stringy::slugify($fieldsInLocales[$locale]['title']); | |
} | |
$fieldsInLocales[$locale]['slug'] = $localeSlug; | |
$optionalLocaleFields = array_keys(array_filter($this->fieldset->inlinedFields(), [$this, 'getIsOptionalForLocale'])); | |
$data = $this->cleanDataFromOptionalFields($content->dataForLocale($locale), $fieldsInLocales[$locale], $optionalLocaleFields); | |
$content->dataForLocale($locale, $data)->save(); | |
} | |
return $content; | |
} | |
private function segrateFieldsByLocale(array $fields) | |
{ | |
$locales = Config::getLocales(); | |
$fieldsByLocale = []; | |
foreach ($fields as $key => $value) { | |
foreach ($locales as $locale) { | |
if ($this->endsWith($key, "_{$locale}")) { | |
$title = str_replace("_{$locale}", '', $key); | |
$fieldsByLocale[$locale][$title] = $value; | |
} | |
} | |
} | |
return $fieldsByLocale; | |
} | |
private function getValidator($fieldset) | |
{ | |
$fieldtype_rules = $this->getFieldtypeValidationRules($fieldset->fieldtypes()); | |
$field_validation_data = $this->getFieldValidationData($fieldset->inlinedFields()); | |
$rules = array_merge($fieldtype_rules, $field_validation_data); | |
return $rules; | |
} | |
private function getFieldtypeValidationRules($fieldtypes) | |
{ | |
$rules = []; | |
foreach ($fieldtypes as $fieldtype) { | |
if ($fieldtype_rules = $fieldtype->rules()) { | |
$rules["{$fieldtype->getName()}"] = $fieldtype_rules; | |
} | |
} | |
return $rules; | |
} | |
private function getFieldValidationData($fields) | |
{ | |
$rules = []; | |
foreach ($fields as $field_name => $field_config) { | |
if ($field_rules = array_get($field_config, 'validate')) { | |
$rules["{$field_name}"] = $field_rules; | |
} | |
} | |
return $rules; | |
} | |
private function getIsOptional($value) | |
{ | |
if (array_has($value, 'co_type') && $value['co_type'] === 'section-title') { | |
return false; | |
} | |
if (!array_has($value, 'validate')) { | |
return true; | |
} | |
$validateString = $value['validate']; | |
if (strpos($validateString, 'required') !== false) { | |
return false; | |
} | |
return true; | |
} | |
private function getIsOptionalForLocale($value) | |
{ | |
if (array_has($value, 'localizable') && $value['localizable']) { | |
return true; | |
} | |
return $this->getIsOptional($value); | |
} | |
private function cleanDataFromOptionalFields($existingData, $updateData, $optionals) | |
{ | |
foreach ($optionals as $key) { | |
if (array_has($existingData, $key)) { | |
if (!array_has($updateData, $key) || !$updateData[$key]) { | |
unset($existingData[$key]); | |
} | |
} | |
} | |
$data = array_filter(array_merge($existingData, $updateData)); | |
return $data; | |
} | |
private function startsWith($haystack, $needle) | |
{ | |
return substr_compare($haystack, $needle, 0, strlen($needle)) === 0; | |
} | |
private function endsWith($haystack, $needle) | |
{ | |
return substr_compare($haystack, $needle, -strlen($needle)) === 0; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment