Append field content in another field

On my portfolio I have 2 tags systems : the “official” one, displayed for each project, not clickable and the “secret” one with direct URL vich I give to selected clients.

Example for official tags : http://judbd.com/portfolio/boulogne (after “expertise” under the title)
Example of hidden tags : http://judbd.com/view/filter:coolstuff (the tag is “coolstuff”, wich doesn’t appears anywhere)

Now I want to populate the “secret” tags with some of the “official” one, is there a way to append automatically the content of the “secret tags” with the “official one” ? Maybe something not permanent, but just one time to avoid the massive copy/paste on online projects.

thanks.

How do you define “with some tags” here?

Even easier would be to include all “official” tags dynamically while filtering for the “secret” ones. Could you please post the section of your code where you are filtering the portfolio based on the “secret” tag in the URL?

yep, it’s in the view.php controller :

  // add the filter
  if(!empty(param('filter'))) {
    $filter = param('filter');
    $projects = $projects->filterBy('filter', $filter, ',');
  } else {
    $projects = new Pages(array($projects_portfolio_featured, $projects_side_featured));
  }
  return compact('projects', 'filters', 'filter');

I’m not sure to understand your solution, but i’m just trying to copy/append the fields for working on it later (just to have tags pre-filled in back office)

What is the field called that contains the “official” tags?

Oh Ok sorry, it’s “job”

Then you could use the following code to get all projects that have a matching tag in either field:

  // add the filter
  if(!empty(param('filter'))) {
    $filter = param('filter');
    $projects = $projects->filter(function($project) use($filter) {
      // check if one of the fields contains the tag
      if(in_array($filter, $project->filter()->split(','))) return true;
      if(in_array($filter, $project->job()->split(','))) return true;
      
      // neither field contains the tag
      return false;
    });
  } else {
    $projects = new Pages(array($projects_portfolio_featured, $projects_side_featured));
  }
  return compact('projects', 'filters', 'filter');

Thanks, but I’m not sure to understand what the code will do. Do you have an example with 2 URL and their behaviour ?

It will display all the project with official “UX” tag in URL for example, and also with secret “coolstuff” tag that’s it ?

If it’s correct, the problem is that I don’t want to show all “UX” projects, and maybe show projets not publicly tagged “UX” as UX projects (sometime it’s not UX project per se but plays nice in a UX collection). That’s why I have this “secret tags” system.

But as my portfolio is online and filled with project, and a lot of them needs to bee tagged “UX” or whatever, I was thinking that it’s more easy to duplicate/append the tags and then discard the ones I don’t want on some projects.

