Skip to content

Instantly share code, notes, and snippets.

@Neophen
Created June 29, 2019 14:41
Show Gist options
  • Save Neophen/e8a96d2bc6b298b46550dec1d3b633b1 to your computer and use it in GitHub Desktop.
Save Neophen/e8a96d2bc6b298b46550dec1d3b633b1 to your computer and use it in GitHub Desktop.
A json workshop.
<?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