Skip to content

Commit

Permalink
Merge pull request #1024 from kzrnm/feature/#1020
Browse files Browse the repository at this point in the history
Make setter of `Url.Query` independent of SearchParams
  • Loading branch information
FlorianRappl committed Dec 11, 2021
2 parents 667ca54 + 2455fcb commit c3b5898
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 41 deletions.
14 changes: 14 additions & 0 deletions src/AngleSharp.Core.Tests/Urls/UrlApi.cs
Expand Up @@ -147,6 +147,20 @@ public void UrlParamsAreLive()
Assert.AreEqual("foo=bar", url.Query);
}

[Test]
public void UrlQueryDoesNotDependOnParams()
{
var url = new Url("https://florian-rappl.de?qxz=bar");
Assert.AreEqual("bar", url.SearchParams.Get("qxz"));
Assert.AreEqual(true, url.SearchParams.Has("qxz"));
Assert.AreEqual(null, url.SearchParams.Get("foo"));
url.Query = "foo";
Assert.AreEqual(null, url.SearchParams.Get("qxz"));
Assert.AreEqual(false, url.SearchParams.Has("qxz"));
Assert.AreEqual("", url.SearchParams.Get("foo"));
Assert.AreEqual("foo", url.Query);
}

[Test]
public void UrlSearchAssigningStringWithoutQuestion()
{
Expand Down
11 changes: 8 additions & 3 deletions src/AngleSharp/Dom/Url.cs
Expand Up @@ -393,7 +393,7 @@ public String Protocol
}
else
{
ParseQuery(value, 0, value.Length, true);
ParseQuery(value, 0, value.Length, true, false);
}
}
}
Expand Down Expand Up @@ -1109,7 +1109,7 @@ private Boolean ParsePath(String input, Int32 index, Int32 length, Boolean onlyP
return true;
}

private Boolean ParseQuery(String input, Int32 index, Int32 length, Boolean onlyQuery = false)
internal Boolean ParseQuery(String input, Int32 index, Int32 length, Boolean onlyQuery = false, Boolean fromParams = false)
{
var buffer = StringBuilderPool.Obtain();
var fragment = false;
Expand Down Expand Up @@ -1137,7 +1137,12 @@ private Boolean ParseQuery(String input, Int32 index, Int32 length, Boolean only
}

_query = buffer.ToPool();
_params?.ChangeTo(_query);

if (!fromParams)
{
_params?.ChangeTo(_query, true);
}

return fragment ? ParseFragment(input, index + 1, length) : true;
}

Expand Down
83 changes: 45 additions & 38 deletions src/AngleSharp/Dom/UrlSearchParams.cs
Expand Up @@ -17,14 +17,7 @@ public class UrlSearchParams
#region Fields

private readonly List<KeyValuePair<String, String>> _values;
private Boolean _reflow;

#endregion

#region Events

internal event Action<String>? Changed;

private readonly Url? _parent;
#endregion

#region Constructors
Expand All @@ -35,50 +28,47 @@ public class UrlSearchParams
[DomConstructor]
public UrlSearchParams() => _values = new();

internal UrlSearchParams(Url parent) : this(parent.Query ?? String.Empty) => Changed += qs =>
internal UrlSearchParams(Url parent) : this(parent.Query ?? String.Empty)
{
_reflow = true;
parent.Query = qs;
_reflow = false;
};
_parent = parent;
}

/// <summary>
/// Creates a new instance filled from the provided string.
/// </summary>
[DomConstructor]
public UrlSearchParams(String init) : this() => ChangeTo(init);
public UrlSearchParams(String init) : this() => ChangeTo(init, false);

#endregion

#region Methods

internal void Reset() => _values.Clear();

internal void ChangeTo(String query)
internal void ChangeTo(String query, Boolean fromParent)
{
if (!_reflow)
Reset();

if (query is "")
{
return;
}

foreach (var pair in query.Split('&'))
{
Reset();
var kvp = pair.Split('=');

if (query is "")
if (kvp.Length > 1)
{
return;
AppendCore(Decode(kvp[0]), Decode(kvp[1]));
}

foreach (var pair in query.Split('&'))
else
{
var kvp = pair.Split('=');

if (kvp.Length > 1)
{
Append(Decode(kvp[0]), Decode(kvp[1]));
}
else
{
Append(Decode(pair), String.Empty);
}
AppendCore(Decode(pair), String.Empty);
}
}

RaiseChanged(fromParent);
}

/// <summary>
Expand All @@ -88,9 +78,14 @@ internal void ChangeTo(String query)
/// <param name="value">The value of the param.</param>
[DomName("append")]
public void Append(String name, String value)
{
AppendCore(name, value);
RaiseChanged(false);
}

private void AppendCore(String name, String value)
{
_values.Add(new KeyValuePair<String, String>(name, value));
RaiseChanged();
}

/// <summary>
Expand All @@ -99,9 +94,14 @@ public void Append(String name, String value)
/// <param name="name">The name of the param.</param>
[DomName("delete")]
public void Delete(String name)
{
DeleteCore(name);
RaiseChanged(false);
}

private void DeleteCore(String name)
{
_values.RemoveAll(p => p.Key == name);
RaiseChanged();
}

/// <summary>
Expand Down Expand Up @@ -139,15 +139,15 @@ public void Set(String name, String value)
if (Has(name))
{
var index = _values.FindIndex(p => p.Key == name);
Delete(name);
DeleteCore(name);
_values.Insert(index, new KeyValuePair<String, String>(name, value));
}
else
{
Append(name, value);
AppendCore(name, value);
}

RaiseChanged();
RaiseChanged(false);
}

/// <summary>
Expand All @@ -157,7 +157,7 @@ public void Set(String name, String value)
public void Sort()
{
_values.Sort((a, b) => a.Key.CompareTo(b.Key));
RaiseChanged();
RaiseChanged(false);
}

/// <inheritdoc />
Expand Down Expand Up @@ -210,7 +210,14 @@ private static String Decode(String value)
return sb.ToPool();
}

private void RaiseChanged() => Changed?.Invoke(ToString());
private void RaiseChanged(Boolean fromParent)
{
if (!fromParent)
{
var qs = ToString();
_parent?.ParseQuery(qs, 0, qs.Length, true, true);
}
}

#endregion
}
Expand Down

0 comments on commit c3b5898

Please sign in to comment.