Like run one time a copy of the field “job” in “filter” (without erasing the existing content in "filter) for the existing projects. Starting from here, I’ll just do it manually for each adding.

I keep jour code snippet, it can be useful for other tag system.

My solution includes the official tag automatically when searching in the secret system. So if you go to http://judbd.com/view/filter:ux, you get every project that has the UX tag, either in the official tags or the secret tags. Every “official” UX project will then be listed automatically, and you can add other projects by adding the “UX” tag to their “secret” tags field.

If you want to copy the tags, you can use the update method with something like this:

<?php

foreach(page('portfolio')->children() as $project) {
  $secret = $project->filter()->split(',');
  $official = $project->job()->split(',');
  $new = implode(', ', array_unique(array_merge($secret, $official));  

  $project->update(array('filter' => $new));
}

Please make sure to only run this code once and also to delete the code after you are done to prevent unexpected things from happening.

But as I wrote, the code I posted in my previous post should work just fine for this without the need to duplicate the tags.

Seems that @judbd does not want to include all projects of the officially tagged collection in the filtered collection …

Also, if you copy all tags, you will have to manually remove then non-wanted ones from the secret tags again, so the question is if it is faster to copy all tags and then remove manually; or just add them manually …

Also, if you copy all tags, you will have to manually remove then non-wanted ones from the secret tags again, so the question is if it is faster to copy all tags and then remove manually; or just add them manually …

Yes, I’m aware of this, and I think that it’s easier this way (remove a couple of tags in a second time).

My solution includes the official tag automatically when searching in the secret system. So if you go to http://judbd.com/view/filter:ux, you get every project that has the UX tag, either in the official tags or the secret tags. Every “official” UX project will then be listed automatically, and you can add other projects by adding the “UX” tag to their “secret” tags field.

Maybe my solution is too complicated and this on will do the trick. I will start by that solution, and see if I have a lot of use cases when I don’t want to filter an officialy tagged project. Maybe the simpler is to remove the tag, if I can add it secretly, wich is the case in your code @lukasbestle .

In your solution, what happens if a tag is tagged UX in official and secret system ?

If you want to copy the tags, you can use the update method with something like this:

Where I copy this code ? How I execute it only one time ? I just copy it in an new php file, access it one time and then delete it ?

Thank you !

OK I remember why I can’t implement @lukasbestle solution : because a lot projects are hidden (mostly for legal reasons) but well tagged(official system) and I want to keep the expertises tags when I show the project single page (with direct URL) but I absolutely don’t want them to show when It’s a filtered view (but I want to keep the ability too show other hidden projects in filtered view).

That’s why I have a double tag system.

In short “job” is just here to list expertises on a project and NOT for filtering, but still there are au lot fo “job” tag that can be a filter.

I will try the copy/append code.

You can put the tags copy code to any template, access a page that uses the template one time and the revert it again.

OK cool thanks. I will add Visible() at the start of the code so this will not copy the tags in invisible projects (I’ll do it manually later, it will be simpler as I can filter case by case for hidden projects)

@lukasbestle I was wondering if I can’t simply use your solution as shown in Append field content in another field but only with the visible projects when filtered with “official” tags.

I made this:

 // add the filter
  if(!empty(param('filter'))) {
    $filter = param('filter');
    $projects = $projects->filter(function($project) use($filter) {
      // check if one of the fields contains the tag
      if(in_array($filter, $project->filter()->split(','))) return true;
      if(in_array($filter, $project->job()->split(',')) && $project->isVisible()) return true;
      
      // neither field contains the tag
      return false;
    });
  } else {
    $projects = new Pages(array($projects_portfolio_featured, $projects_side_featured));
  }
  return compact('projects', 'filters', 'filter'); 

I think it’s working, I have to test it further to see if there is no side effects and if displayed projects are good.

Also, I need to make the tags non case sensitive in url, and url-friendly (ux = UX and tags with accents)

That’s no problem:

  // add the filter
  if(!empty(param('filter'))) {
    $filter = str::slug(param('filter'));
    $projects = $projects->filter(function($project) use($filter) {
      // split tags and convert to lowercase
      $secretTags   = array_map('str::slug', $project->filter()->split(','));
      $officialTags = array_map('str::slug', $project->job()->split(','));
      
      // check if one of the fields contains the tag
      if(in_array($filter, $secretTags)) return true;
      if(in_array($filter, $officialTags) && $project->isVisible()) return true;
      
      // neither field contains the tag
      return false;
    });
  } else {
    $projects = new Pages(array($projects_portfolio_featured, $projects_side_featured));
  }
  return compact('projects', 'filters', 'filter');

OK I was trying to mess with url decode/encode but str:slug helper seems cooler :slight_smile: Thanks!

I have just another little question @lukasbestle because i’m struggling with str_slug

In the portfolio page I was testing a classic tag system with this code (simple, just filter out the project tagged on the page) :

	 // add the filter
	if(!empty(param('expertise'))) {
		$filter = param('expertise');
		$projects = $projects->filterBy('job', $filter, ',');
	}

Wich is working nice if I type manually the URLs with correct case/accent, but when I try to set this up with links (and str::slug), it fails miserably and I can’t figure why.

Links:

<a href="<?php echo url($page->uri().'/expertise:'.str::slug($expertise))?>">

Filter (with slug):

 // add the filter
if(!empty(param('expertise'))) {
	$filter = str::slug(param('expertise'));
	$projects = $projects->filterBy('job', $filter, ',');
}

Returns 0 projects.

I also tryed with the str::slug in $projects = $projects->filterBy('job', str::slug($filter), ','); without succes.

Also, another problem shows up : If I want a link on each tag, I have to do a foreach on tags, and that means that I have a comma after each one, even at the end (like : Direction Artistique, Identité, UX, ) is there a better solution without manipulating array to have nice tags (like the native function) but with links on it ?

Thanks.

In fact i’m not even sure I need slug as the URLs/filters seems to work without it, even with accents and diacritics.
I also discovered url::paramsToString in the documentation : https://getkirby.com/docs/solutions/blog/tagswith tags cloud examples

Lol i’m so lost right now, and I also have a headache. :smile:

The issue is that you “sluggify” the parameter, but the param is checked against the raw tags. You need to sluggify them as well:

// add the filter
if($filter = param('expertise')) {
  $projects = $projects->filter(function($project) use($filter) {
    $tags = array_map('str::slug', $project->job()->split(','));
    return in_array($filter, $tags);
  });
}

No, you don’t. But you wrote above that you would like to have case-insensitive and url-friendly tags. If the “real” tags are fine for you, then just use them and don’t sluggify the tags. :slight_smile:

I generally don’t output commas at all and use an <ul> with a <li> for each tag. The commas can then be inserted using CSS:

.tags li:not(:last-child):after {
  content: ', ';
}

That’s useful if you have multiple params. It also makes sure that the resulting URL works on both Windows and Linux servers. But you don’t have to use that.

1 Like

Yes because I thought that it’s the right thing to do, but I’m not sure is still relevant. What are the pros and cons ? I thought clean URL without space and accent were better but browser add %20 etc by themselves and the filter works. So maybe it’s better to not touch anything, I don’t know what the best solution is.

The issue is that you “sluggify” the parameter, but the param is checked against the raw tags. You need to sluggify them as well

I though I’d sluggify them with my str::slug in my code. Why this doesn’t work ? (I tried to pley it like urldecode/urlencode

Thanks for your patience and pedagogy